/* cb.uil − Plain and simple callback setting example. */
module cb
procedure
print (string);
quit();
object Hello : XmPushButton {
callbacks {
XmNactivateCallback = procedure print ("hello!");
};
};
object Goodbye : XmPushButton {
callbacks {
XmNactivateCallback = procedures {
print ("goodbye!");
quit();
};
};
};
object root : XmRowColumn {
controls {
XmPushButton Hello;
XmPushButton Goodbye;
};
};
end module;
The callback declarations in the procedure section tell the UIL compiler that the procedures are defined externally
in the application program. A callback setting looks similar to a resource setting; it always begins with the name of a
callback, such as XmNactivateCallback, and is followed by an equal sign. The right−hand side of the setting
varies depending on the number of callback procedures you are specifying. A single callback is specified with the
keyword procedure followed by the callback invocation. Multiple callbacks are specified with the keyword
procedures followed by a list of callback invocations.
In the source code the XmNactivateCallback of the Hello PushButton is set to the single callback procedure
print(), while the XmNactivateCallback of the Goodbye PushButton is set to the two callbacks print()
and quit(). You cannot specify multiple callbacks by setting the same callback more than once because when you
set the same resource or callback multiple times, only the last setting is used. The Xt specification doesn't guarantee
the order in which callbacks are called, as widgets can reorder callback lists internally. In nearly all cases, however,
callbacks are called in the order that they are listed.
As with resource settings in an arguments section, the UIL compiler makes sure that the callbacks you set in a
callbacks subsection exist and are supported by the widget. When you add callbacks in application code, there is
nothing to prevent you from setting a callback on a widget that does not support it. This problem is not caught at
compile−time or run−time by Xt.
25.2.2 Sharing Widgets Among Modules
When the source code for an application grows beyond a certain size, you normally split it into multiple source files.
You can use the same technique to divide an interface description among multiple UIL modules. When you use this
technique, one module must often reference a widget that is defined in another module. UIL supports this technique
25 Creating a User Interface With UIL25.2.2 Sharing Widgets Among Modules
665
by allowing you to export a widget definition from one module and import, or reference, the definition in another
module. A widget definition is exported by using the optional exported storage specifier before the widget type
name in the definition, as shown in the source code
/* first.uil − First half of a two−module interface description. */
module first
object top : exported XmText { };
end module;
An exported definition looks and acts just like a regular definition. The difference is that you can access an
exported widget in another module by declaring it with the imported storage class specifier. This technique is
illustrated in the source code which imports the top widget from the source code
/* second.uil − Second half of a two−module interface description. */
module second
object top : imported XmText;
object bottom : XmPushButton { };
object root : XmPanedWindow {
controls {
XmText top;
XmPushButton bottom;
};
};
end module;
Since the imported declaration refers to a widget defined elsewhere, you cannot specify attributes for the widget
and must end the declaration immediately after the type name, as shown in this example. You can think of an
imported widget declaration as having the same meaning as an extern variable declaration in C. Collectively, the
two modules describe the same interface as the source code After compiling these two modules, you can view the
interface with the following command:
showuid first second
Placing a single widget in a separate file, as we've done in this example, is clearly a trivial example of sharing
widgets. This technique makes more sense when you are creating a larger interface for a real application. You can see
a more realistic example of sharing widgets in Chapter 25, Building an Application With UIL.
Widget definitions, like top−level variable definitions in C, are global by default, which means that you really don't
need to use the exported storage specifier. However, we recommend using it when you plan to reference a widget
in another module because it clearly indicates which widget definitions you expect to use elsewhere. When you import
a widget, UIL assumes that the widget class in the imported declaration matches the class of the widget definition.
If you make a mistake and import a widget that is different from its declared class, you defeat the compiler's
type−checking of the imported widget and may run into problems at run−time. Although some of the Motif managers
can detect an attempt to create an unsupported child, you should ensure that your widget definitions and declarations
match rather than relying on possible run−time detection.
25 Creating a User Interface With UIL25.2.2 Sharing Widgets Among Modules
666

Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.