coordinates specified in the event data structure. The menu is then popped up using XtManageChild(). As far as
Xt is concerned, this method for popping up a menu is technically incorrect. It is supported by the Motif toolkit to
simplify the PopupMenu interface. For more information, see the discussion on popping up dialog boxes in
Chapter 5, Introduction to Dialogs. The menu contains four items, the last of which has the accelerator
Ctrl<Key>C. Any time the user presses CTRL−C in the application, the callback routine associated with the menu
is called as if the menu had been popped up and the Exit item had been selected. The popup_cb() routine either
prints the name of the menu item or exits, depending on which item the user selected. Note that the name of the menu
item does not correspond to its label. As described in Chapter 4, The Main Window, menu items are automatically
given names of the form button_n, where n is assigned in order of menu item creation, starting at 0 (zero).
16.2.2 Cascading Menus
A cascading menu, or a pullright menu, is implemented as a PulldownMenu displayed from a menu item in another
PulldownMenu or PopupMenu that is already displayed. The menu item that posts the cascading menu must be a
CascadeButton. the source code demonstrates how to add a cascading menu using the simple menu routines. The
program adds a Line Width menu item to the PopupMenu from the source code This menu item is a CascadeButton
that posts a PulldownMenu created with XmVaCreateSimplePulldownMenu(). XtSetLanguageProc() is
only available in X11R5; there is no corresponding function in X11R4. XmStringCreateLocalized() is only
available in Motif 1.2; XmStringCreateSimple() is the corresponding function in Motif 1.1.
/* simple_pullright.c −− demonstrate how to make a pullright menu
* using simple menu creation routines. Create a main window that
* contains a DrawingArea widget that displays a popup menu when the
* user presses the third mouse button.
*/
#include <Xm/RowColumn.h>
#include <Xm/MainW.h>
#include <Xm/DrawingA.h>
main(argc, argv)
int argc;
char *argv[];
{
XmString line, square, circle, weight, exit, exit_acc;
XmString w_one, w_two, w_four, w_eight;
Widget toplevel, main_w, drawing_a, cascade, popup_menu, pullright;
void popup_cb(), set_width(), input();
XtAppContext app;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
/* Create a MainWindow widget that contains a DrawingArea in
* its work window.
*/
main_w = XtVaCreateManagedWidget ("main_w",
xmMainWindowWidgetClass, toplevel,
XmNscrollingPolicy, XmAUTOMATIC,
NULL);
/* Create a DrawingArea −− no actual drawing will be done. */
drawing_a = XtVaCreateManagedWidget ("drawing_a",
xmDrawingAreaWidgetClass, main_w,
XmNwidth, 500,
XmNheight, 500,
NULL);
16 Menus 16.2.2 Cascading Menus
437
line = XmStringCreateLocalized ("Line");
square = XmStringCreateLocalized ("Square");
circle = XmStringCreateLocalized ("Circle");
weight = XmStringCreateLocalized ("Line Width");
exit = XmStringCreateLocalized ("Exit");
exit_acc = XmStringCreateLocalized ("Ctrl+C");
popup_menu = XmVaCreateSimplePopupMenu (drawing_a, "popup", popup_cb,
XmVaPUSHBUTTON, line, 'L', NULL, NULL,
XmVaPUSHBUTTON, square, 'S', NULL, NULL,
XmVaPUSHBUTTON, circle, 'C', NULL, NULL,
XmVaCASCADEBUTTON, weight, 'W',
XmVaSEPARATOR,
XmVaPUSHBUTTON, exit, 'x', "Ctrl<Key>c", exit_acc,
NULL);
XmStringFree (line);
XmStringFree (square);
XmStringFree (circle);
XmStringFree (weight);
XmStringFree (exit);
/* create pullright for "Line Width" button −− this is the 4th item! */
w_one = XmStringCreateLocalized (" 1 ");
w_two = XmStringCreateLocalized (" 2 ");
w_four = XmStringCreateLocalized (" 4 ");
w_eight = XmStringCreateLocalized (" 8 ");
pullright = XmVaCreateSimplePulldownMenu (popup_menu,
"pullright", 3 /* menu item offset */, set_width,
XmVaPUSHBUTTON, w_one, '1', NULL, NULL,
XmVaPUSHBUTTON, w_two, '2', NULL, NULL,
XmVaPUSHBUTTON, w_four, '4', NULL, NULL,
XmVaPUSHBUTTON, w_eight, '8', NULL, NULL,
NULL);
XmStringFree (w_one);
XmStringFree (w_two);
XmStringFree (w_four);
XmStringFree (w_eight);
/* after popup menu is created, add callback for all input events */
XtAddCallback (drawing_a, XmNinputCallback, input, popup_menu);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
/* input() −− called in responses to events in the DrawingArea;
* button−3 pops up menu.
*/
void
input(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
Widget popup = (Widget) client_data;
XmDrawingAreaCallbackStruct *cbs =
(XmDrawingAreaCallbackStruct *) call_data;
if (cbs−>event−>xany.type != ButtonPress ||
cbs−>event−>xbutton.button != 3)
return;
16 Menus 16.2.2 Cascading Menus
438
/* Position the menu where the event occurred */
XmMenuPosition (popup, (XButtonPressedEvent *) (cbs−>event));
XtManageChild (popup);
}
/* popup_cb() −− invoked when the user selects an item in the popup menu */
void
popup_cb(menu_item, client_data, call_data)
Widget menu_item;
XtPointer client_data;
XtPointer call_data;
{
int item_no = (int) client_data;
if (item_no == 4) /* Exit was selected −− exit */
exit (0);
puts (XtName (menu_item)); /* Otherwise, just print the selection */
}
/* set_width() −− called when items in the Line Width pullright menu
* are selected.
*/
void
set_width(menu_item, client_data, call_data)
Widget menu_item;
XtPointer client_data;
XtPointer call_data;
{
int item_no = (int) client_data;
printf ("Line weight = %d0, 1 << item_no);
}
In the call to XmVaCreateSimplePulldownMenu(), the PopupMenu is specified as the parent of the cascading
menu. The button parameter is set to 3 to indicate that the fourth item in the PopupMenu posts the cascading menu.
the figure shows the output of the program.
Output of simple_pullright.c
16 Menus 16.2.2 Cascading Menus
439

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.