Display Classes for Buttons ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ 1. The Action Display Class 1a. Actions 1a(i). Callbacks; Screen Position Attributes: atsector preset set x y yx 1a(ii). Other Actions Attributes: f1, ..., f12 fkeys selected 1b. Appearance 1b(i). Arrangement of the Buttons Attributes: geometry verify 1b(ii). Size Attributes: C R xs ys yxs 1b(iii). Displayed Characters Attributes: justify label labelfont shelltitle title titlefont 1b(iv). Color Attributes: bg fg labelfg titlefg 1c. Additional Windows 1c(i). Kinds of Windows Attributes: iconic ws Variable: s.WS 1c(ii). Visibility Attributes: followers followertree hide icon icontitle lower raise show 1c(iii). Selection Mouse Pointer Keys: Arrow keys Ctl-Shift-Tab Ctl-Tab Enter Shift-Tab Tab 1d. More about Appearance 1d(i). Changes in Appearance Attributes: hl hlthickness shadowthickness 1d(ii). Other Features Attributes: exit foot head is leftfoot pin resizeable rightfoot 1e. Status and its Preservation 1e(i). Status Attributes: bound class stateself settings 1e(ii). Saving Attribute: script Variable s.WM_SAVE_YOURSELF 2. The Button Display Class Attributes: margins naturalsize 3. The Check Display Class 4. The Radio Display Class --------------------------------------------------- 1. The Action Display Class An object of the action display class is shown as a set of buttons. Each button can trigger some action when it is pressed -- i.e., when the left mouse button is clicked while the pointer is on the button. Only slotfiller variables can be bound to this class. The display has one button for each of the slotfiller's symbolic indices, and these indices are used to label the buttons by default. The slotfiller's values do not appear in the display. A simple example with an immediately obvious action is an object that moves around the screen when its buttons are pressed. First, label the buttons and specify movements by creating the slotfiller: acû(`up `down `left `right;(¢100 0;100 0;0 ¢100;0 100)) The numbers will be used as increments, in pixels, to the vertical and horizontal positions. Now, after loading the s context, use the is function to bind ac to the action display class and then the show function to display the object on the screen. The is function is dyadic. It takes the variable name, in symbol form, as left argument, and the display class name, which is always in symbol form, as right argument. The show functions is monadic, taking a variable name, in symbol form, as argument; it returns Null. Since is, in addition to displaying some messages, returns its left argument as an explicit result, you can combine these two operations: $load s scrûs.SCREEN-34 12 br{w;m}:{w has (`yx;scr-m+Ø`yxs of w);} show `ac is `action; br{`ac;0} You should see an action object on the screen. Click the left mouse button while the pointer is on the object's "up" button. You get a pretty animation but no action, because no callback has been set on ac. 1a. Actions 1a(i). Callbacks; Screen Position Attributes: atsector preset set x y yx Suppose v is the unqualified name of a slotfiller variable bound to the action display class and c is its context, both in symbol form. Then whenever a button is pressed, s makes the reassignment (pØc%v)ûpØc%v, where p is the symbolic index corresponding to the button that was pressed. These assignments, since they involve the slotfiller's values, enable those values to be used to select actions. You write a function of the form f{s;d;i;p;c;v} that incorporates the actions you want, and you set the callback f on cÖv in order to have them triggered. In the callback, s is the static data (if any) you specified when you set the callback and d (the data) is the value to which p is the path; you can use any of them to determine an action. The index i is null. Since we will move ac around the screen as an example of the actions that can be triggered by an object of this class, we first discuss attributes used to position objects. The "x" and "y" attributes specify the horizontal and vertical distances in pixels between the top left corner of an object and the top left corner of either the object that contains it (a layout, for example) or, for top-level objects, the screen. For a top-level object, the default value for each is zero. The of function is used to query attributes. It takes a scalar or vector left argument of attributes, which are always in symbol form, and a variable name, in symbol form, as right argument. In its result, it encloses the value for each element of the left argument: `y`x of `ac The value of the "yx" attribute is simply the vector composed of the y and x attribute values. The has function sets attributes. It takes a variable name, in symbol form, as left argument, and as right argument an association list or slotfiller containing attribute names and values. It returns its left argument as explicit result. Change x and see the new position and the new attribute value: `ac has (`y;0; `x;300) `yx of `ac As stated above, a value selected from ac by a button press is available to a callback function, as its second argument. The of function encloses attribute values in its result, so Disclose or Raze must be used to obtain the attribute values themselves. Define a callback function to adjust the yx attribute by the value selected from ac by the button press, limiting the movement so as to stay well on any screen. Then set the callback on ac: acbfn{s;d;i;p;c;v}:cÖv has (`yx;0Ó600Ä(Ø`yx of cÖv)+d) `ac _scb (acbfn;'Just to illustrate') Two alternative methods of setting the callback use the "set" attribute: `ac has (`set;acbfn) `ac has (`set;(acbfn;'Just to illustrate')) If the former is used, the Null will be passed to acbfn as its first argument; if the latter, 'Just to illustrate' will be passed. No matter how the callback is imposed, by set or _scb, the value of the set attribute is the name of the function and the static data (the Null, if no static data was specified): `set of `ac Having entered these statements in an A+ session, you can move the action object around the screen, within the prescribed limits, by pressing its buttons. Try it. There is a "preset" attribute that is similar to set. It can be used to set and query preset callbacks, functions that are called just before a value is changed, rather than just after. Execute pc{s;d;i;p;c;v}:{Õ"Jump!";d} `ac has (`preset;pc) Now move the object around the screen. "Jump!" should appear in the session log, showing that pc is being called. To get rid of this preset callback, use a null function specification. (Null for set would likewise eliminate an ordinary callback.) Enter `ac has (`preset;) Since we have been discussing positioning, we might as well consider the "atsector" attribute now. It is used to move objects around the virtual desktop and to determine where they are. A position on the desktop is specified by a vector of two indices. The following three lines should move ac to sector 1 1 and back. (If you are already in sector 1 1, change the 1 1 to 0 0 in the second statement.). Suppose you are in sector 1 0 (the semicolon in the first line causes the result to be displayed -- see immediate execution display of expression groups in the A+ Reference Manual): ;sectorûØ`atsector of `ac `ac has (`atsector;1 1) `ac has (`atsector;sector) If your virtual-desktop window is visible, you can watch ac move around on it as you change the value of the atsector attribute. 1a(ii). Other Actions Attributes: f1, ..., f12 fkeys selected Whenever a button is pressed, the "selected" attribute is set to the symbolic index corresponding to that button. Press the "down" button; then: `selected of `ac You can also set selected to any of the symbolic indices using an A+ statement. Setting it does not cause a callback and an assignment of an illicit value is simply ignored. The domain of the selected attribute depends upon the display class: for an object bound to the array class, for instance, its value is an integer vector consisting of a row and a column index, initially ¢1 ¢1 to indicate no selection. For any object, you can associate an action with a function key. As an example, define an action similar to the ones we have associated with the buttons of ac: diag{x}:x has (`yx;600(|@0)100+Ø`yx of x) For any one of the twelve function keys, the key can be connected with a function and an argument by a statement such as the following, which uses an association list to specify several attributes at once. A slotfiller can be used instead of an association list, as you will see later. `ac has (`f1;(diag;`ac);`yx;0 0) Now press the F1 key while the mouse pointer is in the ac display and you will see the display move diagonally, with jumps to avoid getting too far. These twelve connections are listed in the "fkeys" attribute, which is for reference only; it cannot be set. Its value is a slotfiller such that the first two of the following three expressions give the same result for each of f1, f2, ... f12. (Recall that we must Disclose or Raze the of result to obtain the attribute value.) Ø`f1 of `ac `f1ØØ`fkeys of `ac `fkeys of `ac You may have to move to the Emacs A+ area to page up and see all of the result of the last statement. Then press End and move to the tutorial area. 1b. Appearance 1b(i). Arrangement of the Buttons Attributes: geometry verify The default arrangement of the buttons on the screen is vertical, but you can use the "geometry" attribute to alter it. Try these arrangements: `ac has (`geometry;¢2); br{`ac;0} `ac has (`geometry;¢1); br{`ac;0} `ac has (`geometry;`horizontal); br{`ac;0} `ac has (`geometry;`vertical); br{`ac;0} `ac has (`geometry;2 2); br{`ac;0} `ac has (`geometry;1 1 1 1); br{`ac;0} `ac has (`geometry;2); br{`ac;0} `ac has (`geometry;1 1 2); br{`ac;0} -2 is a conventional value for horizontal arrangement, and -1 for vertical. Non-negative numbers indicate how many buttons there are to be in each row and are used repeatedly if necessary. Fancier arrangements are possible using a matrix value for geometry. The matrix partitions the action display. Symbolic indices of the slotfiller indicate the arrangement, with a null symbol signifying an empty section. Alternatively, integers can be used: they must be indices of the symbolic indices in the slotfiller, or -1 signifying an empty section. The order of the buttons need not correspond to the order in the slotfiller variable. Omissions and repetitions are allowed, but the repetitions for any given symbolic or numeric index must form a submatrix. In the following examples, commas and parentheses are used only to make the examples immediately obvious. The first statement avoids all overlap of vertical and horizontal buttons, the second one omits the "right" button, and the third one provides partial overlap: `ac has (`geometry;3 3Ò(` `up `),(` `down `),(`left ` `right)); br{`ac;0} `ac has (`geometry;3 3Ò(` `up `),(` `down `),(`left ` `)); br{`ac;0} `ac has (`geometry;3 4Ò(¢1 0 0 ¢1),(¢1 1 1 ¢1),(2 2 3 3)); br{`ac;0} The geometry attribute, like set and unlike f1, is persistent. The free function takes a variable name, in symbol form, as its only argument and, besides displaying a message, returns its argument as an explicit result: free `ac show `ac is `action; br{`ac;0} The buttons are arranged as they were before and they still function as they did, but if you put the pointer in the ac display and press the F1 function key nothing happens. You can also change the order of the buttons by respecifying the underlying variable, unless geometry contains symbolic indices. When you respecify the value of a variable that is bound to a display class, you might inadvertently try to change it to a value that is not allowed for that class. The assignment is refused, either tersely by the interpreter, when the "verify" attribute is 0: `verify of `ac `ac has (`verify;0) acû'No good!' or with an explanation by s, when the verify attribute is 1, the default: ý `ac has (`verify;1) acû'No good!' (The "a action" in the response is presumably for faster execution.) Be sure to clear the suspension: ý 1b(ii). Size Attributes: C R xs ys yxs Corresponding to the position attributes there are size attributes: "ys" is the vertical size of the object, in pixels, and "xs" is the horizontal size. The value of "yxs" is the concatenation of the values of ys and xs. Try these statements: `ys`xs of `ac ;sizeûØ`yxs of `ac `ac has (`yxs;2«size); br{`ac;0} `ac has (`yxs;size); br{`ac;0} You may have noticed the asymmetry of the ac display, caused by the unequal lengths of the labels. When the "C" attribute is 1, the columns are required to be of equal width; the default for C is 0. Watch the display of ac become symmetric when you change C to 1: `C of `ac `ac has (`C;1); br{`ac;0} There is a similar attribute "R", also with default 0, that requires the rows to be of equal height when it is 1. Here is an example showing its use. First, load some auxiliary variables that are in a separate file to avoid cluttering the tutorial; they will all have the prefix ld_ so you will know where they came from. _load{'/usr/local/aplus-fsf-4.18/doc/tutorials/s.tutorials/aux_vars.+'}; aû(`a`b`c`d`e`f`g`h`i`j`k`l`m;(;;;;;;;;;;;;)) lbû('Exit';'Refresh';'Corporate Axes'),ld_nlb `a has (`class`shelltitle`title`label;(`action;'nexus';'';lb)); Note the use of a slotfiller to specify several attributes at once. The shelltitle, title, and label attributes are discussed in the next section, and class in a later section. gû` ` `a`a `b`b ` ` ` `,(20Ò`),Ø5Ò¡`c`d`e`f`g`h`i`j`k`l`m` `a has (`C;1; `geometry;9 10Òg; `show;1; `xs;600); br{`a;0} The two empty rows take no space now. Setting R to 1 provides the vertical separation implied by the geometry: `a has (`R;1; `xs;600); br{`a;0} _ex¡ `sector `size `lb `g, free `a 1b(iii). Displayed Characters Attributes: justify label labelfont shelltitle title titlefont The "A+" appearing at the top of the ac display is the default value for the "shelltitle" attribute for a top-level object. To change it, change the value of the shelltitle attribute: `ac has (`shelltitle;'Move') The "ac" below the shelltitle is the default value of the "title" attribute. To change it: `ac has (`title;'') `ac has (`title;' ') `ac has (`title;'Direction') Notice that an empty vector means no title area at all. The symbolic index names appearing on the buttons are, again, the default. They appear when the "label" attribute is null. The label attribute governs what is shown in the label areas. (When there are also value areas, as in the slot class, it has no effect on them.) If its value is a character vector or a single symbol, the same label appears on all buttons: `ac has (`label;'Push') `ac has (`label;'') The buttons can be separately labeled using either a vector of symbols or a nested vector of scalars or vectors: `ac has (`label;`u`d`l`r) `ac has (`label;('Ù';'Õ';'û';'ý')) The label attribute is functional, the function being called once for each button with the path as an argument: f{s;d;i;p;c;v}:pØ(`left`right`up`down;('l';'r';'u';'d')) `ac has (`label;f) The fonts need not be the default, kaplgallant-19. Try the "titlefont" and "labelfont" attributes: `ac has (`titlefont;'times-19'); br{`ac;0} `ac has (`labelfont;'helvetica-boldoblique-19') The labels are centered in both directions within the buttons, by default. The "justify" attribute is used to modify their positions. Essentially, its argument is one of 'l' 'r' 't' 'b' 'lt' 'lb' 'rt' 'rb' `left `right `top `bottom, and it is cumulative (the first statement below produces no visible effect, since there is no extra vertical space): `ac has (`justify;`bottom) `ac has (`justify;`left) `justify of `ac `ac has (`justify;'r') `justify of `ac In the character form, a period at the beginning of the argument makes it non-cumulative: `ac has (`justify;'.rt') `justify of `ac A .t or .b argument centers the labels horizontally, .r or .l vertically. To restore the positions to centered both ways, set justify to null: `ac has (`justify;) 1b(iv). Color Attributes: bg fg labelfg titlefg There are four attributes that govern the colors in the display. The default values are: `titlefg `labelfg `fg `bg of `ac The foreground attributes, "...fg", refer to text and the "bg" to background. In our example there is no text corresponding to the "fg" attribute. In a member of the array display class it would be the array values (see the Data tutorial); in the slot class it would be the contents of the value areas; and so on. These attributes can be set to whatever colors you want, as in: `ac has (`titlefg;`blue); `ac has (`labelfg;`green); Vectors of colors can also be used for the labels. The colors are used cyclically: `ac has (`labelfg;`blue`brown`green`red); `ac has (`labelfg;`blue `red); `ac has (`fg;`pink); `ac has (`bg;`yellow); The default colors can be restored by giving null values: `ac has (`titlefg `labelfg `fg `bg;(;;;)); 1c. Additional Windows 1c(i). Kinds of Windows Attributes: iconic ws Variable: s.WS A+ can, of course, display more than one window at a time. Produce three more windows, without stopping to make their buttons work. Notice that they all appear originally in the top left corner, the default position: bû(`run `stop `cancel;(;;)) cû(`yes `no `more;(;;)) dû(`load `save;(;)) show¡ `b`c`d is¡ `action br{`b;0 600}; br{`c;0 400}; br{`d;0 200} You might want each of them to be sized according to its labels, the default. Suppose, however, that you want them to be all the same size. Enlarge the smaller ones: `c`d has¡ <(`yxs;>`yxs of `b);br{`d;0 200} Incidentally, the vertical justification that you took on faith can now be demonstrated: `d has (`justify;`bottom); `d has (`justify;); The new windows are popups, as can be seen by their having pins rather than buttons at the top left. (See the s-Context Variables tutorial for a way of changing this default.) It is possible to change them from popups and back again, using the "iconic" attribute, which controls this property: `d has (`iconic;1); `d has (`iconic;0); The s-context variable s.WS contains the name of the "screen workspace", which is always a top-level object, not a popup. (The significance of the screen workspace is discussed in the next section.) The default value of s.WS, before any objects are shown, is the Null. When an object is initially shown and s.WS is null, that object becomes the screen workspace unless you prevent it. When an object is first shown, it is prevented from becoming the screen workspace if the value of its "ws" attribute is 1, and not prevented if ws is 0. If you change the value of s.WS, you name a new screen workspace and you "demote" the old one to a popup: `d has (`shelltitle;`Popup); s.WSû`d s.WSû`ac `ac has (`shelltitle;`Move); Notice that the value of the shelltitle is treated as related to the screen workspace: when the screen workspace was changed, the ac display was given its variable name as a shelltitle and d was given "A+", the default shelltitle, and the reverse happened when the screen workspace was changed back. The shelltitles that had been set were lost in the process. 1c(ii). Visibility Attributes: followers followertree hide icon icontitle lower raise show The "hide" attribute for a pop-up window, when specified by any value other than 0, removes it entirely from the screen. The "show" attribute, when specified by any value other than 0, restores the display of the window. It can also create the original display of a window sometimes, i.e., be used in place of the show function, as we will soon see. When queried, one of these attributes is always 1 and the other 0, corresponding to the visibility of the window: `d has (`hide;); `hide`show of `d `d has (`show;); `hide`show of `d The hide attribute for a top-level window, when specified by any value other than 0, changes it to an icon, generally at a different location. Change d to top-level and hide it, then change it to be non-iconic and see the icon disappear: `d has (`iconic;1); `d has (`hide;); `d has (`iconic;0); `d has `show; Note the last form: a value need not be given for an action attribute: the value is assumed to be 1 or, what is equivalent, null. Now keep an eye on all the objects: `ac has `hide; `ac has `show; Notice that when ac was changed to an icon, the other three windows vanished. The reason is that they are "followers" of the screen workspace, as indicated by the attribute of that name: `followers of `ac Suppose that you use the followers attribute to make d a follower of c. The new arrangement is reflected in the reference-only attribute "followertree", whose value is a recursive slotfiller. Then when c is hidden, d will be hidden also. Although d is no longer a follower of ac, it will still follow it into hiding because it is a follower of a follower of ac: `c has (`followers;`d); `followertree of `ac `c has `hide; `hide of `d `c has `show; `ac has `hide; You can change the icon image and title, using the "icon" and "icontitle" attributes. The value for the icon attribute must be an m by n bit matrix, with m and n each at most 64: `ac has (`icontitle;'Buttons'); `ac has (`icon;64 64Ò1 0 0 0 0); `ac has `show; The other way to change visibility is to put one window in front or in back of another, i.e., have one window obscure another. To put one in front, set its "raise" attribute to anything; to put it in back, set its "lower" attribute to anything. Note that lowering a window places it in back of everything, including the emacs session window, and that the followers attribute is for hiding, not lowering or freeing: `d has (`lower;); `d has `raise; `ac has `lower; `ac has (`raise;0); `raise of `ac Unlike hide and show, raise and lower are pure action attributes: even setting them to 0 causes their normal actions, and no value can be shown for them; the of function disavows them. Now make d a follower of ac again: `d has (`leader;`ac); 1c(iii). Selection Mouse Pointer Keys: Arrows Ctl-Shift-Tab Ctl-Tab Enter Shift-Tab Tab You have already seen that when the f1 attribute is given a non-null value for some object, the mouse pointer must be in the object's window in order for the F1 function key to trigger the specified action. This property of the keys' applying to a particular window is called "keyboard focus". It is signalled by a brightening of the window's border. You can give keyboard focus to any window that is at least partially visible just by moving the pointer into any visible part of it. When one s window has focus, you can move the focus to another by pressing Control-Tab or Control-Shift-Tab. Move the mouse pointer into one of the s windows and press Control-Tab four times. You will see keyboard focus and the pointer move from one window to another. Press Control-Shift-Tab and you will see the keyboard focus traverse the windows in the opposite order. Within a window, you can move the selection from one field to another by pressing Tab or, to go in the opposite order, Shift-Tab. Move the pointer to the ac window and press Tab four times and then Shift-Tab four times. The visible sign of selection is a gold border around the selected button. One significance of selection is that you can press the selected button by pressing the Enter key. (Because the buttons move the ac window, you may have to move the pointer to maintain focus after pressing Enter.) Now move the pointer onto a button of another object, press and hold the left mouse button, then release it and press and hold the Enter key. Do you see a significant difference between the two ways of pressing the displayed button? When you use the left mouse button, the displayed button stays depressed for as long as you hold the mouse button down: the displayed button acts as if it were the mouse button. When you press and hold Enter, however, the usual typamatic action takes place: the displayed button is pressed and released once, and then, after a slight pause, it is rapidly pressed repeatedly until the Enter key is released. Moving selection within a row or column can also be done with the arrow keys. Movement appropriate to the key occurs in a cyclic fashion. Try the up and down arrow keys in the various windows after selecting a button. Notice that two buttons are isolated from the other two in ac as far as these arrow keys are concerned. Then try the left and right arrow keys in the various buttons of ac. 1d. More about Appearance 1d(i). Changes in Appearance Attributes: hl hlthickness shadowthickness Three appearance attributes are related to selection and pressing of buttons. The "hs" attribute controls the color of the selection border; its default value is gold. Execute `d has (`hl;`mediumseagreen) and move the pointer to give focus to d, so that you can see the green border. The "hlthickness" attribute controls the width of the border; its default value is 0, which means the thinnest. Execute `c has (`hlthickness;5); br{`c;0 400} and see how the object is enlarged, to allow for the wider border. Now give focus to c, so that you can see this border. When an action is taken to press a displayed button, the button appears to be physically pressed. The button is darkened; its bottom and right edges are highlighted, instead of its top and left; and its top and left edges are shadowed, instead of its bottom and right. Thickening the edges of the buttons increases their apparent height and emphasizes this apparent action. The thickness is controlled by the value of the "shadowthickness" attribute, which has a default value of 2. Execute `b has (`shadowthickness;6); br{`b;0 600} and see how the object is enlarged, to allow for the thicker edges. Now press one of b's buttons, and notice how the shadow is switched. When an object is placed in a container, giving it a shadowthickness of zero is sometimes useful, so that its buttons do not seem separate from other objects in the container: `b has (`shadowthickness;0) 1d(ii). Other Features Attributes: exit foot head is leftfoot pin resizeable rightfoot In popups, the pin can be used for communication between the viewer and the programmer. For example, the viewer can push the pin in to say that he wants to have the window remain visible or pull it out to indicate that he would like to have the window removed. Likewise, the programmer can show the pin in or out to state his intentions. The viewer changes the pin position by clicking on it with the left mouse button. In an A+ statement, the "pin" attribute is used to set the position. This attribute always reflects the pin position, 1 for in and 0 for out. Try this sequence: `pin of¡ `b`c `b has (`pin;1) Place the mouse pointer on the pin of c and press and release the left mouse button. `pin of¡ `b`c `b has (`pin;0) Click on the pin of c again. The c window vanished, didn't it? The "exit" attribute determines what happens when a viewer attempts to remove an object from the screen. Its default value is 1, which means hide the object. By changing this value to 0, say, you can have nothing happen when the pin is pulled: `d has (`exit;0) `d has (`pin;1) Now click on the pin of d. The pin moves, but nothing else happens. You can push and pull the pin as much as you like and nothing happens. Exit is functional: its value can be a function. It can be set for top-level windows as well as popups. For example: no{x}:Õ"Don't do that to the ",x," window,",sys.getusername{},"!" `b has (`exit;(no;Ø`title of `b)) `ac has (`exit;(no;Ø`title of `ac)) Now push and pull the pin of b. Place the tip of the mouse pointer in the window-manager button of the ac window, press and hold the right mouse button, move the pointer down to "Quit", and release the button. In both instances, the no function is called and the usual behavior does not occur, an admonition appearing instead. If, however, you click on the window-manager button of the ac window or choose "Close" from its menu, the window will be hidden; then double-clicking on its icon will bring it back. Three otherwise unrelated attributes pass along window-manager facilities, and cannot be changed for a window after it has been shown. They are "head", "foot", and "resizeable". None applies to objects that are not top-level or popups, since they relate to window-manager features. The head attribute determines whether a window has a window-manager area at the top; since that area is not removable for top-level objects, head applies only to popups. The foot attribute determines whether there is an area at the bottom for footnotes. The resizeable attribute determines whether the window has resize corners; that is, whether a viewer can resize the window by dragging. These attributes are set between binding and mapping, so this is a good time to mention the "is" attribute. It can contain a function (and, optionally, an argument) that is called immediately after the variable is bound. Its default is null. eûd f{x}:Õ(Îx),' is bound to ',,ÎØ`class of x `e has (`is;(f;`e)) `e is `action `e has (`resizeable `head `foot;(0;0;1)) show `e; br{`e;0 200} Note that the e display has no panel at the top, so no pin or shelltitle appears; it has a panel at the bottom that becomes lighter when the window has focus (and that can be used for moving with the mouse); and it should have no resize corners -- although it probably does have them, because of a window manager bug, an interaction between resizeable and head that causes only the one that is set later to be obeyed when they are both set to 0. Two footnotes can appear; they are the values of the "leftfoot" and "rightfoot" attributes. Space is not made for them automatically, and they are truncated if there is not enough room: `e has (`leftfoot;'Morgan Stanley') `e has (`xs;150) `e has (`rightfoot;'March 1994') `e has (`xs;250) 1e. Status and its Preservation 1e(i). Status Attributes: bound class stateself settings There are attributes which give you information about objects. Some, like the "bound" and "class" attributes, apply meaningfully to objects that are not bound. The class attribute for an unbound variable, for instance, is its default display class. You cannot set bound directly; it is a reference-only attribute. prometheusû'fire' `bound of¡ `e `prometheus `class of¡ `e `prometheus `prometheus has (`class;`command) `bound`class of `prometheus The bound attribute is set to 1 by the is and show functions and by a non-null specification of the class attribute; it is set to 0 by the free function and null specification of class. The class attribute is set by the is function to its right argument; it is set to a default class by the free function, in effect, and, if bound was 0, by show. The "settings" attribute, which is for reference only, can be used to obtain a slotfiller holding, generally speaking, the attributes that have non-default values (except the class attribute) and the values of those attributes. `settings of `e The xs attribute was not included, because its value was not known to be non-default. The attributes can be restricted or extended to certain ones by naming them. The statement above is equivalent to (`settings;) of `e. (`settings;`leftfoot `xs `title) of `e The title attribute is omitted, because its value is the default. Since a specific request was made for xs and its value is not known to be the default, it is included. The "stateself" attribute, which is also for reference only, gives the same information as `settings of, plus the value of the class attribute. The value of stateself will create the object when executed in the presence of the underlying variable with a suitable value. It is an s definition of the object in association-list form: `stateself of `e 1e(ii). Saving Attribute: script Variable: s.WM_SAVE_YOURSELF Function: s.script{} The s.WM_SAVE_YOURSELF variable can hold the name of a function and, optionally, an argument. Its default value is null. When "Save Workspace" or "owplaces" is selected from the OLVWM Utilities Menu, the function named in s.WM_SAVE_YOURSELF, if any, is called, allowing any vital information to be saved or necessary actions to be taken. The s-context niladic function s.script produces a script that will recreate the current screen layout, given the presence of the necessary variables with appropriate values. There may be no need to preserve information about some of the objects. The default value of 1 for the "script" attribute dictates that the s definition of the object appear in that script and a value of 0 dictates that it not appear. Try, for example, `d has (`script;0) s.script{} Now clean up for the next display class: _ex¡ `acbfn `pc `diag `f `no, free¡ `ac `b `c `d `e `prometheus 2. The Button Display Class Attributes: margin naturalsize An object of the button class looks rather like an object of the action class with only one button and no title area. The variable that is bound to it does not contain symbolic indices and values, however, but rather a function array and perhaps data. The function must be monadic or niladic. Specifically, let fn be a monadic function and define b as (fn;data). Then b can be bound to the button class, and whenever the button is pressed, fn{data} will be executed. A second form for defining a button is <{fn}, which is equivalent to (fn;) for monadic functions; when the button is pressed, the expression fn{()} or, for a niladic function, fn{} is executed. Notice that for the button class no callback need be set; the function that is bound is called automatically. As an example, define a button that, when pressed, moves across the screen and jumps back, but don't press it until after you have made the comparison set up below: bf{v}:v has (`x;600|100+Ø`x of v) buû(bf;`bu) show `bu is `button; br{`bu;0} Just for a comparison of their appearances: acû(,`bu;,<1) `ac has (`class;`action; `title;''; `show;1); br{`ac;0 50} _ex free `ac Now you can press the button. There is no title area like the one an action object can have; the title attribute applies to the text on the button (unlike for an action object, which employs the label attribute for text on its buttons). When there are no blanks or other impermissible characters in it, a title or label can be given as a symbol, instead of a character string. The object is not automatically resized for a new title: `bu has (`title;`Move) The "naturalsize" attribute is an action attribute; it cannot be queried. It resizes an object to show it afresh, as if it, with its current text, values, and features, were being initially displayed -- `bu has (`naturalsize;); br{`bu;0} -- except that in an array or matrix or suchlike the same rows and columns might not be shown as originally, as demonstrated in the discussion of naturalsize in the array section of the Data tutorial. The "margin" attribute governs the minimum margin around the title on the button; its default value is 2. It does not affect the button size: `margin of `bu `bu has (`margin;10); `bu has `naturalsize; br{`bu;0} `bu has (`margin;200); `bu has `naturalsize; br{`bu;0} `bu has (`margin;2); `bu has `naturalsize; br{`bu;0} The margin attribute also applies to the margin around the text in an object of the label class. _ex free `bu 3. The Check Display Class An object of the check class is a slotfiller variable with boolean values that are represented by buttons. A button is "on" if the corresponding value is 1 and "off" if it is 0. When a button is on it has a sunken appearance and is the color specified by the fg attribute, and when off it has a raised appearance and is the color specified by the bg attribute. Clicking the left mouse button on a check button toggles it between on and off, and at the same time the corresponding value in the A+ variable is toggled between 1 and 0. Therefore, if a callback function is defined for the slotfiller variable, mouse clicks cause the callback function to be executed, the path argument p being the symbolic index of the changed value. The slot areas that appear in the display and their arrangement can be controlled by the setting of the geometry attribute. This first example is a two-button moving display, in which pressing a button moves the display to the position indicated by its buttons: cû(`bottom`right;(0;1)) `c is `check cbf{}:`c has (`yx;500«Ø1Øc) `c has (`show;1;`set;cbf;`yx;0 500) `c has (`fg;`mediumseagreen;`bg;`rosybrown) Try the various button combinations. In the second example, we show one way to set up a check display to allow one or more categories of data to be selected. Actually, the function we define here for the button just lists the selected categories in the session log when it is pressed: ckû(`cb`ci`co`ib`i`s`sb`wb`w;(0;0;0;0;0;0;0;0;0)) lbû(`cmo_bid;`cmo_inventory;`cmo_oddlot),ld_clb ckfn{}:Õ>(Ø1Øck)/Ø`label of `ck `ck has (`class;`check; `set;ckfn; `geometry;9); `ck has (`shelltitle;`CMOView; `title;'CMO Inventory Viewer'); `ck has (`labelfont`titlefont;2Ò<'newcenturyschlbk-roman-16'); `ck has (`label;lb; `show;1; `xs;1140); br{`ck;0} Press some category buttons, adding to and deleting from the set of requests. Observe the list that appears in the A+ session log each time. _ex¡ `lb `cbf `ckfn `bf, Øfree¡ `c `ck 4. The Radio Display Class The radio class is like the check class, except that (1) it has the additional stipulation that one and only one of the values of the boolean-valued slotfiller is 1, (2) its buttons are diamond-shaped, and (3) pressing a button that is off turns it on and causes the button that had been on to be turned off (pressing a button that is on has no effect). When a button that is off is pressed, the value of the underlying variable is changed accordingly. Therefore, if a callback function is defined for that variable, it is called, the path argument p being equal to the symbolic index of the selected button. Note that even though there are two value changes, a callback function associated with the variable of a radio button is called only once, and the path argument of the callback function refers to the value that changed from 0 to 1. The slot areas that appear in the display and their arrangement can be controlled by the setting of the geometry attribute. In our first example, we make the usual moving buttons. Execute the following statements and press various buttons: rû(`tl`t`tr`l``r`bl`b`br;(1;0;0;0;0;0;0;0;0)) cbf{}:`r has (`yx;0 250 500[3 3Î(Ø1Ør)É1]) `r has (`class;`radio; `set;cbf; `geometry;3 3 3; `show;1); In more realistic examples, the radio object might offer a choice among four differently formatted security definition tables and also function as a heading for that table, or it might present a choice of security types for listing portfolio holdings. In our examples, the callback function merely gives (in the session log) a waiter's response: _ex free `r rdû(`ms`ba`na`bl;(0;1;0;0)) `rd has (`class;`radio; `geometry;¢2; `shelltitle;'MBS'; `title;''); `rd has (`label;('BASIC MBS/STRIP';'BASIC ARM'),ld_rlb); cbf{s;d;i;p;c;v}:Õ(>(Ø`label of `rd)[(0Ørd)Ép]),'. Good choice.' show `rd has (`set;cbf); br{`rd;0} Now the second example: `rd has (`hide;1;`shelltitle;`PH;`fg;`white;`labelfg;`white;`bg;`black); `rd has (`label;('Corporate';'Municipal'),ld_r1lb); show `rd Ý rdû(`co`mu`mo`cm`us`ab;(1;0;0;0;0;0)); br{`rd;0} Notice that you can click on the label or the diamond to press the button. _ex¡ `cbf, free `rd