Creating a UI Panel Interface

It is beyond the scope of this manual to provide general information on the creation of user interfaces. For information on creating a user interface using the IDL widget toolkit, see "Creating Graphical User Interfaces in IDL" (Building IDL Applications). Keep the following points in mind when creating IDL widget interface code for iTool user interface panels.

Panel Creation Routines

A user interface panel creation routine is similar to the widget creation routine that creates a standalone widget application, but with the following important differences:

Signature

The routine signature of a user interface panel looks like this:

PRO PanelName, wPanel, oUI 

where PanelName is the name of the routine, wPanel is an input argument that contains the widget ID of the panel widget associated with this panel, and oUI is an input argument that contains an object reference to the IDLitUI object associated with the iTool that includes the user interface panel.

Event Loop and Widget Management

Standalone widget applications must arrange for the management of their widgets and the creation of an event loop; these details are usually handled by the XMANAGER or WIDGET_EVENT routines. A user interface panel does not need to call XMANAGER or WIDGET_EVENT; widget management is handled by the main iTool interface code. A user interface panel simply attaches itself to the bulk of the iTool interface.

About the Panel Widget

In the initial release of the iTools, user interface panels are contained in an IDL tab widget displayed on the right side of the iTool window. We will refer to this tab widget as the panel widget in this documentation, since all user interface elements in a UI panel are contained in this widget.

The panel widget itself is created automatically when a user interface panel is registered with an iTool, and its widget ID is passed to the panel creation routine along with a reference to the iTool user interface object.

Use the widget ID of the panel widget to set the title of the tab that appears at the top of the panel. For example the following lines might occur at the beginning of a routine that builds a user interface panel:

PRO ExamplePanel, wPanel, oUI 
 
   ; Set the title used on the panel's tab. 
   WIDGET_CONTROL, wPanel, BASE_SET_TITLE='Example Panel' 
 
   ... more panel code. 

The wPanel argument contains the widget ID of the panel widget, which was assigned when the iTool interface was built. The oUI argument contains an object reference to the IDLitUI object associated with the current iTool. The call to the WIDGET_CONTROL procedure sets the title of the tab to be "Example Panel."

You may also find it useful to specify a single event-handling routine for all events generated by the panel widget. You can specify the name of this routine with a statement similar to the following:

WIDGET_CONTROL, wPanel, EVENT_PRO = 'ExamplePanel_event' 

where ExamplePanel_event is replaced by the name of the event-handling routine you create for your panel. Of course, you can also specify event-handling routines for specific widgets within the panel using the EVENT_PRO and EVENT_FUNC keywords to the widget creation routines.

Registering the Panel with the User Interface Object

To ensure that notifications from the iTool itself are passed to the user interface panel as needed, the panel creation routine must register the panel widget with the iTool user interface object. This registration step allows you to specify the name of the callback routine that will be called when a notification is generated by the iTool itself.

To register a user interface panel, use the RegisterWidget method of the IDLitUI object:

idObserver = oUI->RegisterWidget(wPanel, 'Panel', 'Ex_callback') 

where oUI is an object reference to the IDLitUI object and wPanel is the widget ID of the panel widget; both are passed in as arguments to the panel creation routine. The second argument to the RegisterWidget method ('Panel', in this example) is the human-readable name of the UI panel. The third argument ('Ex_callback', in this example) is the name of the panel's callback routine. See "IDLitUI::RegisterWidget" (IDL Reference Guide) for details. Callback routines are discussed in detail in Creating Callback Routines.

Adding Observers

For notification messages to be passed to the correct callback routine, an OnNotifyObserver must be established by calling the AddOnNotifyObserver method of the IDLitUI object. The AddOnNotifyObserver method takes as its arguments the ID created by the call to the RegisterWidget method (as discussed in the previous section) and the component object identifier of the iTool component to observe. Once the observer is created, each time the specified iTool component generates a message (that is, when the component itself calls the DoOnNotify method), the registered widget callback routine is called with the message as one of its arguments. The call to the AddOnNotifyObserver method looks like:

oUI->AddOnNotifyObserver, idObserver, idSubject 

where idObserver is an identifier created by a call to the RegisterWidget method, and idSubject is usually the component object identifier of the iTool component being observed. See "IDLitUI::AddOnNotifyObserver" (IDL Reference Guide) for additional details.

The idSubject argument to the AddOnNotifyObserver method is normally the object identifier of an iTool component object, but it can be any string value. For example, any time the selection within an iTool window changes, the DoOnNotify method is called with its first parameter (idOriginator) set to the string value 'Visualization' rather than to the object identifier of a component. An observer whose idSubject argument is set to the string 'Visualization' will be notified each time the selection changes in the iTool window. For example, the following statement specifies that the panel widget (as registered via the RegisterWidget method) will receive notifications whenever a visualization changes in the iTool window.

oUI->AddOnNotifyObserver, idObserver, 'Visualization' 

Here, idObserver is the identifier created in the previous section. The second argument ('Visualization') specifies that messages will be generated whenever a visualization is modified.

Example: A Simple UI Panel provides examples of observers of both types. See iTool Messaging System for background information on observers and messages.

Create the Widget Hierarchy

The widget hierarchy of a user interface panel looks like the following:

Panel widget 
   | 
    - Base widget 
        | 
         - other widgets 

Since the widget ID of the panel widget is supplied as an argument to the panel creation routine, all that is left is to create a base widget with the panel widget as its parent, and to populate the base widgets with other widgets as necessary.

Passing State Information

State information can be passed between widget creation routines and widget event handling routines in several different ways. The method used most often in iTool user interface panels is to create a state structure in the panel creation routine, store the appropriate values in this structure, and assign the structure to the widget user value of one of the widgets in the panel widget hierarchy. For a more detailed discussion of this technique, see Managing Application State (User Interface Programming).

In addition to widget IDs and other state information from your widget interface, you may find it useful to store object references to the iTool object and to the IDLitUI object associated with the iTool object in the state structure. Having these object references available in your event handler and callback routines allows you to take advantage of methods available in the iTool and user interface objects.

Create Event Handlers

Like other widget applications, iTool user interface panels use one or more event handling routines to perform actions based on the user's interaction with the widgets in the interface. As with generalized widget applications, you can write event handling routines for a user interface panel in numerous ways; see Widget Event Processing (User Interface Programming) for an in-depth discussion of widget event handling.

The following suggestions apply specifically to event handlers for iTool user interface panels:

Use the GetSelectedItems Method

Often, you will want to apply an operation to one or more items in the iTool window when the user selects an element on the user interface panel. Use the GetSelectedItems method of the iTool object to retrieve references to the iTool component objects that are selected.

The following statement retrieves an array of object references to all of the currently selected items in the iTool:

oTargets = state.oTool->GetSelectedItems(COUNT = nTarg) 

Note
Note that this example assumes that a reference to the iTool object is stored in the oTool field of the state structure variable. The COUNT keyword to the GetSelectedItems method returns the number of items selected.

Use the DoAction Method

In many cases, the user's interaction with the user interface panel will instruct the iTool to apply an iTool operation to the selected item. Where possible, use the DoAction method of the operation to perform this task. Calling the DoAction method ensures that the changes caused by the operation are properly inserted into the iTool undo/redo system.

For example, the following statement:

success = state.oUI->DoAction('Operations/Rotate/RotateLeft') 

calls the DoAction method on the IDLitUI object associated with the current iTool, invoking the operation registered with the system with the operation identifier 'Operations/Rotate/RotateLeft'.

Redraw the iTool Window

Call the RefreshCurrentWindow method of the iTool object to force the iTool's window to update, displaying any changes that took place as the result of the operations executed in your event handling routine:

state.oTool->RefreshCurrentWindow 

Note
Note that this example assumes that a reference to the iTool object is stored in the oTool field of the state structure variable.