Builder Xcessory facilitates creating the initial layout of your UI, but that's only part of the development process. Most interfaces are dynamic and include elements that change during the session, usually in response to the use of the application. This chapter examines how to use Builder Xcessory to build this behavior into your application.
Constants are Builder Xcessory representations of compile-time constants, that is,
#defines . When setting a resource value, select Constant from the Resource Placement menu to the right of the Extended Editor button. You are presented with a choice of constants that you've already defined, and <New>. Choosing <New> brings up the Constant Editor with which you can define a new constant. Builder Xcessory includes this definition in the generated source code.
You can work with your constants by using the Constant Manager (select Constants from the Browser Managers menu). Refer to Constant Manager for more information.
Note: Because constants have values, using them has an immediate effect in Builder Xcessory. Whenever you change the value of a constant with the Constant Editor, all resources that use the constant are immediately updated.
Identifiers are variables that are valid within the scope of the creation routine. When setting a resource value, select Identifier from the Resource Placement menu to the right of the Extended Editor button. You are presented with a choice of identifiers that you have already defined, and <New>.
Note: You must declare your identifiers in the application code, either in a user code block, or in an include file. You must also be sure that the identifier is declared prior to the creation of the object that references it.
Identifiers are not necessarily simple variables. You can define an identifier that is a call to a function or a method, with the appropriate return type. You can work with your identifiers by using the Identifier Manager (select Identifiers from the Browser Managers menu). See Identifier Manager for more information.
Note: Because identifiers are given values only at run time, modifying an identifier with the Identifier Editor has no immediate effect on your Builder Xcessory application.
Expressions can be used to specify an integer value for a resource. Type the expression into the value field or in the Integer Editor, as appropriate. The Placement Menu changes to reflect the presence of an expression. Expressions cannot be over-ridden by the X resource manager at run time. In this way they are functionally equivalent to Code Placement.
- expression ::= integer_value
| expression + expression
| expression - expression
| expression * expression
| expression / expression
| ( expression )
- | - expression
Note: If an expression depends on a Constant that is cut or deleted (with the Constant Manager), the expression is converted to its previously evaluated value, and written out as an integer. The Placement Menu is changed from Expr to Code to indicate this.
- The BulletinBoard toggles between red and white as each call to BxSetValuesCB resets the background resource.
Note: Use unique instance names for objects that are referenced by callbacks. Predefined callbacks rely on the instance name remaining the same each time the widget is created, and the default instance names assigned by Builder Xcessory may change when you edit the instance hierarchy.
Accessing Objects at Run Time
In C++, ViewKit, and Java, objects are declared by default as protected class members and are easy to access from within a class. To access an object from outside the class, you must define a public method, though you most likely want your method to perform any manipulation, rather than passing a widget ID out. Follow good object oriented programming practices.
How you access widget IDs when using C depends on whether the widget storage location is already declared or if you want Builder Xcessory to declare the storage location for you. If you set the storage location to Other on the Storage Location dialog (Resource Editor:Component), you are responsible for declaring and allocating the variable in your code, such as in a User Code Block, or in another file.
When you use Other storage, it is good practice to create a structure in which to store the desired widget IDs (and any other useful data). You can then pass a pointer to this structure through to the creation routine and assign the widget ID storage to the appropriate structure members. You can also pass this structure member as client_data to your callback functions, which gives you an easy way to access various widget IDs from those callback functions.
Note: All globally-defined widget IDs are stored in the constants header file.
Note: This variable is not generated by Builder Xcessory in the source code. It is assumed to be accessible within the scope of where it is referenced. In C, this is the creation routine, in UIL, the main routine. ViewKit, C++, and Java do not allow you to set a storage location for an internal class member.
You can also save the widget ID by using a createCallback. A createCallback is similar to an actual Xt widget callback, but is called from the main file after the widget is created. The parameters passed to a createCallback are the same as those passed to an Xt callback, and allow you to access the widget ID.
You may want to use this method of accessing a widget ID if you want to perform an action immediately after a widget is created. If this is not important, declaring a Local Storage Location is a simpler method.
- void createCallback(Widget w,
Note: Using createCallback in this way is similar to selecting Other from the Storage Location option menu (when you have already declared the storage location). These two methods accomplish the same task.
Hint: Accessing class member widgets from a function or method that is not part of the class is possible, but not recommended as it breaks the object oriented model.
Frequently, some objects are displayed only for short periods during the application's execution. For example, when a dialog is displayed for a particular user action and then immediately dismissed. In these cases you might want to start your application with these objects initially unmanaged, so that the application manages them only as necessary.
1. Select Code Generation Preferences from the Browser Options menu to display the Code Generation Preferences dialog (Application Panel on the C Generation Preferences Dialog ).
2. Click on the Application tab ( Application Panel on the C Generation Preferences Dialog ).
Note: This affects code generation only. The dialogs remain managed during your Build sessions.
Note: To unmanage objects on a case-by-case basis, select Hide on any object in the Resource Editor (Resource Editor:Component).
To connect your interface to the rest of your application, you must add callback procedures (for Motif) or event methods (for Java). These callbacks and event methods respond to various actions, or events, on the interface, such as a key press or window exposure.
You add a callback procedure or an event method by assigning its name to one of an object's callback or event resources. You can then edit the resource using the Resource Editor as you edit any other resource.
3. Enter the Procedure Name, select a Parameter Type, and enter the Parameter Name in the appropriate fields, hitting enter to apply the value to the callbacks list. After adding whatever other callbacks you wish to associated with the activateCallback, press Apply.
4. To add code to the callback, select it in the Callback List and press Edit. Builder Xcessory generates code and brings up your favorite editor with the correct file loaded and positioned at your new callback.
Note: You can edit only procedures that have been applied.
2. Bring up the extended editor for the ActionEvent resource ( ActionEvent Editor ).
4. To edit the code for the method, be sure that the method name has been applied, then press the Edit button to the right of the text field. Builder Xcessory generates Java code and brings up your favorite editor with the correct file loaded and positioned at your new method.
Click on the arrow button to the right of the Procedure Name field to display the list of predefined callbacks. Predefined callbacks are provided for common operations such as setting values, managing and unmanaging windows, etc. These predefined callbacks also behave correctly when Builder Xcessory is in Play Mode, allowing you to test the look of the interface without building the application. For more detailed information on these callbacks, refer to the Builder Xcessory Reference Manual .
Using Classes predefined callbacks
Predefined callbacks are especially useful for rapidly prototyping your application. They allow you to preview many common actions that are performed in your interface, during the development process when the efficient execution of the application is not as important.
For a general introduction to classes, refer to Classes . For more detailed information about using exposed resources and methods, refer to Exposing Resources and Exposing Callbacks and Event Methods .
· A private static method assigned to the widget using
XtAddCallback() . This is static because Xt is a C library, and thus cannot use a non-static method. This method is automatically named your_callback_name
The static method is passed a structure pointer that contains a pointer to the instance of the class that initiated the callback and a pointer to any client data that you specified for the callback. The static method then calls the actual class method (the real callback) and passes all of the standard Xt callback parameters (
When you expose a callback in a class, Builder Xcessory generates the two methods described previously, and a public method that adds additional callback functions to the widget. This method's name incorporates the widget's instance name and callback resource name. It uses XtAddCallback() to optionally append to, or replace, the existing callback list. Appending or replacing is controlled with the Remove Overridden Exposed Callbacks toggle on the Code Generation tab (Browser:Options:Language Settings).
Builder Xcessory also allows you to set callbacks defined by the various ViewKit components (ViewKit Callbacks). In the Resource Editor, these callbacks appear identical to Xt callbacks. However, during code generation, these ViewKit callbacks are generated only as methods of the ViewKit component and are added using VkAddCallbackMethod().
Note: Exposing methods in Java is meaningful only if the original event method, specified in the class definition, allows the event to propagate up the instance chain to the parent (original event method returns "false"). Refer to you Java documentation for more information on AWT event processing.
Using Timers, Event Handlers, and Translations
You can register and use timer procedures, work procedures, event handlers, and translations using special editors provided by Builder Xcessory. These elements are managed similarly within Builder Xcessory.
A timer procedure is a procedure invoked when a specified interval of time elapses. When a timeout event occurs, the timer callback procedure is invoked, and the callback is removed. Consequently, timeout events are invoked only once.
In ViewKit code generation, specifying a timer procedure causes Builder Xcessory to create an instance of the VkPeriodic class. This class calls the timer procedure repeatedly until your application stops it. For more information on this class, refer to the VkPeriodic manpage.
Use a timer procedure for an event that you want to happen after a specific time interval. When the timer procedure is registered, Xt first waits for at least the interval you specified, and then calls the timer procedure. Builder Xcessory generates code to register the timeout in the main program.
- Interval specifies the number of milliseconds that should elapse before this function is invoked. After this period elapses, the procedure's callback is invoked by the Xt Intrinsics. The Parameter field specifies client data to pass to the procedure XtAppAddTimeOut.
A work procedure is a callback that provides a limited form of background processing. The Xt Intrinsics invoke a work procedure whenever there are no events pending. Thus whenever the application is not drawing to the display or responding to user actions, the work procedure is called.
Note: Although you can define multiple work procedures, only the most recently registered is called.
Use a work procedure to specify a function to call when no other events are pending. Once a work procedure is called, the program cannot process any events until the procedure returns. Therefore, any work procedure should be a function that executes quickly.
To perform a long calculation with work procedures, set the calculation as an iterative process so that a small portion of the calculation can be done each time the work procedure is called. This approach avoids freezing the interface.
When you specify work procedures and generate code for ViewKit, Builder Xcessory creates a subclass of the VkBackground component for each work procedure you have specified. Each work procedure class is instantiated and started in the main() routine, before the call to VkApp::run().
Sometimes an object does not provide a callback for an X event that you want to respond to in your application. For example, the XmDrawingArea widget does not have a callback for when the user moves the mouse with a mouse button held down. You must add an event handler to the eventHandler resource on the XmDrawingArea object.
3. Enter the Handler Name, the Event Mask, the value of Non-Maskable, and the Parameter Type and Value in their associated fields. The Event Mask specifies the events that trigger the event handler. Non-Maskable is True if the handler is to be triggered on non-maskable events (that is, events that cannot be specified by the Event Mask, for example, GraphicsExpose, SelectionNotify, or ClientMessage), and is otherwise False. The Parameter specifies client data to pass to the procedure XtAppAddTimeOut.
A translation links a sequence of one or more events to an action, the function called when these events are received. You can add translations that include actions already registered for the object, or you can add a translation based on additional actions that you must register in your code before creating any object that references them.
· Click the (...) button to the right of the translations resource's text field to display the Translation Table Editor (Translation Table Editor), and enter the translation.
Note: Builder Xcessory displays a warning if you modify an object's Translation Table and reference an action that you plan to add. However, the action works correctly in your code, provided that the action is registered before you create the object whose translation table references it.