Programmer's Guide



Chapter 15   Programming Forms

This chapter introduces some common ways you might program forms. It includes information about:

For specific programming examples with sample code, see the list of Java client techniques in Application Techniques.

Adding your own methods   Top of page

You can write your own methods for a form. These methods might support a specific business function or act as a module for reusable business logic. You can call these custom methods from anywhere on the form. You can define parameters for the method, as well as a return value.

In the Programming Editor, if you use the full-file view, you can type the method directly in the editing area.

If you use the single-method view, use the Tools>Add New Method menu item. To find a method you've already added, select the form in the lefthand Event Producers dropdown and the method in the righthand dropdown.

For more information, see the Programming Editor in the Tools Guide.

Working with Swing and AWT controls   Top of page

The Form Designer lets you define controls using Swing or AWT-based controls. If you are maintaining forms developed in Version 2, you will probably continue to use AWT-based controls, but SilverStream recommends that you develop new forms with Swing controls.

Swing and AWT   Top of page

AWT controls are the controls that were available in the first versions of Java. They are drawn on the screen using the native resources of each supported platform.

Swing controls were introduced as an optional library in JDK 1.2 and are now a standard part of the JDK. They are in the JDK's javax.swing package. They provide several benefits over AWT controls:

SilverStream packages for forms

Swing package

SilverStream's Swing-based controls are in the package com.sssw.rt.jform. SilverStream subclasses add extra functionality, such as data binding or more ways to specify a control's appearance.

When you work in the Form Designer, you don't need to work directly with a control's data model. For most controls, SilverStream uses the information you specify in the Designer to set up a default data model. The controls themselves have methods that you can use to update information in the data model so that you don't need to write code that manipulates the model directly. However, if you want, you can use getModel() to get a reference to the model and setModel() to substitute your own model.

For some controls, it is more efficient to make changes to the data model directly. In particular, the AgcJTree control is rather complex and you cannot set up a multilevel hierarchy of data without some coding. For examples of working with the AgcJTree control's data model, see programming Swing Tree controls in Application Techniques.

Package for basic form support and AWT-based controls

Basic form classes, including AgfForm and AgcData, and SilverStream's AWT-based controls are in the package com.sssw.rt.form.

Combining Swing and AWT controls in one form

You can mix Swing and AWT controls, with some restrictions. In particular, when you layer controls, a heavyweight control is always drawn in front of a lightweight control, regardless of how you layer them in the Designer. Documentation from Sun Microsystems provides information on using Swing and AWT controls together in the same container. To learn more, see the Sun documentation on mixing controls.

For information about adding controls to a form and the toolbars that contain Swing or AWT controls, see the discussion of form controls in the Form Designer documentation.

Converting existing applications to Swing   Top of page

Converting existing forms to Swing is not necessary. You will want to convert if you want the additional functionality of Swing controls, pluggable look and feel, or easier access by users with disabilities. If you have developed an extensive application with many forms, it may not be worth the effort to convert it to Swing. It takes a lot of time and the end result won't seem very different. For new forms, it's a good idea to use Swing, which is more standard, will be readily understood by Java developers, and has a larger set of controls and more functionality.

If you do want to convert existing forms, you need to change the type of each control on the form. Then you will set properties and rewrite code, as needed.

To change the type of one or more controls:

  1. Open the Property Inspector.

  2. Select one or more controls that you want to convert to the same type.

  3. At the right of the Control type field, click the ellipses button to display the list of controls. Select the new type from the list. The Swing types begin with "J".

When you change the type, some compatible properties retain their values; for example, the value in the Data Column property stays the same, leaving the data binding as it was. You can change property values for several controls at once by selecting them as described for the control type.

After you've converted the controls, examine the code for your form. The APIs for the Swing controls are different from the AWT-based controls so you'll need to change some method calls.

In particular, here are some areas to watch out for:

Working with Swing controls   Top of page

The SilverStream API documentation for the rt.jform package has information about using individual SilverStream controls that extend Swing components.

For complete information on programming Swing controls, see the Swing Connection from Sun MicroSystems. Their Swing tutorial provides thorough treatment of many of the Swing controls. In fact, it describes much more than you need to know if you let the Form Designer handle the setup of the controls.

To study specific programming techniques for controls with sample code, see the list of Java client techniques in Application Techniques.

About Swing controls and scrolling

Individual Swing controls do not scroll by themselves. Instead, they must be placed on a JScrollPane in order to scroll. In the Form Designer, when you drop a JTextArea, JList, JTree, JEditorPane, or JTable on a form, SilverStream automatically creates a JScrollPane, adds the control to the scroll pane, and adds the scroll pane to the form. This allows these controls to scroll. The generated code looks something like this:

  myTextArea = new com.sssw.rt.jform.AgcJTextArea(); 
myTextArea.setName("myTextArea");
myTextAreaScrollPane = new JScrollPane(myTextArea);
myTextAreaScrollPane.setBounds(320,115,130,115);
myTextAreaScrollPane.setVisible(false);
myTextArea.setLineWrap(false);

...

this.add(myTextAreaScrollPane);

If you write code to instantiate scrollable controls, your code must instantiate the scroll pane too. As shown in the code above, some actions, like setting the control's bounds, setting its visibility, and adding it to the form, are performed on the scroll pane, not the control itself.

For more on using scroll panes, see the Swing Sampler example in Application Techniques.

Using child forms   Top of page

A form that is instantiated from another form has a parent-child relationship with the original form. You can create child forms in several ways:

Child forms and data   Top of page

Like all forms, child forms have an agData instance variable and can support additional AgcData objects. (The agData instance variable allows a form to access and update a primary dataset.)

The child form's dataset can be related to the parent's dataset, or it can be completely independent. You may also need to synchronize changes to the data on the parent and child forms. For subforms added in the Designer, SilverStream creates and you can edit a Link clause that restricts the subform's data retrieval. For other types of child forms, you can restrict the query on the child form programmatically and you can pass information between the two forms to synchronize changes.

When retrieving data, you can restrict the query in several ways. You can do any or all of the following:

In situations where the child form has a Where clause, a Link clause, and you call the query() method with a Where clause, SilverStream resolves the query by ANDing the clauses together.

Updating data in dialogs

There are two ways to update data from the dialog to the database. Your choice depends on how atomic the updates must be. Here are the options:

Updating data in subforms

Subforms can manipulate the contents of their own agData object as well as the contents of the parent's agData object. Likewise, the parent form can manipulate the subform's agData object as well as its own. Like any agData object, the subform's agData object contains a copy of the database's data, and you must call the agData.updateRows() method to commit any changes to the database.

For updating data, you can choose to update only the subform or all the data on the form. Here are the options:

How SilverStream determines a Link clause for subforms

When you add a subform to a form in the Form Designer, SilverStream uses the Link Clause property to spell out the relationship between the data for the parent form and the subform. If it determines that the two datasets are related (by searching for any database relationship between the primary tables), SilverStream automatically populates the subform's Link Clause property with an expression that relates the two datasets. The expression describes a join operation between the datasets of the parent and the subform.

If SilverStream cannot determine a relationship between the datasets, it does not generate a Link clause. However, you can add a Link clause or change an existing Link clause using the Property Inspector. When you specify a Link clause, you can refer to tables and fields in both the subform and parent datasets, as well as controls on the parent form.

For example, if a form with employee data displays a subform with data from the salaries table, a Link clause like this would ensure that the two forms display information for the same employee:

  employees.employeeid=salaries.employeeid 

The Link clause is ANDed with the subform's Where clause. You can think of it as a refinement of the Where clause.

NOTE   The View control also supports the Link Clause property.

Communicating between parent and child forms   Top of page

Typically, you want to notify the parent form when particular events occur in the subform or dialog box. There are several ways to do this.

Calling a method on the other form

Calling a method in another form class is a simple and portable way to handle inter-form communication. A form can call a method on another form as long as the form has a reference to the other one. Arguments to the method can pass data from one form to another.

This sample code calls a method of the parent form whose class name is frmMaster.

  frmMaster parent = (frmMaster)getParentForm(); 
parent.addToList( fldTree.getText(), "Flower" );

This sample code in the parent form calls a method on a subform. The method returns the name of the employee in the first row of the form's dataset.

  String empname = frmEmployees.getEmployee(1); 

Testing and deployment requirements

When you test and deploy your application, both forms must be in the same JAR file so that the references to the form classes can be resolved. For information on building JAR files, see the Jar Designer in the Tools Guide.

Then in the Form Designer, for each form, you need to add a reference to the JAR file by using the File>Jar Files menu item.

Using an interface for the methods you want to call

When more than one form implements the same set of methods, you can ensure consistency by defining an interface for the methods. A communication strategy with an interface has three parts:

The requirements for testing and deployment are the same as for calling methods directly, described in Calling a method on the other form. The forms and the interface must all be in the JAR file.

Defining the interface

First define the interface in the Business Object Designer. For information, see Business Object Designer in the Tools Guide.

Be sure to include a package declaration in the interface, which makes importing the interface more straightforward.

An interface with one method might look like this:

  package utilities; 
public interface ListUpdater {
   public void addToList(String item, String category);
}

Implementing the interface

In the form that implements the interface, you need to:

  1. Import the package containing the interface.

      import utilities.*; 
  2. Add the interface to the list of interfaces that the form implements. Choose File>Java Interfaces and click Add. Specify the interface and optionally click the check box so the method declarations will be added to the form code.

    The result is that the class declaration includes code like this:

      implements ListUpdater 

    The body of the class includes a method declaration like this:

      public void addToList(String item, String category) 
    {
    }
  3. Write code for the method.

      public void addToList(String item, String category) 
    {
       if (category.equals("Tree"))
          lstTrees.addItem(item);
       if (category.equals("Flower"))
          lstFlowers.addItem(item);
    }

Calling the interface method

In the form that calls the interface method, you need to:

  1. Import the package containing the interface.

      import utilities.*; 
  2. Call the method of the related form by getting a reference to the form, casting it to the interface, and calling the method.

    This example is code in the child form -- the parent form implemented the interface.

      ListUpdater parent = (ListUpdater) getParentForm(); 
    parent.addToList("oak", "Tree");

    If the child form implements the interface, the parent form already has a reference to the child. The code to call the method might look like this:

      ((ListUpdater)subform1).addToList("oak", "Tree"); 

Using fireEvent with programmer-defined events for a subform

You can create programmer-defined events in the subform to inform the parent form of conditions or user actions on the subform. This technique is easy to implement because the Programming Editor exposes the events in the parent form so you can write code for them.

Using programmer-defined events has these parts:

Specifying event identifiers

When you are designing the subform in the Form Designer, you create the programmer-defined events by specifying values for the Events Produced property on the Form page of the Property Inspector. The event name should describe the event; you might use names like UPDATE, REFRESH. The names can include letters, numbers, and underscores.

In the form code, the identifiers are actually numeric constants. SilverStream converts the name you enter to uppercase, following the Java convention for constants.

You use the identifier when you call the fireEvent() method and the parent form uses the identifier when it creates names for the programmer-defined events.

Calling fireEvent() in the subform's code

You fire a programmer-defined event by calling the subform's fireEvent() method with one of the identifiers you defined. In addition to the event identifier, which is an int, you can specify a second argument, which is data of any Object type to be passed to the event.

For example, if you defined two events, UPDATE and REFRESH, you could trigger the UPDATE event for a particular row number with this call:

  fireEvent(UPDATE, new Integer(5)); 

Writing event code in the parent form

When you are working with programmer-defined events, keep in mind:

Using fireCustomEvent() with ad hoc event identifiers

Every AgfForm supports an event called formCustomEvent, which lets modeless dialogs and their parent forms communicate back and forth. You fire formCustomEvent by calling the fireCustomEvent() method.

This mechanism works just as well when showing a form in a frame (FORM_FRAME) as it does for showing a form in a modeless dialog.

To trigger the event, you might write code like this in the form for the dialog box. The arguments are the form where the event will be triggered, an identifier for the event -- it can be of any type, and data to be passed to the event handler on the target form.

  AgfForm frmParent = getParentForm (); 
fireCustomEvent (frmParent, "text data", "Data to be passed");

On the target form, you write code in formCustomEvent to respond to the event. The event has two arguments: the event identifier and an argument of application-relevant data:

  protected void formCustomEvent(Object identifier, Object argument) 
{
   if ( (String) identifier.equals("text data") )
   {
      fldDisplayChildData.setText((String)argument);
   }
}

Using parameters with the showPage() method

A parameter is a name-value pair that is associated with a form. You can create any number of parameters with names of your choice. The form's parameters are stored in an internal Hashtable (a class in the JDK). The AgfForm methods setParameter() and getParameter() let you add and access individual values. setParameters() returns the entire Hashtable.

The main use for parameters is to pass data to a form on another browser page via the showPage() method in the PVHelperBrowser class. The Hashtable argument lets you pass name-value pairs which SilverStream defines as parameters on the second form. You can write code in the formActivate event that accesses these parameters and takes appropriate actions, such as initializing fields. You might use this technique when you need to pass login information or order status to another page.

NOTE   Using showPage() is not a recommended application design because it has slower performance that an application that uses child forms.

You can also use parameters to pass data from a parent form to a child form, via the showForm() and showFormDialog() methods, but it is not the recommended method. Calling methods of the child form directly and using an interface to standardize those methods is simpler and more standard.

How the hashtable works

The names and values in the hashtable can be any object type. To set up a Hashtable with data from the current form, use code like this:

  Hashtable hshExample = new Hashtable(); 
hshExample.put("custname", fldCustomerName.getText());
hshExample.put("custid", new Integer(CustomerID.getValue()) );

To navigate to a new page and pass the parameters, call showPage():

  agBrowser.showPage("orderinfo.html", null, hshExample); 

On the second page, parameter names and values are stored as Objects. It is up to the application to know what the actual parameter names and data types are and what to do with them. For example, in the formActivate or formLoaded event, you might get individual parameters and use the values to initialize fields on the form or query for data:

  String paramCustName = (String)this.getParameter("custname"); 
lblCustName.setText("Greetings, " + paramCustName);

Integer paramID = (Integer)this.getParameter("custid");
try {
   agData.query("customers.customerid = " + paramID );
} catch (Exception e) {
   // exception processing
}

You can also get the whole Hashtable. Then you can use Hashtable methods such as get() and put() to access its values.

  Hashtable hshParams = getParameters(); 

Working with subforms   Top of page

The term subform describes a way of displaying a form as a child form within the frame of the parent form. Just as with any form, a subform is an instance of the AgfForm class and uses the same data management and inter-form communication techniques described in Using child forms. You use the Form Designer to create the forms you plan to use as subforms.

Subforms and program design   Top of page

Subforms are useful in applications where you need to update multiple datasets or display Master/Detail information on a single display, or when you want to create a reusable component that you can use on multiple forms.

There are two ways to instantiate subforms:

The technique you use depends on where you want to optimize the performance of your application.

Subforms that are part of the parent form's definition are all instantiated when the parent form is. This technique is appropriate if all the subforms are visible at once or if your form includes only a few subforms. If your form includes many subforms, there could be a noticeable delay before the form is displayed.

Enhancing performance by instantiating subforms when needed

Dynamic subforms can help you enhance a form's performance. When you add subforms in the Designer, SilverStream loads those subforms when the parent form is loaded, which delays the display of the parent form. Instead, you can wait until the user needs to view a subform and instantiate it then. In an application that lets the user choose among several subforms, for example, on different panes of a tab control, you would instantiate a subform only if the user displays that pane. Some subforms might never get instantiated if the user doesn't access them.

Enhancing performance of a browser application with subforms

When your application is displayed in a browser, you can use subforms or any type of child form to improve application performance. The reason is the way forms on HTML pages use the Java virtual machine. A form on a page runs as an applet and requires the browser to load the Java VM. When your application has separate HTML pages each with their own form, the browser must instantiate a new Java VM (which can take 5 to 15 seconds) for each applet. If you add and remove subforms dynamically from a single parent form, or if you open dialog boxes, the forms all work within the same instance of the Java VM.

Including a subform to the parent form's definition

In the Form Designer, you can add a subform just as you do a view or other object from the Gallery. For information, see adding subforms in the Form Designer in the Tools online book.

A reference to a subform is compiled as part of the parent form's class. This means that the parent form has complete access to the subform's methods and events, as well as access to any objects on the subform, by qualifying the object name. For example, subform1.getBackgroundColor() returns the subform's background color.

Subforms also have access to their parent forms via the getParentForm()method. For example, getParentForm().getBackgroundColor() returns the parent form's background color.

Subforms are loaded before the parent form. You can refer to the subform in the parent form's formLoaded event.

Dynamically instantiating forms as controls

You can use dynamically instantiated subforms to enhance your application's performance. The subform doesn't need to be created unless the user needs it. To display the subform, the application design might include:

All of the SilverStream controls, including the form control (AgfForm), extend the java.awt.Container class. You can use its add() method, which takes a component as its argument. It adds the form as a subform to an existing form.

Dynamically instantiated subforms are not compiled as part of the calling form's class definition. The form's class only has a string reference to the object. This means that at compile time, SilverStream does not know about the subforms that a form opens. You will get run time exceptions if the subform does not exist or cannot be located at run time.

Here's how you use this technique:

  1. Create and save all of your forms using the Form Designer.

  2. On a main form, create a way for users to navigate to different forms in your application.

  3. When the user navigates to a new form, instantiate it, set its position, then add it to the main form.

Example

These code fragments illustrate how to instantiate a subform and remove a previously displayed subform, if one exists. It loops through a list of three forms, instantiating each in turn.

In General>Declarations section of the form code, declare these variables:

  // Variable for saving a handle to instantiated subform 
AgfForm oldControl = null;
// Array of form names (forms were defined in Form Designer)
String[] sFormList =
   { "frmOrderDetail", "frmCustDetail", "frmShipDetail" };
int iFormCount = 0;

In a button's actionPerformed event:

  try { 
   // if a subform has already been displayed, remove it
   if (oldControl != null)
      remove(oldControl);

   if (iFormCount == sFormList.length) iFormCount = 0;
   // instantiate the new form, but don't display it
   AgfForm newForm = agDialog.getForm(sFormList[iFormCount++]);

   // Save the reference
   oldControl = newForm;

   // Set the form's position
   newForm.setLocation(275,50);
   // Add it to the parent form
   add(newForm);

   // Force the form to repaint
   invalidate();
   validate();
}
catch (Exception e) {
   agDialog.displayError(e);
}

Here's a summary of what the code does:

Working with dialog boxes   Top of page

A dialog box is a window that you can use to display information or to obtain a response from a user. The dialog box can be either modal or modeless. They are instances of the AgfForm class, which you define in the Form Designer. For information about data management and communication between dialog boxes and parent forms, see Using child forms.

A modal dialog box blocks user input to all other windows until the user dismisses it. When you open a form in a modal dialog, SilverStream displays the form in a separate window in the center of the screen. The size of the dialog box is determined by the size specifications for the form being displayed.

A modeless dialog box lets the user work with several forms without having to close the windows. When you open a form as a modeless dialog, SilverStream displays the form in a separate window. You specify the window's properties when you launch the dialog box.

Dialog boxes are not compiled as part of the calling form's class definition. The form's class only has a string reference to the object and SilverStream does not know about dialog boxes that a form opens. You will encounter run time exceptions if the form does not exist or cannot be located at run time.

The parent form's agDialog instance variable (an instance of the PvHelperDialog class) provides methods for displaying dialogs. When you call one of these methods: getForm(), showFormDialog(), and showForm(), SilverStream instantiates and initializes the form and fires the form's formLoaded event. Then, for showForm() or showFormDialog(), SilverStream displays the form immediately. With getForm(), you can do custom initialization before displaying the form.

When writing code in the child form, call the getParentForm() method to get a reference to the parent form.

Displaying a dialog box   Top of page

To display either a modeless or modal dialog, you call showForm() with the appropriate window type (see About window types). The method and constants are in the PvHelperDialog class. For example, this code instantiates and displays the form frmDataEntry as a modeless dialog.

  agDialog.showForm("Specifying data", "frmDataEntry", null, null, 
   null, agDialog.FORM_MODELESS, false, 50, 50);

NOTE   There's also a simpler method for displaying a modal dialog; see Shortcut for displaying a modal dialog.

Other variants of showForm allow you to specify a Hashtable of parameters for the dialog box, a query string, and an Order By specification. To access the parameters, call getParameter() in the formActivate or formLoaded event of the child form.

NOTE   The query string can only reference fields that are already contained in the form's dataset. You must use the tablename.fieldname construct when referencing fields in the Where or Order By strings.

Displaying an instantiated form as a dialog

A second variant requires that you pass an AgfForm object which you obtained using the getForm() method. You can initialize any of the form's fields or variables after calling getForm() but before calling showForm().

The getForm() method in the PvHelperDialog class instantiates and initializes a form but does not display it. Code on the parent form can access controls and methods of the child form and set values, synchronizing with data on the parent form.

  AgfForm frm = agDialog.getForm("frmDataEntry"); 
// Initialize fields on the form
agDialog.showForm("Data Entry", frm, agDialog.FORM_MODAL,
   false, 50, 50);

When you use getForm(), you can specify parameters, which are available when the form is instantiated in the formLoaded event, before the form is displayed. You don't specify parameters with this version of showForm(), when the form is finally displayed.

About window types

You specify the window type with constants of the PvHelperDialog class. They are:

Resizable option

If you create a dialog box that the user can resize (resizable is true), you must programmatically manage the layout and sizing of the form's controls to respond to the resizing. When the user resizes a form object, the form's doLayout event fires. You should resize the controls using the setSize() or setBounds() methods in the doLayout event.

Shortcut for displaying a modal dialog

Instead of calling showForm() with the FORM_MODAL window type, you can call showFormDialog(), which requires fewer arguments. It has several variants. The simplest takes a caption and a form name.

  agDialog.showFormDialog("Data Entry", "frmDataEntry"); 

As with showForm(), the other variants allow you to specify a Hashtable of parameters for the dialog box, a query string, and an Order By specification. To access the parameters, call getParameter() in the formActivate or formLoaded event of the child form.

You'll find showFormDialog() illustrated in the section on displaying a form as a dialog in the topic on displaying dialogs in Application Techniques.

Closing a modal dialog box   Top of page

You programmatically close a dialog box using the form's closeDialog() method. You typically program this method call on a button control. When you close a modal dialog box, control returns to the parent form. The argument to the closeDialog() method is the return value of the parent form's showFormDialog() call.

When you call agDialog.showForm() or agDialog.showFormDialog(), you must handle the case where the return value is null. Even if your form only calls closeDialog() with non-null values, the user can still close the dialog box by clicking the system close box or choosing Close from the system menu. Either of these actions closes the dialog and returns null.

SilverStream recommends that you return null from the Cancel button, since this allows the calling code to handle both the Cancel button and the close box in identical ways.

If the user tries to close the dialog using the system close box or Close menu item, the windowClosing event occurs. You can use that event to intervene in the close process: you might prevent the dialog from closing, return a different value, or call the code you've already written for the button that cancels the dialog box.

Working with message boxes   Top of page

When you want to display a message to the user, you can create a form for that purpose, or you can use one of the predefined message boxes that SilverStream supplies. A message box is a special type of modal dialog box.

SilverStream instantiates the message box for you, providing a standard look and feel. You simply supply a title and the message text. Most of the standard message boxes return a value that reports the user's response. The showMessage() methods are available on the form's agDialog instance variable. agDialog is an instance of the PVHelperDialog class.

The message boxes differ in the number of buttons they have and the values they return:

Return values   Top of page

Both the OK/Cancel and Yes/No methods return a primitive boolean data type. If the return value is true, then the user pressed OK or Yes. If the return value is false, the user pressed Cancel or No.

showMessageYesNoCancel() provides three possible return values, so it returns a Boolean object, not a primitive. If the user presses Yes, the return value is Boolean.TRUE. If the user presses No, the return value is Boolean.FALSE. If the user presses Cancel, the return value is null.

showMessageYesAllNoCancel() has four possible return value, so it returns a String. The values are "y" if the user selects Yes, "n" if the user selects No, "a" if the user selects All, or "x" if the user selects Cancel.

Example

The following code fragment illustrates how you might display a message with the Yes and No options:

  boolean response;  
response = agDialog.showMessageYesNo(
   "This is the caption", "This is the message");
if (response == false)
   // process false . . .
else
   // process true . . .

Creating your own message box   Top of page

If the standard message dialog boxes do not meet your needs, you can create your own form and launch it as a dialog. You use the showForm() or showFormDialog() methods described in the next section.

Navigating pages   Top of page

Unless you deploy your applications using SilverJRunner, SilverStream forms are deployed on HTML pages as Java applets. When a user requests the form's page, the SilverStream Server instantiates the form, together with the objects it contains, and displays it to the user in the browser environment. When the user leaves the page, the SilverStream Server makes the form and the objects it contains available for garbage collection. Any data on the form at the time the browser leaves it is lost. For applications that combine multiple forms and forms that launch multiple windows, the data is lost when the browser leaves the application's main page.

NOTE   Including forms and views in pages is not supported in SilverStream Version 3.0 due to limitations of the Sun Java 1.2 browser plug-in. We hope to re-enable this support in SilverStream in the future. See the release notes for updated information.

There are two ways for an application in a browser to display multiple forms:

Customizing forms for users    Top of page

Some types of applications customize the user interface based on the individual user or the user's group. For example, an application might display employee information to all employees and allow managers to update the information. The application can hide the update button from users that aren't supposed to make updates.

You can set up your server to require user login or you can specify that individual objects require login before the user can open them. You use the SilverStream Management Console to add users, assign them to groups, and set permissions for individual objects. To find out how, see the information on users and groups in the Administrator's Guide.

When a form requires login, you can get the user's login name and set up the form according to that user's needs. There are two methods in the AgfForm class for getting information about the current user:

After you get the user's login name or group membership, you can programmatically enable and disable controls on the form; or you can make certain controls visible, invisible, or read-only depending on the control.

NOTE   Customizing the user interface to disable functionality does not constitute security for your server. You must also take appropriate steps to make your server secure. For information, see information on security in the Administrator's Guide.

Example

The following code illustrates how you might enable a control based on the user's group membership. The example tests whether the user is part of a group named "Employees". If the user is in the group, an AgcJTextArea control containing a product description is made editable so the employee can maintain the description.

  if (userInGroup("Employees")) 
   jtaProductDescription.isEditable(true);
else
   jtaProductDescription.isEditable(false);






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