home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!cis.ohio-state.edu!ucbvax!oceanroutes.ns.ca!deveau
- From: deveau@oceanroutes.ns.ca ("Terry J. Deveau")
- Newsgroups: comp.windows.x.motif
- Subject: popdown menu
- Message-ID: <9209012032.AA04296@BU.EDU>
- Date: 1 Sep 92 20:32:40 GMT
- Sender: daemon@ucbvax.BERKELEY.EDU
- Distribution: inet
- Organization: Oceanroutes Canada Inc.
- Lines: 374
-
- I'm looking for people who are willing to give me some feedback
- regarding the style and desireability of a new Motif menu type.
-
- At the end of this message is a short demonstration program that
- includes the three traditional Motif menus (pulldown, popup,
- and option), plus an ordinary pushbutton, along with a new
- type of menu that I call "popdown". You can run the program
- and compare the behaviour of these five selection mechanisms.
-
- Am I violating the Motif Style Guidelines here? (I don't think so, but
- I'm not really sure). Has anyone else found a need to resort to
- this kind of thing? Any other comments?
-
- The table below summarizes the behaviour I would like to have for the
- selection mechanisms; a + indicates non-default behaviour that I know
- how to achieve via extra translations, etc.; a - indicates behaviour
- that I want, but can't figure out how to get. Hints on how to obtain
- the -'ed behaviours would be appreciated.
-
- All I have (and know much about) is X11R3 and Motif 1.0; if some of
- this is different in later releases I'd like to know that too.
-
-
- Event pushbutton popup pulldown option popdown
- ================ ========== ===== =========== =========== =========
- btn1 down & up arm & -- post menu activate post menu
- on rectangle activate key mode selection drag mode
- (w or w/o motion) -(key mode)
-
- btn1 down arm -- post menu post menu post menu
- on rectangle drag mode drag mode drag mode
- & select
-
- btn1 down on rect. disarm -- post menu post menu post menu
- then move off drag mode drag mode drag mode
-
- btn3 down -- post menu -- -- --
- drag mode
-
- btn up on menu -- activate activate select & activate
- in drag mode & unpost & unpost activate & unpost
- & unpost
-
- btn up off menu -- unpost unpost unpost -unpost
- in drag mode (see note 1)
- (and off rect.)
-
- btn down on menu -- select & select & select & -(select &)
- in key mode change to change to change to change to
- drag mode drag mode drag mode drag mode
- (see note 2)
-
- btn down off app. -- change to unpost change to change to
- in key mode drag mode drag mode drag mode
-
- btn down off menu -- change to change to change to change to
- but on app. in drag mode drag mode drag mode drag mode
- key mode
-
- Meta-mnemonic -- -- post menu -(post menu -(post menu
- key mode key mode key mode)
- & select)
-
- menu mnemonic -- -- -- post menu --
- key mode
- & select
-
- menu accelerator -- post menu highlight & -- -(post menu
- from anywhere key mode accept focus key mode)
- in application (see note 3)
-
- item accelerator -- activate activate select & activate
- & unpost & unpost activate & unpost
- & unpost
-
- ESC when menu -- unpost unpost unpost unpost
- posted any mode
-
- tab to the highlight & -- +highlight & highlight & highlight &
- rectangle accept focus +accept focus accept focus accept focus
-
- tab from the unhighlight& -- -unhighlight& unhighlight& unhighlight &
- rectangle loose focus -loose focus loose focus loose focus
-
- Return when rect. +arm & -- post menu activate post menu
- in focus +activate key mode selection drag mode
- -(key mode)
-
- Space when rect. arm & -- +(post menu post menu post menu
- in focus activate key mode) key mode key mode
- & select
-
- Return when in -- activate activate activate activate
- menu key mode & unpost & unpost & unpost & unpost
-
- Space when in -- +(activate +(activate +(activate activate
- menu key mode & unpost) & unpost) & unpost) & unpost
-
- Up/Down arrow in -- select select select select
- menu key mode
-
- Left/Right arrow -- +unpost unpost & +unpost unpost
- in menu key mode post next
- on menu bar
-
- tab in menu key mode -- +unpost +unpost +unpost unpost
-
- item mnemonic in -- activate activate select & activate
- menu key mode & unpost & unpost activate & unpost
- & unpost (see note 4)
-
- Notes:
- 1. Sometimes this works, sometimes it doesn't. It always works if the btn
- is released off the APPLICATION. It usually works if the menu is first
- crossed with the mouse.
-
- 2. Nothing is selected until the mouse moves to a different entry.
-
- 3. Only works when the rectangle already has focus.
-
- 4. Also works in drag mode as long as the mouse button has been released.
- I would rather have the menu in key mode in that case, however.
-
-
- -------------- CUT HERE FOR DEMO PROGRAM ------------------------
-
- #include <stdio.h>
- #include <X11/StringDefs.h>
- #include <X11/Intrinsic.h>
- #include <X11/keysym.h>
- #include <X11/Shell.h>
- #include <Xm/Xm.h>
- #include <Xm/DrawingA.h>
- #include <Xm/Label.h>
- #include <Xm/RowColumn.h>
- #include <Xm/PushBG.h>
- #include <Xm/PushB.h>
- #include <Xm/CascadeB.h>
-
- #define popup 0
- #define pulldown 1
- #define option 2
- #define popdown 3
-
- #define MySetArg(argList, count, n, d) \
- ( (argList)[count].name = (n), (argList)[count++].value = (XtArgVal)(d) )
-
- static char *menus[] = { "popup", "pulldown", "option", "popdown" };
-
- static void MyCallback (w,client_data,call_data)
- Widget w;
- int client_data;
- XmAnyCallbackStruct *call_data;
- {
- if (client_data)
- fprintf(stderr,"callback from %s menu, pushbutton %c\n",
- menus[client_data>>8],client_data & 0xFF);
- else
- fprintf(stderr,"callback from pushbutton\n");
- }
-
- static void PostPopup (w, menu, event)
- Widget w;
- Widget menu;
- XButtonEvent *event;
- {
- if (event->button == Button3) {
- XmMenuPosition(menu,event);
- XtManageChild(menu); }
- }
-
- static XtCallbackRec cb[2];
- static Arg args[10];
- static int Nargs;
-
- void populateMenu (menu, buttonCodes, menuType)
- Widget menu;
- String buttonCodes;
- int menuType;
- {
- Widget w;
- XmString xmstr;
- char *p_txt, *p_name, *p_acc, *loop,
- *buttonName = "pushbutton x", *acc = "Ctrl <Key>x", *txt = "(Ctrl-x)";
-
- p_name = strchr(buttonName,'\0') - 1;
- p_acc = strchr(acc,'\0') - 1;
- p_txt = strchr(txt,'\0') - 2;
- for (loop=buttonCodes; *loop; loop++) {
- *p_name = *p_acc = *p_txt = *loop;
- cb[0].closure = (caddr_t) (menuType<<8 | *loop);
- Nargs = 0;
- MySetArg (args, Nargs, XmNactivateCallback, cb);
- MySetArg (args, Nargs, XmNmnemonic, *loop);
- MySetArg (args, Nargs, XmNaccelerator, acc);
- xmstr = XmStringCreateLtoR (txt, XmSTRING_DEFAULT_CHARSET);
- MySetArg (args, Nargs, XmNacceleratorText, xmstr);
- w = XmCreatePushButtonGadget(menu,buttonName, args, Nargs);
- XmStringFree(xmstr);
- XtManageChild(w); }
- }
-
- /**************** begin special section to support popdown menu behaviour *********/
-
- static void MyNoOp (w, event, params, num_params)
- Widget w;
- XEvent *event;
- String *params;
- Cardinal *num_params;
- {
- }
-
- static void PostPopdown (w, menu, event)
- Widget w;
- Widget menu;
- XEvent *event;
- {
- int n, height, x, y;
- Arg args[5];
- KeySym ks;
- Widget nxt;
-
- switch (event->type) {
- case ButtonPress : if (event->xbutton.button != Button1) return;
- break;
- case KeyPress : ks = XLookupKeysym(&(event->xkey),0);
- if (ks!=XK_Return && ks!=XK_space) return;
- break;
- default : return; }
- n = 0;
- XtSetArg (args[n], XmNx, &x); n++;
- XtSetArg (args[n], XmNy, &y); n++;
- XtSetArg (args[n], XmNheight, &height); n++;
- event->xkey.x_root = event->xkey.y_root = 0; /* term. cond. won't be right */
- for (nxt = w; nxt; nxt = XtParent(nxt)) { /* if called from a DialogShell */
- XtGetValues (nxt, args, n); /* in that case, stop there */
- if (nxt==w) event->xkey.y_root += height;
- event->xkey.x_root += x; event->xkey.y_root += y; }
- XmMenuPosition(menu, event);
- XtManageChild(menu);
- }
-
- static XtActionsRec MyActions[] = { {"MyNoOp", MyNoOp} };
-
- static String PDbuttonBehaviour = "<Key>Return: ArmAndActivate()\n\
- <Enter>: MyNoOp()\n\
- <BtnDown>: MyNoOp()\n\
- <BtnUp>: MyNoOp()";
- static XtTranslations PDbuttonTranslation = NULL;
-
- static String PDmenuBehaviour = "<Key>space: MenuGadgetReturn()\n\
- <Enter>,<BtnDown>,<BtnUp>: PopupBtnDown() PopupBtnUp()\n\
- <Enter>,<BtnUp>: PopupBtnUp()\n\
- <BtnDown>,<BtnUp>: MenuGadgetEscape()\n\
- <Leave>,<BtnUp>: MenuGadgetEscape()\n\
- Shift<Key>Tab: MenuGadgetEscape()\n\
- Ctrl<Key>Tab: MenuGadgetEscape()\n\
- <Key>Tab: MenuGadgetEscape()\n\
- <Key>Right: MenuGadgetEscape()\n\
- <Key>Left: MenuGadgetEscape()";
- static XtTranslations PDmenuTranslation = NULL;
-
- static String PDshellBehaviour = "<Key>Escape: MenuShellPopdownDone()\n\
- <BtnUp>: MyNoOp()\n\
- <BtnDown>: ClearTraversal()";
- static XtTranslations PDshellTranslation = NULL;
-
- /************** end special section to support popdown menu behaviour *************/
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- XmString xmstr;
- Widget shell, container, menubar, menu, w;
- XtAppContext app;
-
- cb[0].callback = MyCallback; /* initialize constants */
- cb[1].callback = NULL;
- cb[1].closure = NULL;
-
- /* top-level widgets */
- shell = XtInitialize ("main",argv[0], NULL, 0, &argc, argv);
- app = XtWidgetToApplicationContext(shell);
- Nargs = 0;
- MySetArg (args, Nargs, XmNtraversalOn, True);
- container = XmCreateDrawingArea (shell, "area", args, Nargs);
- XtManageChild (container);
- /* build translations, etc. */
- PDbuttonTranslation = XtParseTranslationTable (PDbuttonBehaviour);
- PDmenuTranslation = XtParseTranslationTable (PDmenuBehaviour);
- PDshellTranslation = XtParseTranslationTable (PDshellBehaviour);
- XtAppAddActions (app, MyActions, sizeof MyActions / sizeof (XtActionsRec));
-
- Nargs = 0; /* pushbutton */
- MySetArg (args, Nargs, XmNactivateCallback, cb);
- MySetArg (args, Nargs, XmNtraversalOn, True);
- MySetArg (args, Nargs, XmNhighlightThickness, 2);
- cb[0].closure = 0;
- w = XmCreatePushButton(container,"pushbutton", args, Nargs);
- XtManageChild (w);
- XmAddTabGroup(w);
-
- Nargs = 0; /* reminder label */
- xmstr = XmStringCreateLtoR("Press mouse button 3, or Ctrl-m, for a Popup Menu",
- XmSTRING_DEFAULT_CHARSET);
- MySetArg (args, Nargs, XmNy, 60);
- MySetArg (args, Nargs, XmNlabelString, xmstr);
- w = XmCreateLabel(container,"label", args, Nargs);
- XmStringFree(xmstr);
- XtManageChild (w);
-
- Nargs = 0; /* popup menu */
- MySetArg (args, Nargs, XmNmenuAccelerator, "Ctrl <Key>m");
- menu = XmCreatePopupMenu (container,menus[popup],args,Nargs);
- populateMenu (menu, "abc", popup);
- XtAddEventHandler(container,ButtonPressMask,False,PostPopup,menu);
-
- Nargs = 0; /* pulldown menu */
- MySetArg (args, Nargs, XmNy, 100);
- MySetArg (args, Nargs, XmNmenuAccelerator, "Ctrl <Key>p");
- menubar = XmCreateMenuBar (container,"menubar",args,Nargs);
- XtManageChild (menubar);
- menu = XmCreatePulldownMenu (menubar,menus[pulldown],NULL,0);
- populateMenu (menu, "def", pulldown);
- Nargs = 0;
- MySetArg (args, Nargs, XmNsubMenuId, menu);
- MySetArg (args, Nargs, XmNmnemonic, 'p');
- w = XmCreateCascadeButton (menubar, "pulldown menu (Ctrl-p)", args, Nargs);
- XtManageChild (w);
-
- /* option menu */
- menu = XmCreatePulldownMenu (container,menus[option],NULL,0);
- populateMenu (menu, "ghi", option);
- Nargs = 0;
- xmstr = XmStringCreateLtoR("Option Menu:", XmSTRING_DEFAULT_CHARSET);
- MySetArg (args, Nargs, XmNlabelString, xmstr);
- MySetArg (args, Nargs, XmNsubMenuId, menu);
- MySetArg (args, Nargs, XmNmnemonic, 'o');
- MySetArg (args, Nargs, XmNx, 160);
- w = XmCreateOptionMenu(container,"option menu", args, Nargs);
- XmStringFree(xmstr);
- XtManageChild (w);
- w = XmOptionButtonGadget(w);
- Nargs = 0;
- MySetArg (args, Nargs, XmNtraversalOn, True);
- MySetArg (args, Nargs, XmNhighlightThickness, 2);
- XtSetValues (w, args, Nargs);
- XmAddTabGroup(w);
-
- Nargs = 0; /* popdown menu */
- MySetArg (args, Nargs, XmNy, 100);
- MySetArg (args, Nargs, XmNx, 260);
- MySetArg (args, Nargs, XmNtraversalOn, True);
- MySetArg (args, Nargs, XmNhighlightThickness, 2);
- w = XmCreatePushButton(container,"popdown menu", args, Nargs);
- XtManageChild (w);
- XmAddTabGroup(w);
- Nargs = 0;
- MySetArg (args, Nargs, XmNwhichButton, 1);
- MySetArg (args, Nargs, XmNdialogStyle, XmDIALOG_MODELESS);
- MySetArg (args, Nargs, XmNtraversalOn, True);
- MySetArg (args, Nargs, XmNmenuAccelerator, "<Key>space");
- menu = XmCreatePopupMenu (w, menus[popdown], args, Nargs);
- XtAddEventHandler (w, KeyPressMask | ButtonPressMask, False, PostPopdown, menu);
- XtOverrideTranslations (w,PDbuttonTranslation);
- XtOverrideTranslations (menu,PDmenuTranslation);
- XtOverrideTranslations (XtParent(menu),PDshellTranslation);
- populateMenu (menu, "jkl", popdown);
-
- XtRealizeWidget(shell);
- XtAppMainLoop(app);
-
- }
-