Developer/2000

Strategies for Forms Cross-UI Deployment

Table of Contents


INTRODUCTION
DEVELOPMENT STRATEGIES
SINGLE SOURCE LOWEST COMMON DENOMINATOR DEVELOPMENT
MULTIPLE SOURCES DEVELOPMENT
SINGLE SOURCE DYNAMIC MODIFICATION DEVELOPMENT
REUSABILITY TECHNIQUES
DRAG-AND-DROP OBJECT REUSE
PROPERTY CLASS
OBJECT GROUP
TEMPLATE FORM
PL/SQL LIBRARY
DATABASE STORED PROCEDURE
PORTABILITY ISSUES AND SOLUTIONS
COORDINATE SYSTEM
MONITORS
PLATFORM-SPECIFIC FEATURES
UI WIDGETS
FONTS
COLORS
MENU
TOOLBAR
WINDOWS
LOV
PROGRAMMATIC INTERFACES
MISCELLANEOUS
CONCLUSION

Introduction

In today's computing world, it is not uncommon to work in a heterogeneous environment which uses a multitude of different machines with a plethora of different user interfaces (UI). For example, an ordering system may need to be run on MS Windows in the branch offices, and on character-mode terminals in the warehouse where the order is fulfilled. The developers, on the other hand, may develop the system on Motif. The need for cross-platform and cross-UI application development and deployment is very evident in today's computing environment.

Developer/2000 Forms 4.5 allows you to develop an application, and then re-generate and run that same application on a multitude of platforms without a single change to the source application. On each platform, the application will be displayed using that platform's native widgets, giving the unique look-and-feel of that platform.

However, there are differences in the capabilities of the different environments, as well as differences in the expectations of the users on various platforms, which can cause problems when moving applications between user interfaces.

This paper examines various portability issues, describes the different development strategies for writing portable applications to run on MS Windows, Macintosh, Motif and character-mode terminals, and describes some techniques to create a UI standard and to maximize reusability of your code.

Development Strategies

With the inherent hardware and UI differences, our goal is to deliver applications that users on different platforms will accept and enjoy using, thereby raising their productivity.

However, this could potentially be a non-trivial task and may involve some of the tradeoffs below.

  • Do you want the application to look exactly the same on all deployment platforms?
  • Do you want to maintain multiple sources of your application in order to achieve the highest level of resemblance to applications created natively on each deployment platform?
  • Do you want to keep a single source of your application and deliver a reasonably good-looking application on each deployment platform?

There are three strategies you can follow when writing portable applications.

  • Single Source Lowest Common Denominator Development
  • Multiple Sources Development
  • Single Source Dynamic Modification Development

These are described in more detail in the following sections. You can also use a combination of the above methods to suit your needs.

You should also bear in mind the issues discussed in the section “Portability Issues and Solutions”.

Single Source Lowest Common Denominator Development

You can use this method to create applications that look exactly the same on all platforms. Before you start to develop your application, you need to know in advance the deployment platforms and use only those capabilities that are available on all those platforms.

Depending on the particular deployment platforms, you may not be able to use some of the following port-specific features in Forms:

  • OLE (Object Linking and Embedding)
  • VBX (Visual Basic Controls)
  • DDE (Dynamic Data Exchange)
  • ORA-FFI (Oracle Foreign Function Interface)
  • MDI Window and Toolbar
  • Images
  • Host Commands
  • User Exits
  • Boilerplate Drawings
  • Proportional Fonts

This approach is not ideal for the following reasons.

  • If character-mode is one of the deployment platforms, this approach will severely limit the functionality you can provide in your application. The resulting application may be unacceptable to users on the other platforms.
  • Any change in the deployment platforms in the future may render some part of the application obsolete when that feature is not supported on the newly added platform.

Multiple Sources Development

With this method, the deployed application looks like it has been created on that specific deployment platform. The goal is to reuse as much of the logic in the base application as possible, while changing the UI to look exactly like a natively built application.

To achieve this, you should use the following steps.

  • Create the base application, using the reusability techniques discussed in the section “Reusability Techniques”.
  • For each deployment platform, copy/reference the application objects to reuse the base application as much as possible.
  • Modify the application to look exactly like one that is created natively on each deployment platform.

The main disadvantage of this approach is similar to maintaining different copies of the source application although the effort is greatly reduced with the use of the reusability techniques.

The advantage is that the users of each platform will get to use an application which looks native for each UI, with the features that they are accustomed to. It also means that they would not be susceptible to any performance implications at startup that the Single Source Dynamic Modification method may be.

Single Source Dynamic Modification Development

This approach avoids the disadvantages of the previous two methods, while still delivering pleasant-looking applications on each deployment platform. You can achieve this by:

  • Dynamically Modifying the Application
  • Re-Referencing Port-Specific Implementation

Dynamically Modifying the Application

Forms provides a built-in, get_application_property, to determine the UI at runtime. Depending on the UI, you can dynamically

  • hide objects that are not available on that deployment platform
  • reposition other objects to take up that space
  • alter the attributes of an object to suit the standards on that deployment platform

The details are discussed in the section “Portability Issues and Solutions”.

Re-Referencing Port-Specific Implementation

Users on different deployment platforms are accustomed to a specific standard in their applications. The goal is to be able to pick up the port-specific functionality for each deployment platform.

The architecture shown in the following figure can be achieved using the steps below.

  • Create a separate repository of standards and objects for each deployment UI (Window.fmb, Motif.fmb, Mac.fmb and Charmode.fmb in the figure). Similarly, port-specific code should be put in separate libraries (Window.pll, Motif.pll, Mac.pll and Charmode.pll in the figure). Refer to the section “Reusability Techniques” for more details on the Forms features that can help you in the creation of standards, and reusable objects and code.

Figure 1 Architecture for Re-Referencing Port-Specific Implementation

  • Code each UI repository and library to handle the application objects in the ideal manner for that particular UI.
  • Create your application, making references to the standards and objects in the repository, and using the port-specific code in the library.
  • To pick up the port-specific implementations, copy the port-specific repository and library to the common name (Porting.fmb and Porting.pll in the figure) on each platform and re-generate.

The advantage of this approach is being able to deliver port-specific functionality while maintaining a single source for your application.

Reusability Techniques

Forms provides many features that help you implement the strategies described above. The following are the techniques detailed in this section to enable you to develop and test objects and code once, and reuse them in all your applications.

  • Drag-and-Drop Object Reuse

Reuse individual objects and triggers that have already been tested.

  • Property Class

Deliver applications that conform to your UI standards on different platforms using property classes.

  • Object Group

Create entire reusable applications using object groups.

  • Template Form

Ensure that your developers have all the necessary reusable objects by putting the libraries, object groups, property classes and color palette in a template form.

  • PL/SQL Library

Encapsulate and protect your developers from the implementation details with the use of PL/SQL libraries by providing an API (Application Programming Interface) for reusable code.

  • Database Stored Procedure

Reduce network traffic and improve the performance of your application by moving code that need not be executed on the client to the server.

Drag-and-Drop Object Reuse

Objects and triggers can be encapsulated within a source module and reused by other applications.

First, you need to create the objects and store them in a form module. To reuse the object, you simply drag and drop it into the destination module. When reusing objects, you have two choices.

  • Copy

When you copy an object, it is incorporated into the target module immediately and does not maintain a link to the source object. Thus, any subsequent changes to the source object do not affect the target object and the target object can be modified to suit the needs of the target module.

  • Reference

When you reference an object, a link to the source object is incorporated into the target module. Any changes made to the source object will be picked up when the target module is subsequently opened or generated. Since the reference is resolved at generate time, using this feature will not incur additional overhead at runtime.

Property Class

A property class is a named list of properties and triggers. Once defined, it can be applied to any object in your application. The object will then inherit all the properties and triggers that make sense for it.

Property classes can inherit properties and triggers from other property classes, thus giving you multi-level inheritance. Using this feature, you can create a hierarchy of property classes, with the more specific property classes inheriting from the more generic property classes. You can then apply these property classes to objects in your application. Any change to the property classes will then be propagated to the property classes and objects that make use of them.

For example, you can create property classes for all the UI widgets according to your UI standard so that your application will have the same look-and-feel.

Using the same architecture as in the section “Re-Referencing Port-Specific Implementation” as shown in the figure below, you can place generic property classes (UI attributes that apply across platforms) at the lowest level, and the port-specific attributes customizing the generic property classes in the port-specific repositories. Your application will pick up the UI standard you define for each platform when you use the port-specific property classes.

Figure 2 Architecture for Creating UI Standards and Reusable Objects

Object Group

With drag-and-drop object reuse, you can only reuse one object at a time. Object groups allow you to encapsulate a number of objects and triggers into a reusable component.

For example, you may have a calendar application that can be used by other applications. Instead of referencing each object in the calendar application separately, you can put all the objects and triggers in the calendar application into an object group, and simply drag and drop this object group into your target module.

This has the following two advantages:

  • Productivity

These object groups are already built and tested by the original creator. You simply drag the group into your application and enjoy the use of a bug-free component.

  • Error-free

If you had to remember which objects are required by the reusable application and drag those into your application one at a time, there is a high chance that you may omit some objects. The original creator knows exactly the objects that make up the reusable application and would be able to create the object group without any error. As a result, you will be able to make use of the reusable application with minimal effort and error.

Using the architecture shown above, you can base your objects in the object groups on the port-specific property classes and libraries so that the port-specific implementation will be picked up.

Template Form

Before you start developing your application, you should define a UI standard so that your application has the same look-and-feel throughout. This will increase its acceptance by your end users.

You can define a template form that has all the attached libraries, object groups, property classes, and color palette needed by your developers. When they need to create a new form module, they simply open the template form and save it with a different name. This ensures that your application can be developed according to your UI standards.

PL/SQL Library

A PL/SQL library is a collection of PL/SQL program units (packages, procedures and functions) that can be attached to any form module. Once attached, these program units can be used in the same way as if they are defined directly in that form module.

This has the advantage of encapsulating the implementation details from the users of the library because they will only need to know the API (Application Programming Interface). This feature is an effective way of reusing code and protecting the developers from the implementation of the provided code.

Database Stored Procedure

A stored procedure is a collection of PL/SQL code which is resident on the server and can be called from a Forms application, with data being passed between the application and the procedure.

For example, you may need to perform an analysis of some data residing on the server and then display that on the form. This analysis may involve a large amount of SQL interaction with objects in the database. If the work was done on the client, data would be continually passed back and forth between the client and the server to resolve the analysis. By performing the task as a database procedure on the server, we can avoid this network traffic and thus greatly improve performance.

This also has the advantage that this piece of analysis code can then be reused by other parts of your application.

Portability Issues and Solutions

Before writing any portable application, there are many issues you need to consider.

  • Coordinate System

Should you use the real or character coordinate system when creating your application and how does it affect object sizes and layout?

  • Monitors

Monitors of different sizes and resolutions may be used by your users. How should you create your application so that it looks good on different monitors?

  • Platform-Specific Features

How can you still include port-specific features like VBX and OLE in your application when some of your deployment platforms do not support them?

  • UI Widgets

There are several issues with various UI widgets.

  • On character-mode, users do not have the use of a mouse. This makes navigating to buttons extremely cumbersome.
  • On Macintosh, users will not be able to navigate to anything except text items.
  • On Motif, the moat of a button is very big compared to that on other platforms.
  • Icons used for iconic buttons are not portable. You should also be aware that some icons have special meanings on certain platforms.
  • Bevels are not supported on the Macintosh and character-mode platforms.

With these differences, how can you create an application that provides similar functionality in all your deployment platforms?

  • Fonts

There are a number of issues regarding the use of fonts in a heterogeneous environment.

  • Different fonts exist on different platforms.
  • The same fonts can have different names on different platforms.
  • Users are accustomed to specific fonts on a specific platform.

How can you deliver an application that will be accepted by users on different platforms?

  • Colors

Similar to the font issues, different platforms support different colors and the same color does not always look the same on all platforms. In addition, widgets on MS Windows can only take one of sixteen colors defined in the system color palette. Moreover, you may also see the effect of color washing when displaying several high-colored images simultaneously.

How can you use colors effectively to create a good-looking application that can be deployed on several platforms?

  • Menu

Some platforms display the menu in the MDI window while others display the menu in each window in your application. How can you adjust your window sizes to accommodate the difference?

  • Toolbar

Some platforms allow the toolbar to be attached to the MDI window while others can only attach the toolbar to a specific window in your application. How can your window sizes be adjusted to accommodate the difference?

  • Windows

In a similar fashion, message and status lines are displayed in the MDI window on some platforms but in the console window on other platforms. Again, how can the window sizes be adjusted accordingly?

In addition, on character-mode, there are only 80x24 cells on the screen and the users cannot reposition the window with a mouse. How should you develop your application with these constraints?

  • LOV

On character-mode, List of Values (LOV) cannot be moved using the mouse.

  • Programmatic Interfaces

How can you make use of host commands and user exits (requiring port-specific code) while writing portable applications?

  • Miscellaneous

There are various other issues that should be considered.

  • Path names are specified differently on various platforms.
  • Some platforms restrict file names to eight characters while others have case-sensitive file names.
  • Messages like “Hit the F1 key for help” will not be portable.

The following sections describe these portability issues in more detail, as well as the solutions to help you build applications that would be easily accepted by users of different platforms.

Coordinate System

You can work in two different coordinate systems when building your applications. The selection of the coordinate system depends on whether one of your deployment platforms is character-mode terminals.

If you are only deploying on GUI terminals, you should use the Real Inch or Real Point coordinate system to lay out your application objects. This allows you to size your objects to the exact shape you want instead of being snapped to the nearest character cell size.

Since the pixel size differs on screens with different resolution, Real Pixel is not recommended because your objects' sizes and positions will change according to the deployment screen resolution. For example, all your objects will shrink proportionally when displayed on a screen with higher resolution and this may be too small for the user to work effectively.

If character-mode is one of your deployment platforms, you should use the Character coordinate system and turn on the grid snap. This will ensure that your application objects' sizes are in multiples of the character cell size, and are laid out correctly in character cell units.

In order to lay out your objects accurately, there are two different settings you need in the designer.

  • Set the form's coordinate system to character, turn off Default Font Scaling, and set the size of the character cell. This character cell size is in pixels, and will be used as the base unit for all your objects.
  • Set the character cell size of the ruler setting to match that of the coordinate system. This character cell size is in points.

Since the pixel is dependent on the screen resolution and there are 72 points per inch, you need to perform some calculation to get an equivalent value for each setting.

With the character cell size in pixels, this method has the same problem as using the Real Pixel coordinate system in that your objects will be scaled according to the screen resolution. You can turn on Default Font Scaling after laying out your objects so that they will be scaled according to the font specified in FORMS45_DEFAULTFONT.

The advantage of this is that you can control your objects' sizes independently of your application. There are two issues in this approach:

  • You may need a separate set of icons for your iconic buttons because they will also be scaled and your icons may not fit them exactly.
  • You need to use display items for your boilerplate text because boilerplate text is not controlled by FORMS45_DEFAULTFONT.

Monitors

Physical real-estate varies across platforms. Even on the same platform, monitors of different sizes and resolutions can be used. You should know in advance what kinds of monitors are used in the deployment platforms and design your application windows using the smallest screen size.

Aspect ratio is the width-to-height ratio of an object. When porting to different GUI terminals, the only guarantee is that the aspect ratio of your objects is constant because not all monitors display sizes correctly.

This is a problem on MS Windows because the PC architecture is not capable of determining the screen resolution and the underlying video driver may not be giving the correct information about the screen resolution. As a result, an inch may not always be an inch on MS Windows. Since Forms depends on the underlying video driver for screen resolution information, there is nothing you can do to prevent this.

On the Macintosh, the screen resolution is always 72 dpi (dots per inch). To display more objects on the screen, a bigger monitor has to be used. On UNIX, the operating system is able to determine the resolution of the monitor accurately, thus this problem will not occur.

Platform-Specific Features

Due to their popularity, Forms provides certain features that are platform-specific. For example, OLE 2.0 is available on MS Windows and Macintosh, and VBX 3.0 is only available on MS Windows. Character-mode terminals will not be able to display graphical objects like circles and charts, etc.

If you choose to use these features, you should ensure that the application does not rely on having them on all the deployment platforms. For example, if your users at the goods warehouse are using character-mode terminals and the customer service representatives are using GUI terminals, then you can use images in your application so that the customer service representatives can show their customers what the products look like while the warehouse operators can perform their tasks without that functionality.

While images are not displayed on a character-mode terminal automatically, OLE and VBX objects have to be hidden if you do not want your users to see their placeholders on platforms that do not support them. There are two ways to achieve this:

  • You can put these objects in a separate window invoked either from the menu or a button, and dynamically enable/disable the menu item or button.
  • You can hide/show the port-specific objects and reposition other objects to take their place programmatically using the following code fragment.

WHEN-NEW-FORM-INSTANCE trigger:

declare

ui varchar2(15);

begin

ui := get_application_property (user_interface);

if ui = 'CHARMODE' or ui = 'MOTIF' then

set_item_property ('VBXOBJECT1', displayed, property_false);

set_item_property ('OLEOBJECT1', displayed, property_false);

set_item_property ('TEXTITEM1', position, 43, 4);

end if;

end;

if ui = 'MACINTOSH' then

set_item_property ('VBXOBJECT1', displayed, property_false);

set_item_property ('TEXTITEM1', position, 43, 4);

end if;

You would also need to code the KEY-NEXT and KEY-PREVIOUS triggers to skip over those hidden items. Since boilerplate text cannot be repositioned dynamically, you will have to use display items for your boilerplate instead.

The first method is preferred because the application will look the same on all platforms and it is simpler to enable/disable a menu item or button than reposition the other objects in the application.

UI Widgets

This section describes issues pertaining to the various UI widgets.

General

On character-mode, all the UI widgets are rendered in their character-mode equivalents. For example, a button is displayed as (Query), using the button's label and two more characters for the parentheses. As a result, you have to ensure that the widgets have sufficient space to display themselves entirely. On other platforms, they will be rendered using those platforms' native widgets.

On character-mode, since the users do not have the use of a mouse, you should ensure that your application does not rely on mouse navigation. Thus, item ordering is very important in your application, and you should study the work flow of your users and order the application objects accordingly. As a case in point, ensure that all your buttons have equivalent hot keys and their functionality can be invoked using the menu.

On Macintosh, users will not be able to navigate to anything except text items. Your application should not rely on being able to navigate to all objects.

Buttons

When building applications for GUI platforms, it is very easy to create a button palette that applies to all blocks. However, this does not work well in a character-mode environment where the user needs to navigate to the button because it would then have lost the context with which to work with. The possible solutions are:

  • Define hot keys for your buttons, use a global variable to track the last cursor item, and navigate to that item before performing the operation. However, this has the disadvantage of causing any navigational triggers for that item to fire again.
  • Do not make the button palette available in character-mode but make your users use the menu instead.

The dimensions of a button include the moat (the emphatic border around a button to designate a default button) regardless of whether it is the default button. On MS Windows, this moat is very small compared to that on Motif. Therefore, you will find that the buttons shrink when run on Motif.

You can reduce this moat by copying the Tk2Motif file to your home directory and setting the Tk2Motif*expandNonDefaultButtons property to true. The following figure shows the effect of this setting.

Figure 3 Reducing the Moat on Motif Buttons

Icons are platform-specific. If you use iconic buttons in your application, you will need a separate set of icons for each platform. Icon design is a time-consuming process and you need to be aware that certain icons have special meanings on certain platforms. For example, the trash can on the Macintosh has a specific functionality attached. In this case, you will not want to use this for some other purpose.

To ease the porting process, you should use the same names for the icons on each platform and set the respective environment variables to point to the icon directory. On MS Windows and Motif, this variable is TK21_ICON. You should refer to the Installation Guide for your platform for the specific environment variable for other platforms.

On character-mode, iconic buttons will be displayed using the buttons' labels. You should ensure that iconic buttons have meaningful labels and have sufficient space to display them.

Since objects below the 24th line on the character-mode screen is not visible to the user, you can also place these iconic buttons below the 24th line so that your GUI terminals users can enjoy that functionality while your character-mode users will not see them but be able to invoke their functionality through the menu.

Bevels

Bevels are not available on Macintosh and character-mode terminals. You should not assign a meaning to an object based on its bevel attribute if you are using these platforms.

On MS Windows, there is a known positioning problem when porting between VGA and SVGA screens as shown in the figure below. The two lines which are just touching each other on VGA will overlap when displayed on SVGA. Use of the bevel attribute is encouraged because it does not present this problem.

Figure 4 Effect of Positioning Problem When Porting Between VGA and SVGA

Fonts

There are a number of issues regarding the use of fonts in a heterogeneous environment.

  • Different fonts exist on different platforms.
  • The same fonts can have different names on different platforms.
  • Users are accustomed to specific fonts on a specific platform.

There are two ways you can resolve this:

  • Defining font aliases
  • Defining port-specific property classes

Defining Font Aliases

Font aliasing allows you to substitute one font for another when porting your applications. Developer/2000 comes with a default font alias file for each platform. You can customize this file to suit your needs. The entries in this file are of the following format:

source_font = destination_font

You can substitute the face, size, weight and style of each font in your application. Two very simple examples are given below.

Porting from MS Windows to Motif changing all MS Sans Serif font to Helvetica font:

“MS Sans Serif”=Helvetica

Porting from MS Windows to Macintosh changing all MS Sans Serif 10-point font to Geneva 12-point font:

“MS Sans Serif”.10=Geneva.12

The font alias file gives the exact syntax for defining the aliases, as well as some comments to describe how it is used in more detail. On MS Windows, this file is found in the \orawin\cde2 directory. You should refer to the Installation Guide for the location of this file on other platforms.

This approach is very simple. For example, it is very useful if you want to enable all objects using MS Sans Serif 10-point font on MS Windows to use Helvetica 9-point font on Motif in your application.

However, if both your poplist and text items are using MS Sans Serif 10-point font on MS Windows, but you want your poplist and text items to use different fonts on Motif, you should use the next approach which provides you with that level of granularity.

Defining Port-Specific Property Classes

As discussed in the section “Re-Referencing Port-Specific Implementation”, you can define property classes according to your UI standard. You can also incorporate font information in these property classes to specify the font used for each type of object for each deployment platform.

For example, you can create property classes for poplists and text items. On MS Windows, both of these property classes would specify MS Sans Serif as the font in Window.fmb. On Motif, you can specify that the poplist property class use the Helvetica 9-point font while the text item property class use the Helvetica 11-point font in Motif.fmb.

This approach allows you to customize the font used for each class of objects in your application, providing a higher level of flexibility in choosing the desired font as compared to the previous method. As a result, you can deliver an application using the font that your users are accustomed to on each deployment platform.

Colors

Similar to the font issues, different platforms support different colors and the same color does not always look the same on all platforms. Using the technique in the section “Re-Referencing Port-Specific Implementation”, you can specify the colors to be used for each class of objects for each platform. In this way, each object in your application will take on the color that look best on each platform.

If you want to color-code certain objects in your application, you should do that redundantly. For example, if you want to show negative amounts in red, you should also precede that number with a minus sign so that users of monochrome and character-mode terminals can distinguish positive and negative numbers.

On MS Windows, widgets can only take one of sixteen colors defined in the system color palette. If you assign a color other than these sixteen colors, your widget will snap to one of the sixteen colors that is closest to the one you specify. Your application should use a color palette that includes these sixteen colors.

On monochrome displays, colors will snap to black or white. You need to be careful not to use dark colors for both the background and foreground so that they do not both get snapped to black.

On color monitors, since the color palette is only capable of displaying a certain number of colors at any point in time, color washing is seen when two applications need to display more colors concurrently than what the system's color palette can handle.

As a result, when several high-colored images are displayed simultaneously, only the one in the foreground is displayed correctly while the rest will be displayed using the color palette set by the foreground image, thereby snapping to some strange colors. To minimize this, you should limit the number of colors in your color palette so that more colors in the system color palette can be used for other displays.

In addition, studies have shown that a good user interface only uses a few colors and uses them consistently throughout the application.

Menu

MS Windows applications support Multiple Document Interfaces (MDI) where all the windows belonging to an application are contained in the application's window (also called the MDI window), and there is only one menu for the entire application. The Macintosh has a similar concept to MS Windows.

On Motif, every window has a menu attached, while the menu is always displayed on the first line of the screen on character-mode.

Due to these platform differences, the window sizes of the application need to be adjusted accordingly. This is discussed in the section “Windows”.

When an application has different menu items at the root level, the user may see the screen flash

when switching between form module windows. In order to avoid that, you can combine all the menu options into one single menu application, and use the set_menu_item_property built-in to dynamically enable/disable the respective menu items accordingly.

On character-mode, you may want to define hot keys for the commonly used menu items so that the user does not need to access the menu all the time. In addition, you should note that magic menu items like Cut, Copy and Paste are not available on character-mode.

Toolbar

On MS Windows, you can attach an MDI toolbar to your application which will be displayed in the MDI window, or you can attach a toolbar to a specified window. Again, the Macintosh uses a similar concept.

On Motif, a toolbar can only be attached to a specified window. It is not advisable to use a toolbar in character-mode due to the limited amount of screen real-estate, but enable the same functionality via the menu. This can be achieved by making all the toolbar buttons non-navigable and hiding that canvas in a WHEN-NEW-FORM-INSTANCE trigger as follows.

WHEN-NEW-FORM-INSTANCE trigger:

if ui = 'CHARMODE' then

hide_view ('toolbar');

end if;

Again, these platform differences would require that the window sizes of the application be adjusted accordingly. This is discussed in the section “Windows”.

Windows

The placement of the menu, and message and status lines varies with the deployment platform as follows.

  • On MS Windows, the menu, and message and status lines are displayed in the MDI window. The MDI toolbar is available on MS Windows and is also displayed in the MDI window.
  • Although MDI is not available on the Macintosh, Forms has simulated the behavior as seen on MS Windows.
  • On Motif, the menu is displayed in each window and the message and status lines are displayed only in the console window.
  • On character-mode, the menu is displayed on the first line of the screen and the message and status lines are displayed only in the console window.

It is recommended that you design your window without including the menu, toolbar, nor message and status lines in the window size. On platforms that differ from this standard, you can adjust the window size dynamically in the WHEN-NEW-FORM-INSTANCE trigger as follows.

WHEN-NEW-FORM-INSTANCE trigger:

adjust_window ('consolewindow', true);

adjust_window ('otherwindow');

procedure adjust_window (window_name in varchar2,

console in boolean := false,

toolbar in boolean := true) is

delta number:=0;

ui varchar2(15);

begin

ui := get_application_property (user_interface);

if ui = 'MOTIF' then

/* add space for menu, value depends on size of menu font */

delta := delta + 1;

/* add space for message and status lines */

if console = true then

delta := delta + 2;

end if;

/* add space for toolbar, value depends on size of toolbar */

if toolbar = true then

delta := delta + 1;

end if;

elsif ui = 'CHARMODE' then

/* add space for message and status lines */

if console = true then

delta := delta + 2;

end if;

/* move all windows down 2 to see window frame in character-mode */

set_window_property (window_name, y_pos,

to_number (get_window_property (window_name,

y_pos)) + 2);

end if;

if delta != 0 then

set_window_property (window_name, height,

to_number (get_window_property (window_name,

height)) +

delta);

end if;

end;

When deploying on character-mode terminals, you need to consider the following issues.

  • There are only 80x24 cells on the screen. The first line will be used to display the menu when it is invoked. The last two lines at the bottom of the console window are used to display the message and status lines. If you want to display the top and bottom of the window frame, they occupy another two lines on the screen. You should plan your screens very carefully to fully utilize the remaining space.
  • Since the user does not have the use of a mouse, you should not rely on your users being able to navigate between different forms or different windows in the application but provide buttons or menu options for navigating between forms. When the user is done with the window, you should hide the windows programmatically, or set the window's Remove On Exit property to true.
  • Since windows cannot be repositioned with a mouse, you have to ensure that the displayed window does not obscure the context required for that window.

LOV

On GUI platforms, List of Values (LOV) can be moved using the mouse. However, on character-mode terminals, the LOV is a static object. You need to ensure that the LOV does not occlude the underlying data that provides its context.

You can use the set_lov_property built-in to dynamically position the LOV in character-mode.

Programmatic Interfaces

There are a couple of ways you can write port-specific code in Forms. These will definitely require changes when porting. The following sections discussed how to make use of these features without any changes to your form modules.

Host Commands

The host command executes a port-specific operating system (OS) command. When you embed such commands in your form module, you will need to change these commands as you port your application since OS commands differ from platform to platform.

You can make your form module portable by putting all OS commands in a script file and call this file from your form module. You can then rewrite the script file for each platform and ensure that they have the same name. In this way, you can port your application without modifying your form modules.

User Exits

User exits enables you to call Third Generation Language (3GL) programs from your form module. These 3GL programs are port-specific. There are two ways to make your form modules platform-generic while using this feature.

  • Using an Application Programming Interface (API)

You can create an API for your user exits that is consistent across platforms, rewrite the 3GL programs for each platform, and re-link the user exits or replace the DLL for each platform.

  • Using C Preprocessor Directives

You can use preprocessor directives in your C programs to code port-specific functionality. Depending on the variables defined, the relevant segments of the code will be compiled.

Miscellaneous

This section lists several issues that you need to be aware of.

  • Path name

Path names vary across platforms. You should not hardcode path names in your form module but make use of environment variables to enable Forms to find your files during runtime. Your Installation Guide should have a list of these variables.

  • File Name

There are two issues regarding file names:

  • MS Windows has an eight character maximum.
  • File names on some platforms are case-sensitive.

You should ensure that your file names have a maximum of eight characters and use either uppercase or lowercase consistently.

  • Message

You should be careful not to use port-specific messages in your application. For example, a message like “Hit the F1 key for help” will not be portable.

Conclusion

With Developer/2000 Forms 4.5, you can develop an application once, and run on a multitude of platforms natively without any change to the source application. However, there are differences in the capabilities of the different environments, as well as differences in the expectations of the users on various platforms which may hinder the complete acceptance of your application on every platform.

We have discussed different development strategies for writing portable applications, together with their implications on ease of maintenance and resemblance to native applications. Forms provides many features to assist you in implementing your strategy, creating a UI standard and maximizing reusability of your code.

With the general strategy in mind, we have also examined the various portability issues, and have described solutions to resolve them.