Programmer's Guide



Chapter 16   Advanced Form Topics

This chapter provides information about the following topics:

Working with Java menus   Top of page

SilverStream supports two Java menu objects: java.awt.MenuBar and java.awt.PopupMenu. You create both of them programmatically.

Java menus support the following features:

The following sections provide more details about programming the Java menu objects and their related features.

About MenuBars   Top of page

A MenuBar is a horizontal bar that is displayed at the top of a window and consists of one or more drop-down menus (java.awt.Menu objects). When the user selects a Menu from the MenuBar, a drop-down Menu appears containing a vertical list of MenuItems and submenus (cascading menus).

The following figure shows a MenuBar object with two java.awt.Menu objects: File and View.

When the user chooses File from the MenuBar, its MenuItems Login, Logout, and Exit appear.

MenuBars are attached to a Frame window; therefore, you cannot create MenuBars in applets unless the applet pops up an independent window. It is the independent window that provides the Frame object, which contains the MenuBar.

When you create a Menu and add MenuItems to it (using the form's addMenuItem() method), SilverStream adds the Form as an ItemListener or ActionListener for the MenuItem objects.

About popup menus   Top of page

a PopupMenu is a subclass of Menu. Like Menu, it contains MenuItems. Popup menus are displayed independently of a MenuBar. The following figure shows a PopupMenu object that contains eight MenuItems.

Each operating system platform specifies a user action (such as a right click) that is a popup trigger. If you want to associate a popup menu with a control, you can test for the popup trigger in the appropriate mouse event for that control.

About java.awt.Menu and java.awt.MenuItem objects   Top of page

A Menu consists of java.awt.MenuItem objects. A menu can be a top-level menu on a MenuBar, a submenu that cascades from another menu, or a popup menu. You typically use Menu objects to group logically related MenuItems so the user can find the items. In addition to MenuItems, Menus can also contain separator bars. Separator bars are also useful for grouping logically related MenuItems.

MenuItems present the actual operation or task to the user. When the user chooses a MenuItem, the menu closes and a java.awt.event.ActionEvent or java.awt.event.ItemEvent fires, depending on the type of MenuItem that the user chooses.

Java provides two kinds of menu items: a MenuItem and a CheckboxMenuItem. CheckboxMenuItems represent a yes/no or on/off option.

A MenuItem can have a shortcut key associated with it. Shortcut keys are based on the keys defined in java.event.KeyEvent. For more information on shortcuts, see Creating text-style MenuItems and shortcut keys.

This is an example of a menu that includes text and CheckboxMenuItems and a separator bar:

Menu restrictions   Top of page

Java popup menus are available in any deployment environment. Java MenuBars, however, are only available in java.awt.Frame objects. The SilverStream AgfForm class does not extend java.awt.Frame. However, there are two deployment environments where forms run in an java.awt.Frame. They are:

NOTE   These classes are also available in the Form Designer in test mode. The popup menus behave as you would expect. However, the MenuBar object that you create for your form replaces the Form Designer's MenuBar. (Remember that you can only have one MenuBar per Frame.) When you exit test mode, the normal SilverStream menus return.

Strategies for building menus   Top of page

You can construct a PopupMenu or MenuBar object and add the desired Menu and MenuItems to it in any appropriate AgfForm event, such as formActivate. However, this might cause the formActivate event code to be quite large. To avoid this, create custom methods that build the menus. You can then call those custom methods in the formActivate event, making the formActivate (or other event) code easier to maintain.

Defining MenuBars   Top of page

These are the coding steps for creating menubars:

  1. Create the MenuBar object.

  2. Create Menu objects.

  3. Add MenuItems to the appropriate Menu object.

  4. Add the Menu objects to the MenuBar.

  5. Add the MenuBar object to the form's frame.

  6. Write code that responds to the menu events that occur when the user selects an item.

The following sections describe how to do each step. For complete sample code, see the techniques for building menus in Application Techniques.

For information about PopupMenus, see Defining PopupMenus.

Creating a MenuBar   Top of page

To create a MenuBar object, you use the java.awt.MenuBar constructor method. For example, you might create a new MenuBar object called mb as type MenuBar. Here is the code that does that

  MenuBar mb = new MenuBar(); 

You can create only one MenuBar object per Frame.

Creating Menu objects   Top of page

To create a Menu object, you use the java.awt.Menu constructor method, which takes a String label parameter. The label is the text that the menu displays as its title in the MenuBar. Here is how you create a Menu object called fileMenu. Its title is "File".

  Menu fileMenu = new Menu("File"); 

Adding MenuItems to a Menu   Top of page

A Menu can contain a combination of MenuItems, CheckboxMenuItems, and separators.

Creating text-style MenuItems and shortcut keys

To create a standard MenuItem and add it to an instantiated Menu object, you call addMenuItem(), a method of AgfForm.

The addMenuItem() method creates a MenuItem, adds it to the specified Menu, sets the label, and creates a shortcut key for the MenuItem. The addMenuItem() method also adds the AgfForm as an ActionListener for the MenuItem. When the user selects a MenuItem, the form's menuItemSelected event fires.

About shortcut keys

A shortcut key specifies a keystroke combination that the user can press at any time within the Menu's parent container. It causes the same behavior as if the user used the mouse to open the menu and select an item. The shortcut key specification corresponds to a raw key code. You can find a listing of the raw key codes in Java documentation for the java.awt.event.KeyEvent. If you don't want a shortcut for the item, specify null for the shortcut.

About separators

You can specify null for the label parameter to add a separator between items on a menu. Note that addMenuItem() ignores the shortcut parameter if the label parameter is null.

Example

This example shows how you might add menu items labeled Login, Logout, a separator, and Exit to a Menu object named fileMenu. The Exit item has a shortcut key of CTRL-F5. The MenuItems appear in the order you add them.

  loginMenuItem = addMenuItem(fileMenu, "Login...", null); 
  logoutMenuItem = addMenuItem(fileMenu, "Logout...", null); 
  fileMenu.addSeparator(); 
  exitMenuItem = addMenuItem(fileMenu, "Exit",  
     new MenuShortcut(KeyEvent.VK_F5)); 

Enabling and disabling MenuItems

In some cases, you might want to enable and disable MenuItems based on the current state of your application or the user's selection. You can enable and disable MenuItems using the setEnabled() method.

This example disables the Logout menu item, which was added in the previous example.

  logoutMenuItem.setEnabled(false); 

This is what the menu looks like when Logout is disabled.

Creating CheckboxMenuItems

To create a CheckboxMenuItem and add it to an instantiated Menu object, you call addCheckboxMenuItem(), a method of AgfForm.

Like the addMenuItem() method, addCheckboxMenuItem() instantiates a CheckboxMenuItem, adds it to the specified Menu, and registers the AgfForm as an ItemListener for it. The form's menuItemStateChanged() event fires when the CheckboxMenuItem is selected.

This example shows how you might add two CheckboxMenuItems labeled Bold and Italic to a Menu named viewMenu.

  boldCheckBoxItem = addCheckboxMenuItem(viewMenu, "Bold"); 
  italicCheckBoxItem = addCheckboxMenuItem(viewMenu, "Italic") 

Creating submenus

You might want to include submenus within a MenuBar or PopupMenu. Java does not have a special class for submenus. Instead, you create another instance of a Menu object and add that object to the parent Menu using the add() method.

The following example that shows how to add three MenuItems labeled Red, Blue, and Green to a PopupMenu called popup. It also contains a Menu object that provides access to a submenu called submenu. The submenu's label is Gray. It provides access to the MenuItems labeled Light Gray, Gray, and Dark Gray.

  // Create a popup Menu object 
  PopupMenu popup = new PopupMenu(); 
  // Add three items in the order they will appear at runtime 
  item = addMenuItem(popup, "Red", null); 
  item = addMenuItem(popup, "Blue", null); 
  item = addMenuItem(popup, "Green", null); 
   
  // Create a cascading menu 
  subMenu = new Menu("Gray"); 
  // Add three items to it 
  item = addMenuItem(subMenu, "Light Gray", null); 
  item = addMenuItem(subMenu, "Gray", null); 
  item = addMenuItem(subMenu, "Dark Gray", null); 
   
  // Add it to the popup menu as the last item 
  popup.add(subMenu); 

This is the menu that this code creates.

Adding Menus to the MenuBar   Top of page

After you have created Menu objects and added all of the MenuItems to them, the next step is to add the Menu objects to the MenuBar. You use the add() method of java.awt.MenuBar. The following example adds two Menu objects, one called fileMenu and the other called viewMenu, to a MenuBar called mb.

  mb.add(fileMenu); 
  mb.add(viewMenu); 

Menus appear on the MenuBar in the order that you add them. You can reorder them by changing their physical order in the code.

Adding the MenuBar to the window's Frame   Top of page

MenuBars can only be added to a Frame container. As described in About MenuBars, there are some situations where SilverStream forms are contained within a Frame and can therefore have a MenuBar.

To display a MenuBar, you need a reference to the frame in which the form is displayed. To get the Frame, call the getFrame() method of AgfForm. You cannot call getFrame() in the form's formLoaded event because the form doesn't have a Frame yet. Call getFrame() in the formActivate event instead.

Once you have the Frame object, you can add the MenuBar to it using its setMenuBar() method.

This sample code for the formActivate event shows how to obtain the current Frame and assign a MenuBar called mb to it.

  Frame f = getFrame(); 
  f.setMenuBar(mb); 

Responding to menu selections   Top of page

The AgfForm class provides two events that handle MenuItem selections and CheckboxMenuItem selections: menuItemSelected and menuItemStateChanged, respectively. These events, like all Java events that follow the JDK 1.1 event model, have an event object parameter that you can query for more information about the event occurrence.

menuItemSelected event

The menuItemSelected event fires when the user selects a menu item. In this event, you find what MenuItem the user selected and code the appropriate action.

menuItemSelected has this declaration.

  menuItemSelected(MenuItem menuItem, ActionEvent actionEvent) 

As you can see, it passes two values: One is the menuItem that the user selected; the other is an instance of the java.awt.ActionEvent. You can use this event object to get the key modifiers that the user might have pressed. java.awt.event.ActionEvent provides these methods:

NOTE   You can get the action command from either the ActionEvent or the MenuItem.

menuItemStateChanged event

The menuItemStateChanged event fires when the user checks or unchecks a CheckboxMenuItem. It has this declaration.

  menuItemStateChanged(MenuItem menuItem, ItemEvent itemEvent) 

It passes two parameters: menuItem is the CheckboxMenuItem that was selected, and itemEvent is an instance of the java.awt.event.ItemEvent.

The java.awt.event.ItemEvent has methods for getting information about the event that occurred. The most useful is the getStateChange() method, which returns the MenuItem's new state: SELECTED or DESELECTED.

Menu selection example

This code in the menuItemSelected event checks which item was selected and processes it.

  String command; 
  command = menuItem.getActionCommand(); 
  // File Menu commands 
  if (command.equals("Login...")) 
  { 
     //Do some type of Login processing... 
     logoutMenuItem.enable(); 
     loginMenuItem.disable(); 
  } 
  else if (command.equals("Logout...")) 
  { ... } 

Defining PopupMenus   Top of page

Creating a PopupMenu is similar to a Menu on a MenuBar, but the way you display the menu is different. These are the steps for defining a PopupMenu:

  1. Create the PopupMenu object.

  2. Add MenuItems to the PopupMenu object.

  3. Associate the PopupMenu with the form.

  4. Write code that displays the PopupMenu.

  5. Write code for menu events that occur when the user selects an item.

Creating a PopupMenu   Top of page

To create a PopupMenu object, you use the java.awt.PopupMenu constructor. It has no arguments, since a PopupMenu doesn't display a name. This example creates a PopupMenu object called popup.

  PopupMenu popup = new PopupMenu(); 

Unlike MenuBars, a PopupMenu is not rooted to any Frame, so you can create more than one PopupMenu per SilverStream form.

Adding MenuItems to a PopupMenu   Top of page

MenuItems on a PopupMenu are the same as for a Menu on a MenuBar. For information, see Adding MenuItems to a Menu.

Adding a PopupMenu to the form   Top of page

Unlike MenuBars, which are rooted to a window and require a Frame specification, you can add the PopupMenu directly to the form using add(), a method of Container (an ancestor of the form). Adding the popup menu does not display it; it makes the menu available to be displayed later.

This is an example of adding a PopupMenu called popup to the current form using the this object reference.

  this.add(popup); 

Displaying a PopupMenu to the user   Top of page

PopupMenus are not automatically displayed to the user when forms are displayed. You must programmatically display the PopupMenu at the desired time.

Each platform has a user action that is defined as the popup trigger. The operating system notifies the application when the trigger occurs. The application ignores the trigger action unless there is code in the appropriate event.

In the event code, you check whether the user action is the popup trigger. If so, your code displays the menu; if not, your code can take some other action or no action. Typically, you should check for the popup trigger in both the mousePressed and mouseReleased events. If the action occurs, the operating system passes information about the user action to the event in the MouseEvent object.

There are several things you need to do:

  1. Choose the control with which you want to associate the PopupMenu.

  2. In the code for the control's mousePressed and mouseReleased events, check whether the user action was the popup trigger by calling isPopupTrigger(), which returns a boolean. isPopupTrigger() is a method of MouseEvent.

  3. When isPopupTrigger() is true, display the PopupMenu to the user by calling show(), a method of PopupMenu. With show(), you specify an x, y position that is relative to the control with which the PopupMenu is associated.

    The control and its parent (for example, the form) must be displayed on the screen for show() to be valid.

This example shows how to display a PopupMenu called popup on a control called label. You should put this code in both the mousePressed and mouseReleased events. Or, create a separate method with this code and call it from both events.

  // If a popup trigger occurs on the label, display popup menu 
  if (mouseEvent.isPopupTrigger()) 
  { 
     popup.show(label, mouseEvent.getX(), mouseEvent.getY()); 
  } 

Responding to menu selections on a PopupMenu   Top of page

You respond to selections on the PopupMenu in the same way as for Menus on a MenuBar. Write code for the menuItemSelected event for MenuItems or menuItemStateChanged event for CheckboxMenuItems. The code checks which MenuItem was selected and implements the MenuItem's action.

For information, see Responding to menu selections.

Using Swing menus   Top of page

You can use the Swing menu objects JMenuBar and JMenu instead of their AWT counterparts, but they are less robust and less thoroughly tested.

When you use JMenuBar, you don't add it to the frame as you do for AWT menus. Instead you add it to the JApplet container inside the frame. The getRootPane() method gets the container.

The form uses the JApplet container is so that it can run in both SilverJRunner and a web browser. In SilverJRunner, this JApplet is placed inside SilverJRunner's JFrame. If you add a JMenuBar to the JFrame, the JMenus won't be visible when they're opened. That's because JMenus are lightweight components, and they'll be hidden by the JApplet, which is a heavyweight component.

This sample code illustrates how to implement a Swing menu.

  // Create the menu bar. 
  JMenuBar menuBar = new JMenuBar(); 
   
  JMenu menu = new JMenu(); 
  menu.setLabel("File"); 
  menuBar.add(menu); 
   
  JMenuItem menuItem = new JMenuItem(); 
  menuItem.setLabel("Save"); 
  menu.add(menuItem); 
   
  getRootPane().setJMenuBar(menuBar); 

File attachments and local disk access   Top of page

The File Attachment control (AgcFileAttachment) is a databound control that provides a mechanism for storing and manipulating file attachments within a database. The control must be bound to a database field with the contents of the attachment stored in a long varbinary or longvarchar column. The File Attachment control is not visible at runtime.

NOTE   File attachments can be used in the SilverStream Designer and SilverJRunner. Because of security restrictions inherent in the Java applet environment, file attachments will not work when run in a browser environment (unless users adjust their browsers' security settings).

There are two primary uses for the AgcFileAttachment control. You can use it to:

NOTE   AgcFileAttachment updates the database record directly, bypassing the form's agData object, and using a separate and unrelated transaction.

Binding a file attachment to a database table   Top of page

You bind a file attachment control to a database table at design time by specifying the Database Column property with the Property Inspector.

Programming file attachments   Top of page

You use the upload() method to upload a file attachment to the specified field in the database table. It has this declaration.

  void upload(File file, boolean delete) 

When you call upload(), SilverStream puts the file in the database column that was specified at design time. It is added to the form's current database record. If delete is set to true, SilverStream deletes the local file once the upload is completed.

The download() method displays a dialog box to the user warning the user that a file is about to be written to a local directory and allowing the user to cancel. If the user clicks OK, download() saves the referenced resource in a local file, and then launches the application for that file if the launch parameter is set to true. It has this declaration.

  void download(File file, boolean launch) 

where file specifies the file and path for the file to download.

launch specifies whether to launch the application associated with the file's extension.

NOTE   In Windows, the system launches an application for the file based on the registry entry for the file's extension. If the application is not registered, then Windows prompts the user to create an association for the file.

Forms and asynchronous processing   Top of page

By default, Java method calls are synchronous; that is, the application waits until the called method returns before continuing processing. For example, when you invoke a triggered business object, the form that starts the business object cannot continue until the business object completes and returns control to the calling form.

In most cases, this is the behavior that you want. However, you might want to allow the user of a form to perform other tasks while waiting for a different process to complete. This can be as simple as allowing the user to press a cancel button to stop the action. This type of processing is called asynchronous processing.

SilverStream provides two options for achieving this result. One provides a real asynchronous processing environment, while the other only simulates it.

Using AgcTimer   Top of page

You can use the AgcTimer control to perform some action at regular intervals. AgcTimer lets you specify an interval of time (in seconds) at which the timeIntervalExpired event fires. You can then write code in the timeIntervalExpired event to perform some activity.

The primary advantage to this approach is its ease of use. The AgcTimer control is quickly and easily available. It has very little overhead associated with it and can handle many situations where only an approximation of asynchronous processing is required.

The disadvantage is that you cannot guarantee the same behavior for every situation because AgcTimer does not interrupt an activity--if the user is idle, AgcTimer behaves differently than if the user is active. This is because AgcTimer does not operate in a separate thread. To achieve the same behavior, you must run the process in a separate thread. You can accomplish this by implementing the Runnable interface.

Using threads   Top of page

For true asynchronous processing in the SilverStream form environment, you must construct your own class that implements the java.lang.Runnable interface and starts one or more threads as needed. You are responsible for creating the separate thread and managing all of the issues associated with threads. To run a process in a separate thread, your class must implement Runnable. You then create a thread object to launch the thread and give that thread a reference to the Runnable object in its constructor. It then calls the run() method on your custom object.

A form can also implement Runnable.

In the Form Designer's Programming Editor, choose File>Java Interfaces. Add the java.lang.Runnable interface in the space provided. Add the code in the run() method available through the General section. In the appropriate form event, you might add the following code.

  Thread t = new Thread(this); 
  t.start(); 

Using threads and the Runnable interface is advanced Java programming. To learn more about asynchronous processing, see the Sun Java documentation.

Controlling the appearance of your form   Top of page

You can override the way the Form Designer lays out controls, and you or the user can choose the look and feel for a Swing-based form.

Controlling the layout of the form    Top of page

By default, SilverStream handles the layout of controls by setting the coordinates of each control. The instantiated form looks very much as you laid it out in the Form Designer. If the form is resized, controls keep their size and position unless you explicitly change them.

doLayout event

If you want to make changes to the arrangement of the controls, you can alter the size or position of controls in the doLayout event, which is fired when the form is resized. You can make adjustments based on the form's new size.

Java layout managers

If you want to take advantage of Java's layout managers, you can override SilverStream's arrangement of the controls and handle the layout yourself. For example, you might want certain controls, such as text areas, to be resized when the form is resized, or you might want to create a layout dynamically at runtime.

When you create a form class in the Form Designer, it defines the addAllFormControls() method in your form class. The method adds all the controls you created in the Designer using the absolute coordinates you specified. Code in the form's init() method calls the addControls() method, defined in the ancestor class AgfForm, which calls addAllFormControls().You can't edit addAllFormControls() because SilverStream generates that code.

However, you can override addControls() so that it doesn't call addAllFormControls(). If you override addControls(), it becomes your responsibility to add all controls yourself. You can use the generated list in addAllFormControls() as a reminder of the controls you defined in the Designer.

One reason to override addControls() is to use a layout manager that automatically resizes some controls when the form is resized. When you use this technique, the way you arrange the controls in the Designer has nothing to do with the appearance of the running form. You determine their layout in the code you write. You can also define and add other containers to provide different layout managers for different regions of the form.

In addition, you can bypass addControls() to create your own layout manager at runtime.

    For an example of creating a custom layout that is called at runtime, see Implementing a Nested Layout in Application Techniques.

Taking advantage of pluggable look and feel   Top of page

Swing controls have a UI manager that specifies the visual aspects of the controls. One of the features of Swing is the ability to give your application a consistent look on all platforms or to vary its appearance according to the current system. This is called pluggable look and feel (PLAF). When you use Swing-based controls on your form, instead of AWT-based controls, you can use static methods of the Swing's UIManager class to change the look and feel before or after the form is displayed.

    For sample code that gets and sets the look and feel, see the section on specifying a look and feel in Application Techniques.

Instantiating SilverStream form controls    Top of page

By default, when you add a control to a form using the Form Designer, SilverStream generates the code that instantiates the control, positions it, sets any properties that you specify (or default values for the properties), and adds it to the form. SilverStream automatically runs the generated code when the form is loaded.

If you are not sure what controls you might need, or you don't know until runtime how many you need, you can program all that yourself. Although this might sound like a lot of extra work, there are times when it becomes a requirement of your application. For example, you might want to create a form to edit data from a data source triggered business object. Your application is flexible so that the user can specify the data source that they want to use; thus, until the user makes this specification, you do not know exactly how many fields the form might require. In your code, you can instantiate the controls that are appropriate for that data source.

However, there are two main disadvantages:

All of the SilverStream form controls have null constructors. You can instantiate any control with new and the class name. For example, you can instantiate the text button control (AgcButtonText) by calling:

  new AgcButtonText(); 

Handling events for controls instantiated at runtime   Top of page

There are two ways you can get events from controls that are instantiated at run time.

Overriding or implementing the listener methods does not require you to create an auxiliary class, but there is some hidden complexity for handling events on controls that do exist at design time. If you choose to do this, you should not code any of that event type at design time. Instead, you should implement the listener interface on your form and manually handle that type of event for all controls both design-time and run-time. For example, if you want to respond to mouseClicked on a runtime instantiated control, then you should not write any code in any of the mouseClicked events at design time. Implement the listener interfaces on the form and then manually code the mouseClicked event for every control (regardless of who will instantiate the control: you or SilverStream).

Extending SilverStream form controls   Top of page

You can subclass any SilverStream form control to add to or change its functionality. Depending on how you want to use the subclassed controls, there are a several things you must do.

  1. Create the class that you want using the Business Object Designer. When prompted by the Wizard, specify the name of the class you want to extend, using the full package name (for example, com.sssw.rt.form.AgcButtonText).

  2. Put the newly created class in a JAR file using the SilverStream JAR Designer. For information, see the JAR Designer in the Tools Guide.

  3. Once the class is in a JAR file, you can put the control on the form.

    Include the Class's JAR file using the File>Jar File menu option in the Programming Editor. In the form, write the code to instantiate the control, and add it to the correct location on the form.

For an example, see extending a SilverStream form control in Application Techniques.

Providing context-sensitive help for forms   Top of page

SilverStream forms support application-defined context-sensitive help. When an user presses the F1 key, the help manager can display help appropriate to the control or dialog that has keyboard focus. You control the granularity of help by specifying help information for individual controls, their containers, or the form. The help manager traverses the container hierarchy and processes the help information that it finds.

Specifying help information   Top of page

You can specify help information in the Form Designer by setting the Help Page property in the Property Inspector. Controls that can take keyboard focus and some containers have a Help Page property.

In addition to specifying help information in the Designer, an application can set the help information for a particular control at runtime using the setHelpInfo() method.

The setHelpInfo() method allows you to change help information dynamically as the user navigates the application. For example, an application can use a List control's valueChanged event to change the help information associated with the control based on its the selected item. This allows the application to provide different context-sensitive help for each item in the list , rather than just for the list control as a whole. Similarly, an application can provide different help for the panes of a tab control by calling setHelpInfo() in the tab's paneChanged event.

The setHelpInfo() and getHelpInfo() methods are part of the AgiHelpInfo interface. Controls built by third parties can support context-sensitive help by implementing this interface.

Default help processing   Top of page

For default processing, the help information associated with a control is a relative or absolute URL. When the user presses the F1 key, the help manager calls the getHelpInfo() method on the control that has keyboard focus. If the control has help information, the help manager attempts to launch a browser to display this URL target. If the control with keyboard focus does not supply help information, the help manager looks at its parent (container) in the AWT/Swing component hierarchy. A control can fail to supply help information by returning null from getHelpInfo() or, in the case of 3rd-party controls, by not implementing the AgiHelpInfo interface.

As long as it has not found help information, the help manager continues up the hierarchy looking for help information. If it reaches the top of the hierarchy (a Frame) without finding any help information, it does not attempt to launch a browser.

URLs for help pages

The URL for a help page is relative to the SilverStream/Pages directory of the current database.

NOTE   A SilverStream page has a page name and can have one or more URL aliases. If the page has an URL alias, you can't refer to the page using the page name. You must use the URL.To select a help page in the Designer when the page has an URL alias, don't use the dialog for selecting pages; instead type the URL yourself.

The following examples illustrate how to specify an HTML page for the help manager.

Pages or servlets in the same database as the form

Pages or servlets in another database on the same server

Pages or servlets on another server

Pages anywhere on the web

Custom help processing   Top of page

The help manager also allows containers (typically forms) to handle context-sensitive help requests in a custom manner. While walking up the control hierarchy, the help manager, in addition to looking for help information, also looks for a help processor. A help processor is any control or container that implements the AgiHelpProcessor interface. This interface consists of one method:

  boolean processHelp(Object requester, String helpInfo); 

The help manager passes the help processor the component with keyboard focus (the requester) and whatever help information it has found so far. The help processor can handle this help request in any way and can interpret the help information appropriately for the application. If it processes the help request, it should return true. If it does not process the help request, it should return false and the help manager continues its search for a help processor.

For example, a particular form might implement the AgiHelpProcessor interface to handle context-sensitive help requests by displaying the help information in a dialog box. The help information associated with each control could be text to display in the dialog box, rather than an URL. Alternatively, the help information could be an index into a custom help system and the help processor could use this index to launch the custom help system.

If the help information is an URL, you have to find out whether the control you are using expects an absolute or relative URL and what the URL should be relative to.

How the help manager processes help   Top of page

It is important to remember that the help manager can find help information with one component and the processHelp() method for custom processing on a different component. When the help manager finds the processHelp() method, it calls the method whether or not help information has been found.

The following flowchart illustrates how help gets processed.

Summary of the process

When the user presses F1, the help manager begins these steps:

  1. For the component that has focus, if it implements AgiHelpInfo, the help manager gets the component's help information by calling getHelpInfo(). It saves the help information, if any, for later use.

  2. If the component implements AgiHelpProcessor, the help manager calls processHelp(), even if no help information has been found. If it returns true, the help processing is done.

  3. If processHelp() returns false or if the component doesn't implement custom help, the help manager gets the parent component (container). If there is no parent, processing continues with the last step.

  4. If no help information has been saved and the component implements AgiHelpInfo, help manager calls getHelpInfo() and saves the help information, if any. The help manager continues looking for an implementation of processHelp() by going back to step 2.

  5. Last step: If no help processor has returned true and non-null help information has been found, the help manager processes the help in the default way, by interpreting the help information as an URL and displaying it in a browser.

Mixing help processing

Because you can specify both help information and a help processor, you can mix different kinds of help processing in one component hierarchy. For example, a subform can implement its own help processing, but be used in a containing form that uses the standard help processing. Requesting context-sensitive help in the subform results in that subform processing the help request in its particular way. Help outside the subform works in the default way.

You can also have a subform that has default processing but, when placed on a form with custom processing, displays help using the parent's custom processing. This allows you to implement custom processing at a higher level. However, if this is not what you want--if you want a subform or control to use default processing when its container uses custom processing, you can circumvent the custom processing by implementing processHelp() on the subform. It can mimic default processing by calling agBrowser.showPage() to display the help information URL in the browser.






Copyright © 2000, SilverStream Software, Inc. All rights reserved.