home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / windows / x / motif / 5949 < prev    next >
Encoding:
Text File  |  1992-09-01  |  15.1 KB  |  386 lines

  1. Path: sparky!uunet!cis.ohio-state.edu!ucbvax!oceanroutes.ns.ca!deveau
  2. From: deveau@oceanroutes.ns.ca ("Terry J. Deveau")
  3. Newsgroups: comp.windows.x.motif
  4. Subject: popdown menu
  5. Message-ID: <9209012032.AA04296@BU.EDU>
  6. Date: 1 Sep 92 20:32:40 GMT
  7. Sender: daemon@ucbvax.BERKELEY.EDU
  8. Distribution: inet
  9. Organization: Oceanroutes Canada Inc.
  10. Lines: 374
  11.  
  12. I'm looking for people who are willing to give me some feedback
  13. regarding the style and desireability of a new Motif menu type.
  14.  
  15. At the end of this message is a short demonstration program that 
  16. includes the three traditional Motif menus (pulldown, popup,
  17. and option), plus an ordinary pushbutton, along with a new
  18. type of menu that I call "popdown".  You can run the program
  19. and compare the behaviour of these five selection mechanisms.
  20.  
  21. Am I violating the Motif Style Guidelines here? (I don't think so, but
  22. I'm not really sure).  Has anyone else found a need to resort to
  23. this kind of thing?  Any other comments?
  24.  
  25. The table below summarizes the behaviour I would like to have for the
  26. selection mechanisms; a + indicates non-default behaviour that I know
  27. how to achieve via extra translations, etc.; a - indicates behaviour 
  28. that I want, but can't figure out how to get.  Hints on how to obtain
  29. the -'ed behaviours would be appreciated.
  30.  
  31. All I have (and know much about) is X11R3 and Motif 1.0; if some of 
  32. this is different in later releases I'd like to know that too.
  33.  
  34.  
  35. Event              pushbutton  popup    pulldown      option        popdown
  36. ================   ==========  =====    ===========   ===========   =========
  37. btn1 down & up      arm &       --      post menu     activate      post menu
  38.    on rectangle     activate            key mode      selection     drag mode
  39.    (w or w/o motion)                                               -(key mode)
  40.  
  41. btn1 down           arm         --      post menu     post menu     post menu
  42.    on rectangle                         drag mode     drag mode     drag mode
  43.                                                       & select
  44.  
  45. btn1 down on rect.  disarm      --      post menu     post menu     post menu
  46.    then move off                        drag mode     drag mode     drag mode
  47.  
  48. btn3 down             --    post menu      --            --            --
  49.                             drag mode
  50.  
  51. btn up on menu        --    activate    activate      select &      activate
  52.    in drag mode             & unpost    & unpost      activate      & unpost
  53.                                                       & unpost
  54.  
  55. btn up off menu       --    unpost      unpost        unpost       -unpost
  56.    in drag mode                                                    (see note 1)
  57.    (and off rect.)
  58.  
  59. btn down on menu      --    select &    select &      select &     -(select &)
  60.    in key mode              change to   change to     change to     change to
  61.                             drag mode   drag mode     drag mode     drag mode
  62.                                                                    (see note 2)
  63.  
  64. btn down off app.     --    change to   unpost        change to     change to
  65.    in key mode              drag mode                 drag mode     drag mode
  66.  
  67. btn down off menu     --    change to   change to     change to     change to
  68.    but on app. in           drag mode   drag mode     drag mode     drag mode
  69.    key mode
  70.  
  71. Meta-mnemonic         --        --      post menu    -(post menu   -(post menu
  72.                                         key mode      key mode      key mode)
  73.                                                       & select)
  74.  
  75. menu mnemonic         --        --         --         post menu        --      
  76.                                                       key mode     
  77.                                                       & select
  78.  
  79. menu accelerator      --    post menu   highlight &      --        -(post menu
  80.    from anywhere            key mode    accept focus                key mode)
  81.    in application                                                  (see note 3)
  82.  
  83. item accelerator      --    activate    activate      select &      activate
  84.                             & unpost    & unpost      activate      & unpost
  85.                                                       & unpost
  86.  
  87. ESC when menu         --    unpost      unpost        unpost        unpost
  88.    posted any mode
  89.  
  90. tab to the         highlight &  --     +highlight &   highlight &   highlight &
  91.    rectangle       accept focus        +accept focus  accept focus  accept focus
  92.  
  93. tab from the       unhighlight& --     -unhighlight&  unhighlight&  unhighlight &
  94.    rectangle       loose focus         -loose focus   loose focus   loose focus
  95.  
  96. Return when rect. +arm &        --      post menu     activate      post menu
  97.    in focus       +activate             key mode      selection     drag mode
  98.                                                                    -(key mode)
  99.  
  100. Space when rect.   arm &        --     +(post menu    post menu     post menu
  101.    in focus        activate             key mode)     key mode      key mode    
  102.                                                       & select
  103.  
  104. Return when in        --    activate    activate      activate      activate
  105.    menu key mode            & unpost    & unpost      & unpost      & unpost
  106.  
  107. Space when in         --   +(activate  +(activate    +(activate     activate
  108.    menu key mode            & unpost)   & unpost)     & unpost)     & unpost
  109.  
  110. Up/Down arrow in      --    select      select        select        select
  111.    menu key mode
  112.  
  113. Left/Right arrow      --   +unpost      unpost &     +unpost        unpost
  114.    in menu key mode                     post next    
  115.                                         on menu bar
  116.  
  117. tab in menu key mode  --   +unpost     +unpost       +unpost        unpost
  118.  
  119. item mnemonic in      --    activate    activate      select &      activate
  120.    menu key mode            & unpost    & unpost      activate      & unpost
  121.                                                       & unpost     (see note 4)
  122.  
  123. Notes:
  124.   1.  Sometimes this works, sometimes it doesn't.  It always works if the btn
  125.       is released off the APPLICATION.  It usually works if the menu is first
  126.       crossed with the mouse.
  127.  
  128.   2.  Nothing is selected until the mouse moves to a different entry.
  129.  
  130.   3.  Only works when the rectangle already has focus.
  131.  
  132.   4.  Also works in drag mode as long as the mouse button has been released.
  133.       I would rather have the menu in key mode in that case, however.
  134.  
  135.       
  136. -------------- CUT HERE FOR DEMO PROGRAM ------------------------ 
  137.  
  138. #include <stdio.h>
  139. #include <X11/StringDefs.h>
  140. #include <X11/Intrinsic.h>
  141. #include <X11/keysym.h>
  142. #include <X11/Shell.h>
  143. #include <Xm/Xm.h>
  144. #include <Xm/DrawingA.h>
  145. #include <Xm/Label.h>
  146. #include <Xm/RowColumn.h>
  147. #include <Xm/PushBG.h>
  148. #include <Xm/PushB.h>
  149. #include <Xm/CascadeB.h>
  150.  
  151. #define popup    0
  152. #define pulldown 1
  153. #define option   2
  154. #define popdown  3
  155.  
  156. #define MySetArg(argList, count, n, d) \
  157.     ( (argList)[count].name = (n), (argList)[count++].value = (XtArgVal)(d) )
  158.  
  159. static char *menus[] = { "popup", "pulldown", "option", "popdown" };
  160.  
  161. static void MyCallback (w,client_data,call_data)
  162. Widget w;
  163. int client_data;
  164. XmAnyCallbackStruct *call_data;
  165. {
  166.   if (client_data) 
  167.     fprintf(stderr,"callback from %s menu, pushbutton %c\n",
  168.     menus[client_data>>8],client_data & 0xFF);
  169.   else
  170.     fprintf(stderr,"callback from pushbutton\n");
  171. }
  172.  
  173. static void PostPopup (w, menu, event)
  174. Widget w;
  175. Widget menu;
  176. XButtonEvent *event;
  177. {
  178.   if (event->button == Button3) {
  179.     XmMenuPosition(menu,event);
  180.     XtManageChild(menu); }
  181. }
  182.  
  183. static XtCallbackRec cb[2];
  184. static Arg args[10];
  185. static int Nargs;
  186.  
  187. void populateMenu (menu, buttonCodes, menuType)
  188. Widget menu;
  189. String buttonCodes;
  190. int menuType;
  191. {
  192.   Widget w;
  193.   XmString xmstr;
  194.   char *p_txt, *p_name, *p_acc, *loop,
  195.     *buttonName = "pushbutton x", *acc = "Ctrl <Key>x", *txt = "(Ctrl-x)";
  196.  
  197.   p_name = strchr(buttonName,'\0') - 1;
  198.   p_acc = strchr(acc,'\0') - 1;
  199.   p_txt = strchr(txt,'\0') - 2;
  200.   for (loop=buttonCodes; *loop; loop++) {
  201.     *p_name = *p_acc = *p_txt = *loop;
  202.     cb[0].closure = (caddr_t) (menuType<<8 | *loop);
  203.     Nargs = 0;
  204.     MySetArg (args, Nargs, XmNactivateCallback, cb);
  205.     MySetArg (args, Nargs, XmNmnemonic, *loop);
  206.     MySetArg (args, Nargs, XmNaccelerator, acc);
  207.     xmstr = XmStringCreateLtoR (txt, XmSTRING_DEFAULT_CHARSET);
  208.     MySetArg (args, Nargs, XmNacceleratorText, xmstr);
  209.     w = XmCreatePushButtonGadget(menu,buttonName, args, Nargs);
  210.     XmStringFree(xmstr);
  211.     XtManageChild(w); }
  212. }
  213.  
  214. /**************** begin special section to support popdown menu behaviour *********/
  215.  
  216. static void MyNoOp (w, event, params, num_params)
  217. Widget w;
  218. XEvent *event;
  219. String *params;
  220. Cardinal *num_params;
  221. {
  222. }
  223.  
  224. static void PostPopdown (w, menu, event)
  225. Widget w;
  226. Widget menu;
  227. XEvent *event;
  228. {
  229.   int n, height, x, y;
  230.   Arg args[5];
  231.   KeySym ks;
  232.   Widget nxt;
  233.  
  234.   switch (event->type) {
  235.     case ButtonPress : if (event->xbutton.button != Button1) return;
  236.       break;
  237.     case KeyPress : ks = XLookupKeysym(&(event->xkey),0);
  238.       if (ks!=XK_Return && ks!=XK_space) return;
  239.       break;
  240.     default : return; }
  241.   n = 0;
  242.   XtSetArg (args[n], XmNx, &x); n++;
  243.   XtSetArg (args[n], XmNy, &y); n++;
  244.   XtSetArg (args[n], XmNheight, &height); n++;
  245.   event->xkey.x_root = event->xkey.y_root = 0;   /* term. cond. won't be right */
  246.   for (nxt = w; nxt; nxt = XtParent(nxt)) {      /* if called from a DialogShell */ 
  247.     XtGetValues (nxt, args, n);                  /* in that case, stop there */
  248.     if (nxt==w) event->xkey.y_root += height;
  249.     event->xkey.x_root += x; event->xkey.y_root += y; }
  250.   XmMenuPosition(menu, event);
  251.   XtManageChild(menu);
  252. }
  253.  
  254. static XtActionsRec MyActions[] = { {"MyNoOp", MyNoOp} };
  255.  
  256. static String PDbuttonBehaviour = "<Key>Return: ArmAndActivate()\n\
  257.                                        <Enter>: MyNoOp()\n\
  258.                                      <BtnDown>: MyNoOp()\n\
  259.                                        <BtnUp>: MyNoOp()";
  260. static XtTranslations PDbuttonTranslation = NULL;
  261.  
  262. static String PDmenuBehaviour = "<Key>space: MenuGadgetReturn()\n\
  263.                   <Enter>,<BtnDown>,<BtnUp>: PopupBtnDown() PopupBtnUp()\n\
  264.                             <Enter>,<BtnUp>: PopupBtnUp()\n\
  265.                           <BtnDown>,<BtnUp>: MenuGadgetEscape()\n\
  266.                             <Leave>,<BtnUp>: MenuGadgetEscape()\n\
  267.                               Shift<Key>Tab: MenuGadgetEscape()\n\
  268.                                Ctrl<Key>Tab: MenuGadgetEscape()\n\
  269.                                    <Key>Tab: MenuGadgetEscape()\n\
  270.                                  <Key>Right: MenuGadgetEscape()\n\
  271.                                   <Key>Left: MenuGadgetEscape()";
  272. static XtTranslations PDmenuTranslation = NULL;
  273.  
  274. static String PDshellBehaviour = "<Key>Escape: MenuShellPopdownDone()\n\
  275.                                       <BtnUp>: MyNoOp()\n\
  276.                                     <BtnDown>: ClearTraversal()";
  277. static XtTranslations PDshellTranslation = NULL;
  278.  
  279. /************** end special section to support popdown menu behaviour *************/
  280.  
  281. main(argc, argv)
  282. int argc;
  283. char *argv[];
  284. {
  285.   XmString xmstr;
  286.   Widget shell, container, menubar, menu, w;
  287.   XtAppContext app;
  288.  
  289.   cb[0].callback = MyCallback;                          /* initialize constants */
  290.   cb[1].callback = NULL;
  291.   cb[1].closure = NULL;
  292.  
  293.                                                           /* top-level widgets */
  294.   shell = XtInitialize ("main",argv[0], NULL, 0, &argc, argv); 
  295.   app = XtWidgetToApplicationContext(shell);
  296.   Nargs = 0;
  297.   MySetArg (args, Nargs, XmNtraversalOn, True);
  298.   container = XmCreateDrawingArea (shell, "area", args, Nargs);
  299.   XtManageChild (container); 
  300.                                                    /* build translations, etc. */
  301.   PDbuttonTranslation = XtParseTranslationTable (PDbuttonBehaviour);
  302.   PDmenuTranslation = XtParseTranslationTable (PDmenuBehaviour);
  303.   PDshellTranslation = XtParseTranslationTable (PDshellBehaviour);
  304.   XtAppAddActions (app, MyActions, sizeof MyActions / sizeof (XtActionsRec));
  305.  
  306.   Nargs = 0;                                                   /* pushbutton */
  307.   MySetArg (args, Nargs, XmNactivateCallback, cb);
  308.   MySetArg (args, Nargs, XmNtraversalOn, True);
  309.   MySetArg (args, Nargs, XmNhighlightThickness, 2);
  310.   cb[0].closure = 0;
  311.   w = XmCreatePushButton(container,"pushbutton", args, Nargs);
  312.   XtManageChild (w); 
  313.   XmAddTabGroup(w);
  314.  
  315.   Nargs = 0;                                                 /* reminder label */
  316.   xmstr = XmStringCreateLtoR("Press mouse button 3, or Ctrl-m, for a Popup Menu",
  317.     XmSTRING_DEFAULT_CHARSET);
  318.   MySetArg (args, Nargs, XmNy, 60);
  319.   MySetArg (args, Nargs, XmNlabelString, xmstr);
  320.   w = XmCreateLabel(container,"label", args, Nargs);
  321.   XmStringFree(xmstr);
  322.   XtManageChild (w); 
  323.  
  324.   Nargs = 0;                                                     /* popup menu */
  325.   MySetArg (args, Nargs, XmNmenuAccelerator, "Ctrl <Key>m"); 
  326.   menu = XmCreatePopupMenu (container,menus[popup],args,Nargs);
  327.   populateMenu (menu, "abc", popup);
  328.   XtAddEventHandler(container,ButtonPressMask,False,PostPopup,menu);
  329.  
  330.   Nargs = 0;                                                  /* pulldown menu */
  331.   MySetArg (args, Nargs, XmNy, 100);
  332.   MySetArg (args, Nargs, XmNmenuAccelerator, "Ctrl <Key>p"); 
  333.   menubar = XmCreateMenuBar (container,"menubar",args,Nargs);
  334.   XtManageChild (menubar);
  335.   menu = XmCreatePulldownMenu (menubar,menus[pulldown],NULL,0);
  336.   populateMenu (menu, "def", pulldown);
  337.   Nargs = 0;
  338.   MySetArg (args, Nargs, XmNsubMenuId, menu);
  339.   MySetArg (args, Nargs, XmNmnemonic, 'p');
  340.   w = XmCreateCascadeButton (menubar, "pulldown menu (Ctrl-p)", args, Nargs);
  341.   XtManageChild (w);
  342.  
  343.                                                                /* option menu */
  344.   menu = XmCreatePulldownMenu (container,menus[option],NULL,0);
  345.   populateMenu (menu, "ghi", option);
  346.   Nargs = 0;
  347.   xmstr = XmStringCreateLtoR("Option Menu:", XmSTRING_DEFAULT_CHARSET);
  348.   MySetArg (args, Nargs, XmNlabelString, xmstr);
  349.   MySetArg (args, Nargs, XmNsubMenuId, menu);
  350.   MySetArg (args, Nargs, XmNmnemonic, 'o');
  351.   MySetArg (args, Nargs, XmNx, 160);
  352.   w = XmCreateOptionMenu(container,"option menu", args, Nargs);
  353.   XmStringFree(xmstr);
  354.   XtManageChild (w); 
  355.   w = XmOptionButtonGadget(w);
  356.   Nargs = 0;
  357.   MySetArg (args, Nargs, XmNtraversalOn, True);
  358.   MySetArg (args, Nargs, XmNhighlightThickness, 2);
  359.   XtSetValues (w, args, Nargs);
  360.   XmAddTabGroup(w);
  361.  
  362.   Nargs = 0;                                                   /* popdown menu */
  363.   MySetArg (args, Nargs, XmNy, 100);
  364.   MySetArg (args, Nargs, XmNx, 260);
  365.   MySetArg (args, Nargs, XmNtraversalOn, True);
  366.   MySetArg (args, Nargs, XmNhighlightThickness, 2);
  367.   w = XmCreatePushButton(container,"popdown menu", args, Nargs);
  368.   XtManageChild (w); 
  369.   XmAddTabGroup(w);
  370.   Nargs = 0;
  371.   MySetArg (args, Nargs, XmNwhichButton, 1); 
  372.   MySetArg (args, Nargs, XmNdialogStyle, XmDIALOG_MODELESS); 
  373.   MySetArg (args, Nargs, XmNtraversalOn, True); 
  374.   MySetArg (args, Nargs, XmNmenuAccelerator, "<Key>space"); 
  375.   menu = XmCreatePopupMenu (w, menus[popdown], args, Nargs);
  376.   XtAddEventHandler (w, KeyPressMask | ButtonPressMask, False, PostPopdown, menu);
  377.   XtOverrideTranslations (w,PDbuttonTranslation);
  378.   XtOverrideTranslations (menu,PDmenuTranslation);
  379.   XtOverrideTranslations (XtParent(menu),PDshellTranslation);
  380.   populateMenu (menu, "jkl", popdown);
  381.  
  382.   XtRealizeWidget(shell);
  383.   XtAppMainLoop(app);
  384.  
  385. }
  386.