When you add components to the interface, you can build on this base style. The following fragment shows how you
might handle defining a ToggleButton−specific style:
list toggle_btn_style : arguments {
arguments base_style;
XmNindicatorSize = 10;
XmNindicatorType = XmN_OF_MANY;
XmNselectColor = color ('yellow');
};
Unfortunately, it turns out that most of the resource settings that work well in these situations are best left to resource
files, as we discussed in the previous section. This use of lists can still be useful, however, when you are prototyping
an application and don't feel like using an X resource file. When you are done prototyping, be sure to move the
resource settings that affect appearance to a resource file, so that they can be modified by the user.
You can also use a hierarchy of lists to specify callback resources. If you are developing an application that supports
context sensitive help, the root of your callback hierarchy might be specified as in the following list:
list help_cbs : callbacks {
XmNhelpCallback = procedure help();
};
You can include this list in each widget that supports help. For a group of ToggleButtons, you can augment the list as
follows:
list toggle_cbs : callbacks {
callbacks help_cbs;
XmNvalueChangedCallback = procedure toggle_changed();
};
The following widget definition illustrates how both the style and callback lists might be used:
object hot_fudge : XmToggleButton {
arguments {
arguments attach_args;
arguments toggle_args;
XmNlabelString = "Hot Fudge";
};
callbacks toggle_cbs;
};
You gain a couple of advantages by using lists this way. First, if you decide to change a color or a callback, you only
need to make the change in one place, not in every widget definition. Second, each widget definition is considerably
shorter than it would be without the list, which saves typing and generally makes a module shorter and easier to read.
27.4.2 Reusing Components
You can also use lists to help create reusable components. Earlier in this chapter, we talked about reusing components
for top−level windows and dialogs. Although reusing parts of a dialog is not very common, reusing the panel of
buttons that compose the action area of a dialog makes some sense. An application may use the definitions of OK,
Cancel, and Help PushButtons repeatedly. Using lists, you can create a hierarchy of include files that allows you to
reuse the same definitions for each dialog that needs them.
27 Advanced UIL Programming 27.4.2 Reusing Components
732
The first thing that needs to be defined is a container widget to hold the buttons. We keep this example simple by
using a RowColumn manager widget. the source code shows the definition of the RowColumn.
! btn_panel.uih −− Button panel container
object button_panel : XmRowColumn {
controls buttons;
arguments {
XmNorientation = XmHORIZONTAL;
XmNpacking = XmPACK_COLUMN;
XmNentryAlignment = XmALIGNMENT_CENTER;
! Assume bottom of form placement
XmNleftAttachment = XmATTACH_FORM;
XmNrightAttachment = XmATTACH_FORM;
XmNbottomAttachment = XmATTACH_FORM;
! Provide a hook for additional arguments
arguments button_panel_args;
};
};
The button_panel RowColumn is an open−ended definition, as the children are specified as an undefined list. The
definition also contains an undefined list in its arguments subsection, which allows the specification of additional
resources. The next step is to add the OK, Cancel, and Help buttons to the panel using another include file, which is
shown in the source code
! three_btn.uih −− OK, Cancel, Help button definitions
list buttons : controls {
OK : XmPushButton {
arguments ok_args;
callbacks ok_cbs;
};
Cancel : XmPushButton {
arguments cancel_args;
callbacks cancel_cbs;
};
Help : XmPushButton {
arguments help_args;
callbacks help_cbs;
};
! Hook for additional buttons
controls more_buttons;
};
include file 'btn_panel.uih';
So far, all of the widget definitions have been placed in include files. This technique is necessary because UIL does
not support imported list values, so the only way you can reuse lists is by placing them in include files. We also define
the PushButtons in an include file because they reference callback and argument lists. These lists must be defined by
the module that includes the button definition. If the buttons were defined in a separate module, there would be no
way to specify their behavior from within UIL.
The three_btn.uih file defines the three buttons for the panel and defines the controls list referenced in
btn_panel.uih. An important feature of this example is that we have incorporated undefined lists in each of the
widget's callbacks and arguments subsections. These lists work like macros in that they allow a module to use
customized versions of the standard definitions. We also keep the list of buttons open−ended by including another
undefined controls list named more_buttons. The file ends by including the button panel definition so that the
27 Advanced UIL Programming 27.4.2 Reusing Components
733
main module does not need to include it. We normally recommend putting the include directives at the top of a file,
but in early releases of Motif 1.2, a forward reference to a list causes the UIL compiler to crash. Therefore, it is
necessary to include object definitions after the lists that they reference.
Now that the button panel and button definitions are complete, we can create a dialog that uses them. the source code
demonstrates the creation of such a dialog.
/* dialog.uil − a simple dialog that contains reusable PushButtons */
module dialog
include file 'procedures.uih';
object root : XmForm {
controls {
XmRowColumn dialog_contents;
XmSeparator separator;
XmRowColumn button_panel;
};
arguments {
XmNdialogTitle = "Login";
XmNdefaultButton = OK;
};
};
object dialog_contents : XmRowColumn {
controls {
User : XmLabel { };
Password : XmLabel { };
XmTextField user_field;
XmTextField pw_field;
};
arguments {
XmNnumColumns = 2;
XmNpacking = XmPACK_COLUMN;
XmNtopAttachment = XmATTACH_FORM;
XmNleftAttachment = XmATTACH_FORM;
XmNrightAttachment = XmATTACH_FORM;
XmNbottomAttachment = XmATTACH_WIDGET;
XmNbottomWidget = separator;
};
};
object user_field : XmTextField {
arguments {
XmNcolumns = 2;
};
};
object pw_field : XmTextField {
arguments {
XmNcolumns = 2;
};
};
object separator : XmSeparator {
arguments {
XmNrightAttachment = XmATTACH_FORM;
XmNleftAttachment = XmATTACH_FORM;
XmNbottomAttachment = XmATTACH_WIDGET;
27 Advanced UIL Programming 27.4.2 Reusing Components
734
XmNbottomWidget = button_panel;
};
};
! Button specific settings.
list ok_args : arguments { };
list ok_cbs : callbacks {
XmNactivateCallback = procedure do_it();
};
list cancel_args : arguments { };
list cancel_cbs : callbacks {
XmNactivateCallback = procedure forget_it();
};
list help_args : arguments { };
list help_cbs : callbacks {
XmNactivateCallback = procedure help_me();
};
! No additional button panel arguments
list button_panel_args : arguments { };
! No more buttons
list more_buttons : controls { };
! Include the button panel definition
include file 'three_btn.uih';
end module;
The module starts by including the files that contain the callback procedure declarations. The top−level Form of the
dialog contains the work area, a separator, and the button_panel. The work area consists of two labeled
TextFields in a RowColumn. We complete the button_panel by defining the lists referenced in the include files.
The arguments and callbacks lists for the OK, Cancel, and Help buttons are defined. There are no additional
arguments for the buttons, the arguments lists are empty. Since there are no additional button_panel arguments
and the dialog only has three buttons, the button_panel_args and more_buttons lists are also empty. With
these list definitions in place, the module finally includes the file that defines the buttons and the button panel. The
output of the dialog is shown in the figure.
You can reuse the button panel in as many dialogs as you want by following the model used in the source code
Although we did not use many of the undefined lists, they make the button panel more flexible and configurable.
These techniques can also be applied in a number of other situations throughout an application. This method of using
lists and include files can help to reduce redundancy in an interface definition.
27 Advanced UIL Programming 27.4.2 Reusing Components
735

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.