Example: Changing a Property Value
This example creates a user interface service named SrvExample, which displays a dialog that allows the user to change the NAME property of the currently selected iTool component. The SrvExample user interface service is launched by an IDLitDataOperation named opName.
This example is intended as a demonstration of the techniques used to create a user interface service. In practice, you do not have to create a user interface to change the NAME property; it can be changed more easily by altering the value in the Visualization browser. It is conceivable, however, that you might want to provide an interface that allows the user to change numerous properties simultaneously, with some values being based on other user-supplied values. Similarly, you may wish to display a dialog that allows the user to set the properties of an operation every time that operation is executed, without forcing the user to open the Operations browser.
Creating and using the SrvExample user interface service involves the following steps:
Creating the SrvExample Service
The SrvExample user interface service consists of a single function named SrvExample, stored in a file named srvexample.pro that is located in a directory that is included in the IDL !PATH system variable.
FUNCTION SrvExample, oUI, oRequester ; Retrieve widget ID of top-level base. oUI->GetProperty, GROUP_LEADER = groupLeader ; Retrieve the original value of the name property ; attribute from the selected item. oRequester->GetProperty, NAME = origName ; Display the widget UI that allows the user to choose ; a new name. newName = wdSrvExample(NAME = origName, $ GROUP_LEADER = groupLeader) ; Set the property value. oRequester->SetProperty, NAME = newName ; Return success RETURN, 1 END
Discussion
The function that implements this example service follows the pattern outlined in Creating the UI Service Routine. It uses the object reference to the IDLitUI object to retrieve the widget ID of the top-level base of the iTool user interface, and later uses the retrieved value to set the GROUP_LEADER keyword to the user interface routine. It uses the object reference to the "requester" object (in this case, the iTool component that is selected in the current iTool) to retrieve the NAME property. It then calls a routine (wdSrvExample) that displays a user interface allowing the user to select a new value for the NAME property.
The string returned by the wdSrvExample routine is used to set the NAME property of the selected iTool component, and the routine returns 1 for success.
Creating the SrvExample Interface
The interface presented by the SrvExample user interface service consists of a set of routines that create an IDL widget interface. The creation routine and two simple event-handling routines are stored in a file named wdsrvexample.pro that is located in a directory that is included in the IDL !PATH system variable.
Widget Creation Function
The following function creates the widget interface that is displayed when the SrvExample user interface service is called. The widget creation routine should be the last routine in the file.
FUNCTION wdSrvExample, NAME = origName, TITLE = dialogTitle, $ GROUP_LEADER = groupLeader ; Check to see if a title for the dialog was supplied. ; If not, set a default title. IF (N_ELEMENTS(dialogTitle) EQ 0) THEN $ dialogTitle='Choose a Name' ; Create the dialog. wBase = WIDGET_BASE(/COLUMN, TITLE = dialogTitle, $ GROUP_LEADER = groupLeader) wText = WIDGET_TEXT(wBase, YSIZE = 3, $ VALUE=['The original NAME is:', origName, $ 'Enter a new name:']) wEdit = WIDGET_TEXT(wBase, VALUE = origName, /EDITABLE) wSubBase = WIDGET_BASE(wBASE, /ROW) wOK = WIDGET_BUTTON(wSubBase, VALUE='OK', $ EVENT_PRO='wdSrvExample_ok') wCancel = WIDGET_BUTTON(wSubBase, VALUE='Cancel', $ EVENT_PRO='wdSrvExample_cancel') ; Create a state structure to hold important values. state = { wOK:wOK, $ wCancel:wCancel, $ wEdit:wEdit, $ pName:PTR_NEW(/ALLOCATE) } ; Store the original property name attribute in the ; state structure. *state.pName = origName ; Store the state structure in the user value of the ; top-level widget base. WIDGET_CONTROL, wBase, SET_UVALUE = state ; Realize the widget hierarchy. WIDGET_CONTROL, wBase, /REALIZE ; Call XMANAGER. XMANAGER, 'wdSrvExample', wBase ; After XMANAGER exits, retrieve the value of the name ; property attribute from the state structure. result = (N_ELEMENTS(*state.pName)) ? *state.pName : origName ; Free the pointer. PTR_FREE, state.pName ; Return the new value of the name property attribute. RETURN, result END
Discussion
It is beyond the scope of this chapter to discuss the IDL widget programming techniques used in this example. For more information on widget programming, see the Building IDL Applications manual. Several points are worth noting, however.
- The widget ID of the top-level base retrieved in the SrvExample routine is passed to this routine, and used as the value of the GROUP_LEADER keyword to WIDGET_BASE. This ensures that if the iTool itself is minimized or closed while the example dialog is displayed, it will be handled properly.
- The original value of the NAME property is passed to this routine, and is stored in an IDL pointer variable within the state structure that is associated with the dialog. This allows the event routine that actually retrieves the value entered by the user to communicate the new value back to the widget creation routine, but it also means that the pointer must be freed before the routine exits.
Event-handling Routines
The following event-handling procedures handle widget events generated by the widget interface that is displayed when the SrvExample user interface service is called.
PRO wdSrvExample_ok, event ; Get the stashed state structure from the user value ; of the top-level base widget. WIDGET_CONTROL, event.top, GET_UVALUE = state ; Get the value from the editable text field. WIDGET_CONTROL, state.wEdit, GET_VALUE = value ; Store the text value in a pointer so we can access ; it from the main routine *state.pName = value ; Destroy the dialog. WIDGET_CONTROL, event.top, /DESTROY END PRO wdSrvExample_cancel, event ; Nothing to do, just destroy the dialog. WIDGET_CONTROL, event.top, /DESTROY END
Discussion
When the user clicks the OK button, the current value of the editable text widget is placed in the pointer stored in the state structure's pName field.
Creating an Operation that Calls the Service
In order to launch the SrvExample user interface service, the user must be able to select an operation that calls the DoUIService method. This example uses an IDLitDataOperation named opName, which simply retrieves the list of currently selected items and calls the SrvExample user interface service. The code for this operation is stored in a file named opname__define.pro that is located in a directory that is included in the IDL !PATH system variable.
FUNCTION opName::Init, _REF_EXTRA = _extra ; Initialize the operation, setting the "show UI" property. ; Note that this operation will operate on all iTool ; component types. success = self->IDLitDataOperation::Init( $ NAME="Rename Component", $ DESCRIPTION="Rename an iTool component", $ /SHOW_EXECUTION_UI, TYPES='', _EXTRA=_extra) RETURN, success END FUNCTION opName::DoExecuteUI ; Get a reference to the current iTool and ; make sure it is valid. oTool = self->GetTool() IF (oTool eq OBJ_NEW()) THEN RETURN, 0 ; Get the list of selected items. selItem = oTool->GetSelectedItems() ; Call the UI service on the first item in the list ; of selected items. RETURN, oTool->DoUIService('Example Service', selItem[0]) END PRO opName__define struct = {opName, $ inherits IDLitDataOperation $ } END
Discussion
Only two methods are required: Init and DoExecuteUI. Since this operation is based on the IDLitDataOperation class, all interaction with the iTools undo/redo system is automated.
Even though all of the items that are currently selected in the iTool are retrieved by the GetSelectedItems method, only the first item is passed to the SrvExample user interface service for processing. Handling multiple selected items would require a more complicated user interface.
The process of defining an IDLitDataOperation is discussed in detail in Creating an Operation.
Registering the SrvExample Service
In order for the SrvExample user interface service to be available, it must be registered with the current iTool. The following line in the iTool's launch routine allows the service to be called with the name "Example Service":
Registering the opName Operation
To use the opName operation within an iTool, the operation must be registered in the iTool's definition. The following statement registers the operation with the name "Property Name" and places it in the Operations menu of the iTool.
Invoking the opName Operation
To use the SrvExample service, the user would launch an iTool for which the opName operation is registered, select an iTool component in the window, and select Property Name from the Operations menu.