The item is a CascadeButton, which is usually associated with a pullright menu. The value takes two
additional parameters: a compound string label and a mnemonic. Pullright menus are, ironically, easier to
implement and manage using the not−so−simple menu creation routines described in Chapter 15, Menus.
XmVaSEPARATOR
The item is a Separator and it does not take any additional parameters. Since separators cannot be selected, the
callback routine is not called for this item. Adding a separator does not affect the item count with respect to
the client_data values that are passed to the callback routine for other menu items.
XmVaSINGLE_SEPARATOR
This value is identical to XmVaSEPARATOR.
XmVaDOUBLE_SEPARATOR
This value is identical to XmVaSEPARATOR, except that the separator widget displays a double line instead of
a single line.
XmVaTITLE
The item is a Label that is used to create a title in a menu. It takes one additional parameter: a compound
string label. The item is not selectable, so it does not have a mnemonic associated with it and it does not call
the callback routine. Adding a title does not affect the item count with respect to the client_data values
that are passed to the callback routine for other menu items.
Just as with the CascadeButtons in a MenuBar, the labels associated with each menu item are not the names of
the widgets themselves. The names of the buttons are button_n, where n is the position of the button in the
menu (starting with zero). Similarly, the names of the separators and the titles are separator_n and
label_n, respectively. We will discuss how you can use resources to specify labels, mnemonics, and
accelerators for menus and menu items later in the chapter.
Menus are not intended to be changed dynamically. You should not add, delete, or modify the menus on the
MenuBar or the menu items in PulldownMenus once an application is running. Rather than delete an item on
a menu when it is not appropriate, you should change the sensitivity of the item using XmNsensitive. The
menus in an application should be static in the user's eyes; changing the menus would be like changing the
functionality of the program while the user is running it. The one exception to this guideline involves menu
items that correspond to dynamic objects. For example, if you have a menu that contains an item for each
application that is running on a display, it is acceptable for the items on the menu to change to reflect the
current state of the display.
5.2.2 SimpleMenu Callback Routines
The callback routine associated with the File menu shown earlier is invoked whenever the user selects any of the
buttons in the menu. Just like any callback, the routine takes the form of an XtCallbackProc:
void
file_cb (widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
The widget parameter is a handle to the widget that was selected in the menu. The -client_data parameter is the
index of the menu item in the menu. The call_data parameter is a pointer to a callback structure that contains data
about callback. Both the -client_data and call_data parameters should be cast to their appropriate types
5 The Main Window 5.2.2 SimpleMenu Callback Routines
90
before the data that they contain is accessed.
Every Motif callback routine has a callback structure associated with it. The simplest such structure is of type
XmAnyCallbackStruct, which has the following form:
typedef struct {
int reason;
XEvent *event;
} XmAnyCallbackStruct;
All of the Motif callback structures have these two fields, but they also contain more detailed information about why
the callback function was invoked. The callback routine for the File menu would be passed an
XmPushButtonCallbackStruct, since all of the menu items are PushButtons. This structure has the following
form:
typedef struct {
int reason;
XEvent *event;
int click_count;
} XmPushButtonCallbackStruct;
The click_count field is not normally used when a PushButton is in a menu. If one of the items in the menu were
a ToggleButton, the call_data parameter would be of type XmToggleButtonCallbackStruct, which has
the following form:
typedef struct {
int reason;
XEvent *event;
int set;
} XmToggleButtonCallbackStruct;
The set field indicates whether the item was selected (turned on) or deselected (turned off).
When a menu contains both PushButtons and ToggleButtons, you can determine which of the two callback structures
the call_data parameter points to by examining the reason field. Since all callback structures have this field, it
is always safe to query it. As its name implies, this field indicates why the callback routine was invoked. The value of
this field may also indicate the type of the widget that invoked the callback. While we can always determine the type
of the widget parameter by using the macro XtIsSubClass(), using the reason field is more straightforward.
The PushButton widget uses the value XmCR_ACTIVATE to indicate that it has been activated, while the
ToggleButton uses XmCR_VALUE_CHANGED to indicate that its value has been changed. In our example, the
reason will always be XmCR_ACTIVATE, since there are only PushButtons in the menu. If there were also
ToggleButtons in the menu, we would know that the callback was invoked by a ToggleButton if the value were
XmCR_VALUE_CHANGED.
The event field in all of the callback structures is a pointer to an XEvent structure. The XEvent identifies the
actual event that caused the callback routine to be invoked. In this example, the event is not of particular interest.
In the callback function, you can choose to do whatever is appropriate for the item that was selected. The callback
structure is probably not going to be of that much help in most cases. However, the client_data passed to the
function can be used to identify which of the menu items was selected. The following code fragment demonstrates the
use of -client_data:
/* a menu item from the "File" pulldown menu was selected */
5 The Main Window 5.2.2 SimpleMenu Callback Routines
91

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.