Activating Your Interface

Overview

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.

Initializing Resources at Run Time

Using variables as resource values

The simplest way to be able to set resources at run time is to use variables as resource values. Builder Xcessory provides three easy methods of using variables as resource values:

· Constants

· Identifiers

· Expressions

Constants

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.

Constant Manager

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

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>.

Choosing <New> brings up the Identifier Editor, with which you can define a new identifier:

Identifier Editor


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

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.

The syntax for a Builder Xcessory expression is:

expression ::= integer_value
| constant_name
| expression + expression
| expression - expression
| expression * expression
| expression / expression
| ( expression )
| - expression

Expressions are evaluated from left to right. Standard order of precedence is enforced for binary operator expressions.


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.

Callbacks with XtSetValues Calls

You can dynamically change a resource value using the X Toolkit call, XtSetValues. Builder Xcessory includes the predefined callback BxSetValuesCB, which takes the following string as its parameter:

"<instance_name>.<resource>=<value>
<instance_name>.<resource>=<value>
...
<instance_name>.<resource>=<value>"

When the callback is called, the resources of the designated object are set to the specified values by using the function XtSetValues.

Example

The following example demonstrates a simple use of BxSetValuesCB:

1. Create a BulletinBoard with two PushButton children.

2. Set the activateCallback resource of pushButton to BxSetValuesCB("bulletinBoard.background=red").

3. Set the activateCallback resource of pushButton1 to BxSetValuesCB("bulletinBoard.background=white").

4. Enter Play Mode(Browser:View).

5. To test the interface, click the PushButtons.

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

To manipulate an object at run time, you must have access to it. How you choose to access the object depends on the language in which you plan to generate code.

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.

In C, you can use one of the following methods:

· Set the storage location

· Set createCallback

· Use the class record

· Call Xt functions

If you are generating UIL, you can specify the widget ID with the widget name using MrmFetchWidget.

Setting the storage location

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.

Declaring storage location in Builder Xcessory

If you want Builder Xcessory to declare global storage, follow these steps:

1. Select Storage Location from the Resource Editor Code menu.

2. Select Global from the Storage Location option menu.

Selecting Global tells Builder Xcessory to set up the widget storage location, as well as assign the widget ID's value. This also causes the constants file to be generated.


Note: All globally-defined widget IDs are stored in the constants header file.

Declaring storage location in code

If you have declared the storage location in the code, follow these steps:

1. Select Storage Location from the Resource Editor Component menu to display the Storage Location dialog:

Storage Location Dialog

2. Select Other from the Scope text field on the Storage Location dialog

3. Enter the variable to which Builder Xcessory should assign the ID.


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.

Setting createCallback

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.

Example

A creation callback might look like the following:

void createCallback(Widget w,
XtPointer client_data,
XtPointer call_data)
{
Widget *assign=(Widget*)client_data;
*assign=w;
}

where:

client_data is a variable or structure in which the widget ID is stored.

w is the widget that has just been created.

assign passes the address in which the widget's ID is stored.


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.

Using the Class Record

You can access widget IDs by using the structure that Builder Xcessory generates for each class when you are working in C.


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.

Calls to Xt Functions

You can also use the Xt function, XtNameToWidget, to obtain the widget ID. Although inefficient, this method is an effective way of obtaining the widget ID of a compound widget child.

MrmFetchWidget

If you are generating UIL, you can obtain the widget ID by calling MrmFetchWidget on the widget name.

Managing and Unmanaging Objects

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.

Setting dialogs as initially unmanaged

To set dialogs as initially unmanaged, follow these steps:

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 ).

3. Set (Parented) Dialog Shells Initially Unmanaged.

Parented dialogs are now unmanaged by default.

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).

Application Panel on the C Generation Preferences Dialog

Callback Procedures and Event Methods

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.

Adding callbacks and methods

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.

To add a callback as the activateCallback of a push button, follow these steps:

1. Update the Resource Editor for the push button.

2. Click the (...) button to the right of the activateCallback text field to display the Callback Editor:

Callback Editor

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.

Adding an event method

To add an event method for the ActionEvent of a Java push button, follow these steps:

1. Update the Resource Editor for the push button.

2. Bring up the extended editor for the ActionEvent resource ( ActionEvent Editor ).

ActionEvent Editor

3. Enter the procedure name in the ActionEvent Editor's text field, and apply the value to the resource (Apply).

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.

Predefined Callbacks

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

To set a callback resource to a predefined callback, follow these steps:

1. Display the Callback Editor for the appropriate resource.

2. Click on the arrow button to display the list of predefined callbacks.

3. Click on a predefined callback on the list.

4. Apply the contents of the Callback Editor to the resource.

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.

Using Callbacks in C++ Classes

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 .

Adding callbacks to classes

Whenever you add a callback to an object within a class, Builder Xcessory generates two 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 Callback(Widget, XtPointer, XtPointer) .

· A protected virtual method containing the actual code for your callback. This method is given the name you specified for the callback, your_callback_name (Widget, XtPointer, XtPointer) .

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 ( w , client_data , call_data ).

Exposing callbacks

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().

Using Event Methods in Java Classes

For a general introduction to classes, refer to Classes . For a detailed discussion of using exposed resources and methods, refer to Exposing Resources and Exposing Callbacks and Event Methods .

Adding event methods to classes

When you add an event method to an object within a class, Builder Xcessory adds your routine as a public method.

Exposing event methods

When you expose an event method in a class, you can then specify an additional method (on a per instance basis) to be called in response to the event.


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.

Timer Procedures

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.

Using timer procedures

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.

Refer to O'Reilly & Associates, Definitive Guides to the X Window System, Volumes 4 and 5 for a full description of timer procedures and the XtAppAddTimeOut call.

Adding timer procedures

To add a timer procedure, follow these steps:

1. Select Application from the Browser Managers menu to display the Application Manager.

2. Click on the (...) button next to the Timer Procedures input field in the Application Manager to display the Application Timer Procedures Editor:

Application Timer Procedures Editor

3. Click on New.

4. Enter the name of the timer procedure to be called after the interval expires, along with the interval, the parameter type, and the parameter (data) in their associated fields.

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.

5. Click on Apply to register the timer procedure.

All current timer procedures are displayed in the window above these fields.

Removing timer procedures

To remove a timer procedure, follow these steps:

1. Select the procedure from the list displayed in the Application Timer Procedures Editor

2. Click Delete.

The procedure is removed from the list and from your application.

Work Procedures

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.

Using work procedures

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.

Example

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().

Refer to O'Reilly & Associates, Definitive Guides to the X Window System, Volumes Four and Five for a full description of work procedures and the XtAppAddWorkProc call.

Adding work procedures

To add a work procedure, follow these steps:

1. Select Application from the Browser Managers menu to display the Application Manager.

2. Click on the (...) button next to the Work Procedures input field in the Application Manager to display the Application Work Procedures Editor:

:

Application Work Procedures Editor

3. Click on New.

4. Enter the name of the WorkProcedure, the Parameter Type, and the Parameter Value in their associated fields.

5. Click on Apply to register the work procedure.

All current work procedures are displayed in the scrolled window above these fields.

Registering a work procedure causes a call to XtAppAddWorkProc to be inserted in the main program.

For ViewKit code generation, a VkBackground subclass is instantiated.

Removing work procedures

To remove a work procedure, follow these steps:

1. Select Application from the Browser Managers menu to display the Application Manager.

2. Select the work procedure from the list displayed in the Application Work Procedures Editor.

3. Click on Delete.

The work procedure is removed from the list and from your application.

Event Handlers

An event handler specifies functions called when an X/Motif event is received by the window associated with the object for which the event handler is set.

Example

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.

Refer to O'Reilly & Associates, Definitive Guides to the X Window System, Volumes Four and Five for a full description of event handlers and the XtAddEventHandler call.

Adding event handlers

To add an event handler, follow these steps:

1. Click on the (...) button next to the eventHandler resource on the Resource Editor to display the Event Handler Editor:

Event Handler Editor

2. Click on New.

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.

4. Click on Apply to register the event handler.

Builder Xcessory inserts a call to XtAddEventHandler in the file in which the widget is created. All current event handlers are displayed in the scrolled window above these fields.

Removing event handlers

To remove an event handler, follow these steps:

1. Select the event handler from the list displayed in the Event Handler Editor.

2. Click Delete.

The event handler is removed from the list and from your application.

Translations

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.

Using translations

Most objects provide a large number of actions that are triggered by key presses, mouse actions, and so forth. In most cases, you only add translations to an object to augment its behavior.

Example

Support for Motif drag and drop is added to objects with an action. You must modify a new object's translation table to add drag and drop support.

Adding translations

To add a translation to an object, use one of the following methods:

· Enter the translation in the translations resource text field on the Resource Editor.

· 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.

Translation Table Editor

When you apply the contents of the Translation Table Editor to an object's translations resource, Builder Xcessory replaces the object's Translation Table with the translations you have provided.


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.

 

Documentation: