UIL also supports the private storage specifier. This specifier allows you to restrict the use of a widget definition to
the module in which it occurs. The static storage class specifier in C has the same effect on C functions and
variables. As of Motif 1.2, however, widgets defined as private can still be accessed from other modules. Although
the private storage specifier is rarely used, you can specify it if you want to protect access to private widgets
(assuming the problem will be fixed), or if you want to explicitly indicate that a widget should not be referenced
elsewhere.
25.2.3 The Widget Creation Process
Now that you know how to define widgets in a UIL module, we can take a closer look at how to create widgets at
run−time using MrmFetchWidget(). In Chapter 22, Introduction to UIL, we showed you the basics of using
MrmFetchWidget() to create a widget or a widget hierarchy. As a reminder, this function takes the following
form:
Cardinal
MrmFetchWidget(hierarchy, widget_name, parent, widget_return,
class_return)
MrmHierarchy hierarchy;
String widget_name;
Widget parent;
Widget *widget_return;
MrmType *class_return;
The hierarchy argument is an MrmHierarchy that has been opened with
MrmOpenHierarchyPerDisplay(). The widget_name parameter is the name of the widget to fetch. The
parent argument is the parent of the widget that is to be created. On success, widget_return contains the
widget ID of the widget and class_return contains the internal UIL class code for the widget.
You can also fetch a widget by calling MrmFetchWidgetOverride(), which lets you override resource settings
in the application. This routine takes the following form:
Cardinal
MrmFetchWidgetOverride(hierarchy, widget_name, parent, override_name,
arg_list, num_args, widget_return, class_return)
MrmHierarchy hierarchy;
String widget_name;
Widget parent;
String override_name;
ArgList arg_list;
Cardinal num_args;
Widget *widget_return;
MrmType *class_return;
The override_name argument lets you specify a name for the widget that differs from widget_name.
widget_name is used only to look up the widget definition. If override_name is NULL, widget_name is used
for the name. The arg_list and num_arg parameters specify a standard array of Xt resource name−value pairs.
Any resources specified in this list override those specified in the widget definition from the UIL module. The rest of
the parameters are the same as for MrmFetchWidget().
For each of these functions, Mrm first makes sure that the hierarchy specified is valid and open. If you supply an
invalid hierarchy to a function, it immediately fails and returns MrmBAD_HIERARCHY. Assuming the
hierarchy is valid, the two routines use the widget creation algorithm illustrated in the figure and described in the
following sections.
25 Creating a User Interface With UIL25.2.3 The Widget Creation Process
667
Widget creation algorithm
Mrm begins the widget creation process by searching for the widget definition in the UID files associated with the
hierarchy. The files are searched in the same order as they appear in the array passed to
MrmOpenHierarchyPerDisplay(). The search order matters when two widgets with the same name are
defined in different files, as Mrm uses the first definition that it finds. Once Mrm locates the widget definition, it reads
it from the UID file and moves on to the next step. If Mrm cannot find the widget after looking in each file, it prints a
warning message by calling XtAppWarning().
If the missing widget is at the root of the hierarchy that the application is fetching, MrmFetchWidget() returns a
status of MrmNOT_FOUND. But if the missing widget is one of its descendents, the widget hierarchy creation process
continues, minus one widget. While a failure to create a child widget is bound to cause problems for your application,
MrmFetchWidget() unfortunately returns MrmSUCCESS as long as the top−level widget is created. Before Mrm
creates a widget, any resource or callback settings are put into an ArgList. Many resource settings, such as colors
and fonts, are created and maintained by the X server, which means that they cannot be stored in a UID file. Instead,
descriptions of these values are stored in the UID file. Mrm creates the actual values at run−time based on these
descriptions. Other values, such as integers, strings, and XmStrings, are read from the UID file and placed directly
into the ArgList. Mrm also converts callback names stored in the UID file to function pointers that the application
registered by calling MrmRegisterNames() or MrmRegisterNamesInHierarchy().
If for any reason Mrm cannot create a resource value or cannot find a the specific resource or callback and prints a
warning message using XtAppWarning(). This type of failure does not prevent Mrm from creating the widget, and
the status returned by MrmFetchWidget() or MrmFetchWidgetOverride() does not indicate that a problem
occurred.
If you are fetching a widget with MrmFetchWidgetOverride(), callback function pointer to match a callback
name, it does not set the ArgList you pass to this function is appended to the internally generated ArgList of the
top−level widget. Override arguments do not affect any widgets further down in the hierarchy. Since Xt uses the last
25 Creating a User Interface With UIL25.2.3 The Widget Creation Process
668
occurrence of a resource or callback setting in an ArgList to set the value, the settings from the application program
override any settings specified in the widget definition. You can also override widget resource settings after a widget
is created by using MrmFetchSetValues(), which is described in Section #suilfetch. Now Mrm calls the widget
creation function corresponding to the class of the widget. For the built−in Motif widgets, Mrm uses the Motif
convenience functions, such as XmCreatePushButton(). Some widgets, like the FileSelectionBox, create their
own children at the time they themselves are created. Mrm is aware of these children, but is not responsible for their
creation. For user_defined widgets, Mrm calls the creation procedure that you specified when registering the
widget. (User−defined widgets are described in Section #suiluserdef.) Mrm does not manage the widget at this point
in the procoess. In addition to the callbacks that are part of each widget, Mrm and UIL support a special creation
callback, MrmNcreateCallback, which is invoked by Mrm immediately after the widget is created. In the case of
an automatically−created child, the callback is invoked after its resources are set. The widgets are not aware of the
callback, since it is handled directly by Mrm. The MrmNcreateCallback takes the same form as any other
callback and is specified in the callbacks subsection of a widget definition. The client_data argument is an
XmAnyCallbackStruct, which is defined in <Xm/Xm.h> as follows:
typedef struct {
int reason;
XEvent *event;
} XmAnyCallbackStruct;
The reason field is always set to MrmCR_CREATE, and the event pointer is always NULL. You can use this
callback to handle almost anything you would normally do in a standard Xt program after creating a widget. At this
point, the widget creation process becomes recursive. If the newly−created widget has any children specified in its
controls subsection, Mrm creates them now. Mrm uses the process just described to create each of the children.
Automatically−created children are also processed recursively so that Mrm can handle any resources or callbacks
specified in the UIL file. Instead of creating an automatically−created child in the widget creation step, Mrm just sets
the resources and callbacks using the XtArgList for the child.
The recursive nature of the widget creation process allows you to create, with a single function call, a user interface
that consists of an arbitrarily large widget hierarchy. This behavior is what makes MrmFetchWidget() and
MrmFetchWidgetOverride() so powerful. As we mentioned earlier, if Mrm cannot create a child widget, it
prints a warning message using XtAppWarning() and continues with the next child. In general, both fetch
functions continue working through just about any type of failure, short of not finding the definition of the top−level
widget in the hierarchy. If any children have been created, Mrm now manages them. Mrm manages all non−Shell
children that are part of the controls subsection of the parent widget, unless they are declared as unmanaged.
Since the creation process is recursive, any children of the widgets that are being managed have been managed
previously. The top−level widget that is being fetched is not managed by Mrm because the management step only
applies to the children of a widget. After all of the widgets in the hierarchy have been created, there may still be some
resources that Mrm needs to set because UIL allows you to make forward references to widgets. As a result, you can
specify widgets in resource settings and as callback arguments without worrying about the creation order of the
widgets involved. If you reference a widget before it is defined, Mrm cannot resolve the reference when it is
encountered. To handle this situation, Mrm remembers the reference and resolves it once all of the widgets in the
hierarchy have been created.
The ability to use forward references makes UIL quite flexible. One situation where this feature is useful is when you
create an interface that uses the Form widget. With UIL, you can specify complex Form attachments without having
to worry about the creation order of the widgets. The one limitation to this feature is that it only works within a single
call to MrmFetchWidget(). During a call to MrmFetchWidget(), Mrm maintains a list of the widgets that have
been created, which means that you can only reference a widget that is part of the hierarchy created by the current call.
If you need to set a resource to a widget in another hierarchy, you can set it using the MrmNcreateCallback or set
it after the hierarchy has been created. After the entire hierarchy has been created, Mrm returns the widget ID of the
25 Creating a User Interface With UIL25.2.3 The Widget Creation Process
669
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.