The Menu Display Classes ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ 1. The Choice Display Class 2. The Hmenu and Vmenu Display Classes --------------------------------------------------- 1. The Choice Display Class The choice class, like the radio class, is for boolean-valued slotfiller variables whose value part contains one and only one 1. The radio display may perhaps be more appropriate when the choices are few or choosing is done often, the choice display when there are many choices or choosing is seldom done. The choice representation has three parts, a title area on the left, a button in the middle invoking a pulldown menu, and a value area on the right. The pulldown menu consists of label areas, which hold either the value of the label attribute or, if that is null, the symbolic indices of the slotfiller. The value area holds the label or symbolic index for the only slotfiller value that is 1. In the following example, notice that: when the label attribute is null, the symbolic index is used; when the label attribute is given a non-null value, neither the size of the window nor the display in the value area changes; when the value part of c is respecified, the display in the value area is changed but the size of the window remains unchanged; when naturalsize is specified, the value area is enlarged and all of the label is shown. $load s scrûs.SCREEN-34 12 br{w;m}:{w has (`yx;scr-m+Ø`yxs of w);} cû(`fut `opt `ind;(1;0;0)) `c has (`class;`choice; `shelltitle;'QList Products'; `title;'Type'); show `c; br{`c;100} `label of `c `c has (`label;(`Future;`Option;`Index)); (1Øc)û(1;0;0) `c has `naturalsize; br{`c;100} If instead of respecifying the value part of c you had made a choice from the menu, the effect would have been the same. The instant you pressed the left mouse button with the pointer on the choice button, the display in the value area, but not its size, would have changed. Starting fresh and reversing the order of the last two statements, you see that specifying naturalsize increases the window size but does not change the display in the value area; that display is changed by a respecification of the underlying variable (and could have been done by a choice from the menu): _ex free `c; cû(`fut `opt `ind;(1;0;0)) `c has (`class;`choice; `shelltitle;'QList Products'; `title;'Type'); show `c; br{`c;100} `c has (`label;(`Future;`Option;`Index)); `c has `naturalsize; br{`c;100} (1Øc)û(1;0;0) What these two examples really demonstrate, of course, is that you want to set the label attribute before realizing or showing the object. Now make a selection in two different ways. For the first selection, place the pointer on the choice button, press the left mouse button, move the pointer down the menu that appears, and release the button when the pointer is on Option or Index. For the second, again place the pointer on the choice button, then click the left mouse button, use the up and down arrow keys to move around the menu, stop at Future, and press Enter. So far we have been dealing only with appearances. To provide a response to any menu selection, you must set a callback function. Selecting an item in the menu amounts to selecting a symbolic index of the slotfiller and causes a value change in the underlying variable. When an item is selected, if the value at that symbolic index is 0, then it becomes 1 and the value that was 1 becomes 0. In addition, the menu disappears and the selected symbolic index or label is displayed in the value area. Because of this value change, any callback function defined for the variable is called whenever a new item is selected; the path argument p is the symbolic index to the changed value. Although there are actually two value changes, the callback function is called only once, and its path argument refers to the value that changed from 0 to 1. Set a callback function that just displays the arguments that are passed to it: f{s;d;i;p;c;v}:{Õ'-----------';Õ(s;d;i;p;c;v)} `c has (`set;(f;'choice')); Make some choices and watch the responses that appear in the A+ session log. If you choose a menu item that already has the value 1, no callback occurs. On the other hand, a callback always occurs for a change made by an A+ statement, and all respecified values are included in it. Furthermore, the index and path arguments reflect the statement executed, so they are different for the third and fourth statements below although the actions called for by these statements are identical: cû(`fut `opt `ind;(0;1;0)) (1Øc)[0 1]û(0;1) (1Øc)[1]û<1 (`optØc)û1 _ex free `c; 2. The Hmenu and Vmenu Display Classes The hmenu and vmenu display classes are designed to represent nested slotfillers as cascaded menus. A nested slotfiller is a slotfiller some of whose values are also slotfillers, perhaps nested slotfillers. There is no limit to the level of nesting. In contrast to a choice display, the top-level menu is continuously shown, laid out horizontally in hmenu and vertically in vmenu, but without any indication of the last selection. All submenus are pulldown and are arranged vertically in both classes. The items shown in the top-level menu are the symbolic indices of the slotfiller. If a value is also a slotfiller, then its symbolic indices are shown in the corresponding submenu. If a callback function is set on the nested slotfiller, a callback occurs whenever a menu or submenu item is selected. When the function is called, only pØd is given in the second argument (data), where d is the underlying slotfiller. Incidentally, these classes can be used with non-nested slotfillers to provide buttons that have no outlines unless pressed: cû(`fut `opt `ind;(0;1;0)) `c has (`set;(f;'hmenu')); show `c is `hmenu; br{`c;100} Click on the symbolic indices in the hmenu window. Shadowed outlines will appear around them and callback output will appear in the session log. Do the same for this vmenu: `c has (`set;(f;'vmenu')); show `c is `vmenu; br{`c;100} Here is a more complicated example, with irregular levels of nesting: _ex free `c; cû(`file`edit`charformat;( (`new`open`close`save;(;;; (`save`save_as`save_all;(;;)))); (`copy`cut`paste`undo;(;;;)); (`font`size`style;( (`kaplgallant`courier`times`palatino`helvetica;(;;;;)); (`10`12`14`17`24;(;;;;)); (`regular`italic`bold;(;;)))))) show `c is `hmenu; br{`c;150 100} When you click on an item that has an arrowhead, its submenu appears. When you click on an item without an arrowhead, a selection takes place and any displayed submenus vanish. You can also drag the pointer, holding the mouse button down. In a horizontal menu, a submenu appears whenever you are in an item that has one; in a vertical menu, a submenu appears whenever the pointer is on an arrowhead. If you place the pointer in the hmenu window, the left and right arrow keys move you from item to item in the top-level menu and the down arrow key moves you to a submenu when you are on an item that has one. In the submenus, the up and down arrow keys move you among items, the left arrow key moves you back to the parent menu, and the right arrow key moves you to a submenu when you are on an item that has one. The Escape key aborts the operation. The Enter key makes a selection if you are on an item with no submenu, and otherwise aborts the operation. Try these keys. Then set the callback function and see the results of your selections. `c has (`set;(f;'hmenu')); A vmenu is handled in the same way, except that the keys act the same for the top-level menu as for the submenus, since it is also vertical. Execute the next two statements and then try some selections. show `c is `vmenu; br{`c;150 100} `c has (`set;(f;'vmenu')); _ex free `c;