The IDL procedure that creates your custom iTool widget interface will look much like a widget creation routine from a traditional widget application. This section points out some things you should be aware of.
Your widget creation routine should be an IDL procedure with a signature that looks something like:
PRO example2_wdtool, oTool, TITLE = titleIn, $ LOCATION = location, $ VIRTUAL_DIMENSIONS = virtualDimensions, $ USER_INTERFACE = oUI, $ ; output keyword _REF_EXTRA = _extra
oToolis an object reference to the iTool that will use the interface.
TITLEis an optional keyword that specifies the title used for the iTool window.
LOCATIONis an optional keyword that specifies the location [x, y] in pixels on the screen where the upper left corner of the interface should be positioned on creation.
VIRTUAL_DIMENSIONSis an optional keyword that specifies the virtual size of the iTool drawable area. Note that this size is not the same as the initial visible size.
USER_INTERFACEis a required output keyword that returns an object reference to the iTool user interface object created by the interface routine.
_REF_EXTRAis the standard keyword inheritance mechanism that allows the routine that calls your user interface routine to pass additional keyword values to the interface routine as needed.
Your routine may handle other keyword values as well.
Since the successful creation of an iTool interface relies on the presence of a valid iTool object reference, it is a good idea to check the
oTool argument before proceeding. A statement like the following serves as a reasonable check:
IF (~OBJ_VALID(oTool)) THEN $ MESSAGE, 'Tool is not a valid object.'
The first widget you will need to create when building a custom iTool widget interface is a top-level widget base to hold the interface. Your call to the WIDGET_BASE function should look something like:
wBase = WIDGET_BASE(/COLUMN, MBAR = wMenubar, $ TITLE = title, $ /TLB_KILL_REQUEST_EVENTS, $ /TLB_SIZE_EVENTS, $ /KBRD_FOCUS_EVENTS, $ _EXTRA = _extra)
All of the keywords shown here are documented along with the WIDGET_BASE function, but you should note the following things:
Your widget interface must be associated with an iTool user interface object. Since we will need the object reference to the user interface object when creating the iTool compound widgets, we include the following statement after creating our top level base widget:
oUI = OBJ_NEW('IDLitUI', oTool, GROUP_LEADER = wBase)
Note that we need the iTool object that was the argument to our interface creation routine to create the user interface object. Note also that we specify our top level base as the GROUP_LEADER of the interface object; this will ensure that any floating or modal dialogs displayed by the interface appear in the correct place.
Your custom iTool interface can include both iTool compound widgets and traditional IDL widgets. These are created in the same way as in a traditional widget application. The finer points of creating iTool compound widgets are discussed in later sections of this chapter.
Near the end of the widget creation routine, after the widget hierarchy has been realized, we must register the top-level base with the user interface object:
myID = oUI->RegisterWidget(wBase, 'Example 2 Tool', $ 'example2_wdtool_callback')
Here we specify the name of the callback routine that will handle messages from the iTool components. The return value from the RegisterWidget method is the iTool full identifier of the widget interface. We next use the identifier to specify that the interface is an observer (that is, that it can receive messages generated by iTool components) for the associated iTool:
oUI->AddOnNotifyObserver, myID, oTool->GetFullIdentifier()
This ensures that messages generated by the iTool are handled by the specified callback routine.
Many complex interfaces rely on a state structure containing information about the widgets in the interface. If you pass a reference to this state structure between routines in your user interface code using one or more pointers, free the pointers when the widget interface is destroyed. In our example interface, a pointer to the state structure is stored in the user value of the first child widget of the top level base widget. The following statement specifies a routine to be called when the widgets are destroyed:
WIDGET_CONTROL, wChild, KILL_NOTIFY = "example2_wdtool_cleanup"
Issues related to the destruction of the interface are discussed in more detail in Handling Shutdown Events.