The Container Display Classes ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ 1. General 2. The Window Display Class 3. The Table Display Class 3a. The Headings for the Fields Attribute: titledefine 3b. Interactions between Settings for Fields and Table Attributes: font protected 3c. Controlling What is Shown Attributes: fields firstfield fixedfields 3d. User Interactions Attributes: field selectedfield selectfield 3e. A Case when Refresh is Needed 4. The Graph Display Class 5. The Layout Display Class 5a. Relations among Objects Attributes: ancestors children descendents familytree leader parent shell state 5b. Binding and Showing of Objects Attributes: mapped newshow reparent reshow 5c. Arrangement of the Children Attributes: at build lockposition position structure vcol vcols vrow vrows X Y YX 5d. Size of the Children Attributes: b h H l locksize r resize t w W 5e. Navigation and Interaction Attributes: acceptfocus focus freeze sensitive tabfrom tablist tabto 6. The Hpane and Vpane Display Classes --------------------------------------------------- 1. General As the name implies, objects of a container display class are used to contain other objects, either to group several of them or to provide features that are not available in the contained object's class. The objects that are contained in a container are called its children. For a variable to be bound to a container class, its value must be an array of symbols and each symbol must be either the symbolic form of the name of a variable or null. 2. The Window Display Class A window contains only one object. The value of a variable that is bound to the window class is the name of a single variable, in symbolic form. An object in a window can be of any display class. Placing an object in a window has the effect of putting scrollbars on the display of that object. You should be sure that you really need at least one scrollbar, because they always appear. If the object is completely shown or has its own scrollbars, the window's scrollbars are inoperative; try them after these statements: $load s scrûs.SCREEN-34 12 br{w;m}:{w has (`yx;scr-m+Ø`yxs of w);} a1ûÉ2 2 w1û`a1 show `w1 is `window Ý show `a1; br{`w1;0} Try the various scrollbars after each of these statements: a1ûÉ50 2 a1ûa2ûÉ50 50 It makes no difference whether the scrollbars are needed at the time the window is mapped: w2û`a2 show `w2 is `window; br{`w2;0} The window display class is useful in displaying large objects belonging to the non-container classes that never have scrollbars, namely, action, check, label, page, radio, and slot -- and, of no interest in this regard, button. Here is an artificial example, for the most likely class, slot: sû(,Â`char©97+ô(4Ò26)Î773«É500;<¡?500Ò1000) w3û`s show `w3 is `window; br{`w3;0} Now the vertical scrollbars work. You might think that you could at least minimize the unused horizontal scrollbars by setting hscrollsize to 0, but this attribute does not apply to the window display class. You can, however, adjust the window to fit the slot display better: {`w3 has (`xs;16+>`xs of `s; `shelltitle;'window'); br{`w3;0}; free¡`w1`w2;} Having the horizontal scroll bar, one might be inclined to make it useful: `s has (`geometry;10; `title;'slot'); Can you find the title? The title appears at the middle of the top of the slot and is scrolled with the rest of the slot. Contrast its immobility when both the title and the scrollbars are part of the same object. Notice that the shelltitle comes from the window object and the title from the slot. A title is never displayed for an object of the window display class, nor, naturally, a shelltitle for an object contained in any container class. _ex¡ `a1`a2`w1`w2, Øfree¡ `w3`s; 3. The Table Display Class A table is different from other containers, in that all the objects contained in it (its children) are of the tableField class; they are called fields of the table. The fields of the table can be vectors or simple character matrices. An object can be bound to the tableField class only by A+ and only as a child of a table object. The children of a table object, like all objects shown on the screen, must be unique. The display of a table consists of a title area and a value area. The value area has a title bar on top that holds the names of the fields, and the area below the field titles consists of delineated cells, one column for each field. The fields appear on the screen in the same left-to-right order as their symbols appear in the variable that is bound to the table class. The number of elements in the first field completely controls the rows that can be displayed. Examine the following example: var_0û10 4Ò'blah' var_1û1+É10 var_2û¢150+.01«?10Ò100000 var_3:var_2ßvar_1 tbû`var_0 `var_1 `var_2 `var_3 `tb is `table; `tb has (`shelltitle;'shelltitle'; `title;'title'; `cols;4); `var_2 `var_3 has¡ <(`out;7.2); show `tb; br{`tb;0} 3a. The Headings for the Fields Attribute: titledefine The title bar text for a field can be changed by using the field's title attribute. For a dependency, there is another alternative. The "titledefine" attribute provides a means of displaying the definition, rather than the name, of the dependency. Its effect becomes visible only when the title attribute is set to null. To see the immediate effect of titledefine, watch the fourth field. Because the last column is too wide to be shown in its entirety and s doesn't like to display partial columns, the fourth column gets blanked out. (Under some circumstances you can see a truncated definition.) We force a redrawing after setting titledefine and title: `var_0 has (`title;'Text'); `var_3 has (`titledefine;1; `title;); `tb has (`firstcol;0; `cols;4); br{`tb;0} The next two statements demonstrate that titledefine does not set the title, but rather that it is consulted when the title is set to null: `var_3 has (`titledefine;0); `var_3 has (`title;); `var_0 has (`title;); 3b. Interactions between Settings for Fields and Table Attributes: font protected The "font" attribute specifies the font in which the value area appears. In the table display class, it can be set for both the fields and the entire table. The setting for the table applies to any fields for which font has not been explicitly set. Notice two things in the following statements. First, when the font is changed for the first field, the space allotted to the field is narrowed, resulting in the truncation of the title; watch out for this if you change a font after showing a table. Second, the font for the table does not affect the first field, whose font has already been specified. `var_0 has (`font;'courier-bold-19'); `tb has (`font;'palatino-19'); `tb has (`firstcol;0; `cols;4;); br{`tb;0} The font attribute is functional. Set it for the third field, overriding the table setting but leaving the other fields alone (you will probably need to scroll down to see a negative value in boldface): f{s;d;i;p;c;v}:if (d<0) 'helvetica-bold-19' else 'helvetica-19' `var_2 has (`font;f); Try to trim the column widths: `var_0`var_1`var_2`var_3 has¡ <(`space;12); `var_0`var_1`var_2`var_3 has¡ <(`font;`kaplgallant; `space;12); `tb has `naturalsize; br{`tb;0} Because the characters are not of fixed width, the results of the space specifications were not what we wanted; after the font change, space was set as intended, and the table could be trimmed to fit. The "protected" attribute tells whether protection is on; it is for reference only. It is useful because protect for a table overrides protect for its fields: `var_1 has (`protect;1); Ø`protected of¡ `var_1 `var_2 < 1 < 0 `tb has (`protect;1); Ø`protected of `var_2 1 `var_1 has (`protect;0); Ø`protected of `var_1 1 3c. Controlling What is Shown Attributes: fields firstfield fixedfields One important feature of tables is the ability to retain certain fields in view while scrolling among others. In a table of bond information, for instance, you might want to have issuer, coupon, and maturity always shown, no matter what other fields were or were not visible. The value of the "fixedfields" attribute is the number of fields on the left that do not participate in horizontal scrolling: `tb has (`fixedfields;1); `tb has (`cols;2; `firstfield;`var_2); Notice the gap; the second field is not shown. Try some horizontal scrolling. The "fields" attribute always has the same value as the cols attribute: setting one for a table sets the other: `fields of `tb `tb has (`fields;3); `cols of `tb The firstcol attribute is affected by fixedfields for tables. It is the first visible field on the left disregarding the fixed fields. The "firstfield" attribute differs in taking the name of a field, in symbol form, rather than a number, but is otherwise the same as firstcol, and setting one for a table sets the other: `firstfield `firstcol of `tb `tb has (`fixedfields;0; `fields;2; `firstfield;`var_1); `firstcol of `tb `tb has (`firstcol;0); `firstfield of `tb 3d. User Interactions Attributes: field selectedfield selectfield In addition to selecting a cell by clicking the left mouse button with the pointer in it, you can select a column by clicking the button with the pointer on a title. When a field title is selected, the selected cell is at the intersection of that field and the currently selected row; if no row is currently selected, the first row (row 0) is used. The value of the "selectedfield" attribute is the identity of the selected cell, as row index and, in symbolic form, field name. This attribute identifies the same cell as does the selected attribute, whose value is its row and column indices. Similarly, the "field" attribute gives the (symbolic) field name of the selected column, which is always the same column that is identified by index number in the col attribute and that is referred to in the selectedfield and selected attributes. Make some selections by clicking on the titles and in the cells, executing the following statement after each selection: `field `selectedfield of `tb A callback is associated with selection of a field, and a function is specified for it using the "selectfield" attribute. Here we use a function that just shows its arguments and the value of the selectedfield attribute: cb{s;c;v}:Õ(s;c;v;Ø`selectedfield of `tb) `tb has (`selectfield;(cb;'field selection')); Select a field or two and see the arguments and the value of selectedfield. Also select a cell or two directly and see that this function is not called. 3e. A Case when Refresh is Needed The "refresh" attribute was introduced in the array section of the data display tutorial. Here is another example of its use. To minimize backing store space requirements, when a substantial amount of data is only potentially displayed it is not always calculated in advance. If its display is requested through the window manager and not A+, it may be necessary to request that A+ refresh the object: alûblû1000+É100; tlû`al`bl; show `tl is `table; `tl has (`ys;1750;`x;scr[1]-Ø`xs of `tl); Now use the scrollbar to drag the later part of the table into view. It should be blank. Specifying refresh causes the numbers to be calculated and shown: `tl has `refresh; _ex¡ `cb`f, Øfree¡ `tb`var_0`var_1`var_2`var_3`tl`al`bl; 4. The Graph Display Class The graph display class resembles the table class in that its children are all of one class, graphTrace, and only A+ can bind a variable to that class. Because of its complexity, it is treated in a separate tutorial. As an aside, we might mention that because all the graph features are optional, it is possible to produce pictures using an object of the graph class, as in this simple example: jû¢100+É200 t1ûj(,@0)100 t2ûj(,@0)¢975+(1000000-j*2)*.5 t3û1 2Ò20 75 gû`t1`t2`t3 `g is `graph; `g has (`title `legend `axis `zero;('';`none;`none;`none)); `g has (`xmin;¢100;`xmax;100; `ymin;0;`ymax;100); `t1 `t2 has¡ <(`style;`area); `t3 has (`style;`scatter; `symbol;`circlefilled; `symbolsize;50); `t1 has (`linecolor `fillcolor; 2Ò<`cyan2); `t2 has (`linecolor `fillcolor; 2Ò<`cornflowerblue); `t3 has (`linecolor `fillcolor; 2Ò<`yellow); show `g; br{`g;0} The area style fills in down to the axis. Only the order of drawing prevented the cyan from obliterating the blue. The fill style allows fuller control of the area covered, as in this example of three rectangular planes: p1û4 2Ò ¢90 10 ¢90 70 0 70 0 10 p3û(4 2Ò30 10)+ p2û(4 2Ò30 10)+p1 gû`p1`p2`p3; free¡ `t1`t2`t3; `p1`p2`p3 has¡ <(`style;`fill); Reversing the order of the symbols in the definition of g reverses the order of drawing and thereby the obscuration and apparent depth of the planes: gû`p3 `p2 `p1; _ex¡ `j`t1`t2`t3, Øfree¡ `g`p1`p2`p3; 5. The Layout Display Class A layout is a container whose children can be of any classes. Almost all of what is said in this section applies also to the hpane and vpane classes, which are essentially just layouts with slider bars. When a child is placed in a layout, the context of its name is assumed to be that of the layout's. There is no need to qualify the child's name unless its context differs from the layout's. 5a. Relations among Objects Attributes: ancestors children descendents familytree leader parent shell state The first seven attributes listed above give information about containment and subordination of objects. All but two are for reference only. Knowing that an object is called the child of its container, you can guess the meanings of most of these attributes. Here is a simple example illustrating their use: aûbûcûdûeûnûÉ3 show `a; br{`a;0 200} l1û`b`c; l2û`d`e; lû`l1`l2; `l`l1`l2 is¡ `layout; show `l; br{`l;0} `children of `l `children of `l2 The "children" attribute is actually not just for reference: `l has (`children;`l1`l2`n); `children of `l l So the children attribute of l changed value and, as had better be the case, the value of l changed. The display, however, did not change. When an object that is not being shown is added to an existing layout, the default is not to show it there automatically. One way to make it appear is to apply the show function to it, before or after it is added to the layout (you will see several other ways later on): show `n; br{`l;0} `descendents of `l `parent of `d `ancestors of `d The "familytree" attribute applies only to containers, since it shows only the object's descendents and not its ancestors: `familytree of `l `familytree of `l2 `familytree of `d The "shell" attribute contains the name of the top-level object that contains the object in question. The "leader" attribute, for top-level objects only, tells what object will be followed into hiding; its default value is the screen workspace. A top-level object can be made its own leader; the canonical value for the leader attribute in this situation is the Null: `shell of `d `leader of `l `l has (`leader;`l) `leader of `l You have already seen the stateself attribute, in the Buttons tutorial. The "state" attribute is similar to it, but recursive. That is, for a container the stateself attribute gives only the definition of the container itself, whereas the state attribute includes the value of the state attribute for each child. When a child appears in a layout definition more than once (to establish the desired geometry), the state for it is given only once, for economy. For tableFields and graphTraces, the class does not appear in the result, to keep it executable. `stateself of `l `state of `l _ex¡ Øfree¡ `l`l1`l2`a`b`c`d`e`n; 5b. Binding and Showing of Objects Attributes: mapped newshow reparent reshow When a layout is first shown, all its children are shown. When children are added to it, however, they are not automatically shown in it unless they were already shown somewhere. A simple example: aû'original'; bû'show fn'; cû'show attribute'; dû'mapped'; eû'newshow'; `a`b`c`d`e is¡ `label; show `b; lû`a; show `l is `layout; br{`l;96 72} lû`a`b`c`d Although l has four children, only two are shown: a because it was a child when the layout was first shown and b because it was already shown when it was added to the layout. If you set the show attribute of a child to 1, it will be shown: `c has (`show;1); In fact, it is enough to set the "mapped" attribute to 1: `d has (`mapped;1); Setting the mapped attribute for a top-level object to 0 when it is shown (unmapping it) has the effect of making its contents blank.This effect can be useful when you are making several changes in a layout and do not want the flashing that would otherwise occur: `c has (`mapped;0); `l has (`mapped;0); `c has (`mapped;1); `l has (`mapped;1); When the "newshow" attribute is 1 for a layout, any child that is added to that layout is shown: `newshow of `l < 0 `l has (`newshow;1;); lû`a`b`c`d `e Similarly, you can control what happens when a child is removed from a parent (orphaned). By default, the child becomes a top-level object (it is made its own parent) and it is shown independently. If, however, you set the "reshow" attribute to 0, then an orphaned object still becomes top-level but is not shown. Furthermore, if you set the "reparent" attribute to 0, it is not made its own parent but rather is freed, and of course is therefore not shown: Ø`reshow `reparent of `l 1 1 lû`a`b`c`d ã .e: variable reparented to popup window `l has (`reshow;0); lû`a`b`c ã .d: variable reparented to popup window `show of `d < 0 `l has (`reparent;0); lû`a`b ã .c: freed _ex¡ `c, Øfree¡ `l`b`c`d`e; 5c. Arrangement of the Children Attributes: at build lockposition position structure vcol vcols vrow vrows X Y YX Starting with a null layout allows you to set attributes: a1ûa2ûa3ûa4ûa5ûa6ûa7ûa8ûa9ûa10ûÉ10 12 lû() `l has (`class;`layout); When a variable is to be bound to the layout class, the arrangement of the symbols in it usually determines the geometry of the display. (Compare the geometry attribute, with symbolic indices, for an action display.) A+ arranges the display when the variable is a vector: lû`a1`a2`a3`a4`a5`a6 show `l; br{`l;0}; `l has (`y;0); Each item of a nested vector is taken to represent a row: lû(`a1`a2`a3; `a4`a5`a6); br{`l;0} lû(`a1; `a2`a3; `a4`a5`a6); br{`l;0} As you are probably about to see (or saw), the history of a layout affects its display when its geometry is changed. Setting naturalsize provides the arrangement that would appear if the layout were new: lû(`a1`a2`a3; `a4`a5`a6) lû(`a1; `a2`a3; `a4`a5`a6) `l has `naturalsize; A matrix form for the layout variable establishes the virtual rows and columns of the display, with the empty symbol is used to indicate a blank area. You will notice a lot of drawing, giving a jumpy effect; this could be avoided by hiding or unmapping the object, making the changes, and then showing the variable again: lû3 2Ò`a1`a2 `a3`a4 `a5`a6; `l has `naturalsize; br{`l;0} lû4 3Ò`a1`a1`a2 `a1`a1`a3 ``a4` `a5``a6; `l has `naturalsize; br{`l;0} {lû4 5Ò`a1`a1`a2`a2`a2 `a1`a1`a3`a3`a3 ``a4`a4`a4` `a5`a5``a6`a6; `l has `naturalsize; br{`l;0}} The layout variable can be a matrix of matrices, each submatrix indicating the arrangement within its area of the matrix: {`l has (`newshow;1); lû2 2Ò(2 1Ò`a1`a2;1 2Ò`a3`a4;;4 1Ò`a5`a6`a7`a8); `l has (`ys;800); br{`l;0}} l[1;0]û<1 2Ò`a9 `a10; br{`l;0} free `l; The "build" attribute for a layout allows you to arrange objects on the screen and have the relative arrangement of those objects maintained in the layout display. You could get the size and position you wanted for the objects by dragging them, but we will set their yx and yxs attributes instead in this simple example: show `a1; `a1 has (`yx;350 300); show `a2; `a2 has (`yx;350 550); show `a3; `a3 has (`yx;580 300; `yxs;170 440); show `a4; `a4 has (`yx;350 770;`yxs;390 200); lû(); `l is `layout; `build of `l `l has (`build;1); lû`a1`a2`a3`a4; show `l; br{`l;0} It would clearly be simpler to use a non-vector value for l to obtain this particular layout, but in complicated cases build might provide the easiest means of specification, or you might want to let a viewer decide the arrangement. Implied in all of these methods and explicit in the method we are about to explore is the idea of virtual rows and columns, whose edges are established by edges of the children and which may be spanned by children. The "at" attribute is a four-element integer vector representing the position and extent of an object in a layout in terms of these divisions: (starting virtual row, starting virtual column, number of virtual rows spanned, number of virtual columns spanned). Conceptually, a layout can be placed over an imaginary grid so that the border of each object in the layout lies on grid lines. The position and size of each object can then be described by the row index and column index of the grid block containing the upper left corner of the object, and the number of grid rows and columns that the object overlaps. If the grid is the minimal one, i.e., the one with the fewest possible grid lines, then these four numbers are the value of the at attribute. The origin for the grid coordinates is the upper left corner of the layout. The complexity of building a layout from screen positions may lead to unexpected at values, but when the layout is specified by, say, a matrix value, then at is what you would expect: >Ø`at of¡ `a1`a2`a3`a4 0 0 7 8 0 10 7 8 9 0 7 18 0 19 16 8 lû2 3Ò `a1`a2`a4 `a3`a3`a4 >Ø`at of¡ `a1`a2`a3`a4 0 0 1 1 0 1 1 1 1 0 1 2 0 2 2 1 The "structure" attribute of a layout, which is for reference only, gives you a slotfiller containing the values of at for all of its children: `structure of `l < < `.a1 `.a2 `.a4 `.a3 < < 0 0 1 1 < 0 1 1 1 < 0 2 2 1 < 1 0 1 2 The four elements of the at attribute value are synonymous with the attributes "vrow", "vcol", "vrows", and "vcols"; they can be set individually to rearrange a layout, as in the first line below. You can specify the entire arrangement of a layout by setting the at attribute on each of its children, as in the four-line statement group below: `a3 has (`vcol;1;`vcols;1);`a1 has (`vrows;2);`l has `naturalsize {free `l; lû`a1`a2`a3`a4; `l is `layout; `a1 has (`at;0 0 1 2); `a2 has (`at;1 0 1 1); `a3 has (`at;1 1 1 1); `a4 has (`at;2 0 1 2); show `l; br{`l;0 200}} The R and C attributes that you saw in the Buttons tutorial can be used to constrain the virtual rows or columns of a layout to be all the same size: lû(`a1``a2;```;`a3``a4); `l has `naturalsize; `l has (`C`R;(1;1)); The "YX", "Y", and "X" attributes are related to the yx, y, and x attributes, respectively. The latter three can be set or referenced and they pertain to the position of an object (in pixels) within its parent or, for top-level objects, within the screen. The former are for reference only and always pertain to the position of the object (in pixels) within the screen: `YX `yx of `l < 327 538 < 327 538 `YX `yx of `a1 < 357 540 < 30 2 Several objects can occupy a layout in such a way that only one is visible at a time, taking up the entire area of the layout, and any other one can be brought into view simply by setting the value of its raise attribute to 1. Since the objects within the layout can themselves be layouts, or other complex objects, this provides a simple, efficient, and general way of displaying multiple objects when only one must be visible at a time. You use the "position" attribute to accomplish this. This attribute must be set before the layout is built, so start with a null layout and set position and then give the layout its correct value: free `l; lû(); `l is `layout; `l has (`position;0) lû`a1`a2`a3`a4`a5`a6`a7 show `l; br{`l;0} `a4 has (`raise;1) When you remove children from a layout by freeing or unmapping them, the remaining objects may or may not retain their positions. The "lockposition" attribute forces them to remain in the same positions. Consider this example of two layouts that are identical except for the values of lockposition (and the locations of the layouts themselves, so you can see them both at once): free `l; a1û'one'; a2û'two'; a3û'three';a4û'four'; a5û'five'; a6û'six'; a7û'one'; a8û'two'; a9û'three';a10û'four'; a11û'five'; a12û'six'; `a1`a2`a3`a4`a5`a6`a7`a8`a9`a10`a11`a12 is¡ `label; lû3 2Ò `a1`a2`a3`a4`a5`a6; llû3 2Ò`a7 `a8`a9`a10`a11`a12; show¡ `l `ll is¡ `layout; br{`l;0 130}; br{`ll;0} `ll has (`lockposition;1; `reparent;0); `l has (`reparent;0); free¡ `a3 `a9; `a2 `a8 has¡ <(`mapped;0); `a4`a6 `a10`a12 has¡ <(`mapped;0); The layout on the left should now have only one column, while the one on the right, for which lockposition is 1, still has two columns, with the two remaining labels still in their original positions. The effect can be perhaps even more pronounced when the layout geometry is a single column: free¡ `l`ll; `a1`a2`a3`a4`a5`a6`a7`a8`a9`a10`a11`a12 is¡ `label; lû`a1`a2`a3`a4`a5`a6; llû`a7`a8`a9`a10`a11`a12; show¡ `l `ll is¡ `layout; br{`l;0 78}; br{`ll;0} `ll has (`lockposition;1;`reparent;0); `l has (`reparent;0); free¡ `a2 `a8; `a5 `a11 has¡ <(`mapped;0); _ex¡ `a2`a8,Øfree¡ `l`ll`a1`a2`a3`a4`a5`a6`a7`a8`a9`a10`a11`a12; 5d. Size of the Children Attributes: b h H l locksize r resize t w W If the "locksize" attribute of a layout is 1, the removal of a child should not cause any remaining child to change size. In Release 2.21, however, if the "locksize" attribute of a layout is 1, the removal of a child cannot cause the layout to change size, although remaining children may change size. The latter behavior is expected to be replaced by the former if there is another release of version 2. Here is an example of the behavior of two layouts that are essentially the same except for this attribute; you can tell from this example which way the release you are using behaves: aûbûcûdûeûfûgûhûiûjûÉ14 17 lû(`a`b;`c`d;`e); llû(`f`g;`h`i;`j); show¡ `l `ll is¡ `layout; br{`l;0 412}; br{`ll;0} `ll has (`locksize;1; `reparent;0); `l has (`reparent;0); Ø`ys of¡ `l `ll < 539 < 539 `b`c`d `g`h`i has¡ <(`mapped;0); Ø`ys of¡ `l `ll < 370 < 539 free¡ `l`ll; The way a child behaves when a layout is resized depends in part on its display class. Call a child sticky if its class is action, button, scalar, label, slot, check, or radio and call all others non-sticky. If a layout has at least one row with only non-sticky children, then any row containing a sticky child retains its vertical size when the layout is resized. See how all the extra vertical space is allotted to the bottom row when you execute the next to last of these lines: `r is `radio Ý rû(`w`j`z;(1;0;0)); `ac is `action Ý acû(`a`c`t;(;;)); lû(`r`a;`ac`b;`c`d); show `l is `layout; br{`l;108 81} `l has (`yxs;Ä1.2«Ø`yxs of `l); free `l; The size of an object in a layout, which is normally affected by other objects in its row and column or by resizing the layout, can be controlled by setting the "H" and "W" attributes to 1. These settings prevent resizing of an object's height and width, respectively. There are even stronger resize restrictions, which apply to the entire row and column in which the object is positioned: setting the "h" and "w" attributes to 1 means retain the height of the row and the width of the column, respectively. The constraints can be seen after the layout enlargements in this example: lû3 2Ò`a`b`c`d`e`f; show `l is `layout; br{`l;162 121} szûØ`yxs of `l `a`b`c`d`e`f has¡ <(`resize;''); `c has (`W;1); `f has (`H;1); `l has (`yxs;Ä1.3«sz); `l has (`yxs;sz); `c has (`w;1); `f has (`h;1); `l has (`yxs;Ä1.3«sz); `l has (`yxs;sz); Setting these constraints to 0 does not remove them. They are actually just a way of inserting constraints in the "resize" attribute, whose value can be a character vector containing any of 'WHwhtblr' (we will deal with the last four in the next paragraph). Settings of resize are cumulative unless there is a period in the value being given for it or that value is empty. Resize settings of both '.' and '' remove all constraints. If the newly allotted space for the object within the layout is larger than the object, its position within that space is controlled by setting the "t", "b", "l", and "r" attributes to 1. They stand for top, bottom, left, and right and have the obvious effect. Now we remove all constraints and then constrain the heights and widths of two children, enlarge the layout, and move the constrained children within their spaces: `a`b`c`d`e`f has¡ <(`resize;''); `c`f has¡ <(`W`H;(1;1)); `l has (`yxs;Ä1.3«Øsz); `c has (`t;1); `c has (`l;1) `f has (`b;1) `f has (`r;1) `resize of `c < ltWH In real life, of course, you would set the constraints before enlarging the layout, so that the desired result would appear all at once, but when learning it is better to see the steps and not just the outcome. Before leaving this layout, let's look at the dominance of left and top -- the nullity of b and r in the presence of t and l -- and the change when a size constraint is removed: `c has (`resize;'br'); `c has (`resize;'WHb.r'); `c has (`resize;'.'); `f has (`resize;''); free `l; These attributes can be used in the initial display of a layout, when they apply to the relation between the natural size of the object and the space allotted to it in the layout. Consider this example: dû'and ',cû'still ',bû'another ',aû'array' `a`b`c`d is¡ `label; `a has (`resize;'tr'); `b has (`resize;'Wtr'); `d has (`b;1); jû10+kû10+mû10+nûÉ14 17 lû4 2Ò`a`j `b`k `c`m `d`n show `l is `layout; br{`l;0} The default label position, centered both ways, is shown by c. Why is b at the right but not a? Because the latter is as wide as its space in the layout, whereas b was not made wider than its natural size: we had set W for it, and so it had room to move. But then why did all the vertical movements succeed? Because for any object bound to the label class resize has the default value 'hH' and we simply added to that value. Therefore each label has its natural height and has room to move vertically in its space in the layout. 5e. Navigation and Interaction Attributes: acceptfocus focus freeze sensitive tabfrom tablist tabto First, a note about function keys, which were discussed in the Buttons tutorial. When Fj is pressed, if it was set on the object that has focus, then its function is executed. If it was not set on that object, then the object's container is checked and the function executed if the key was set on that object, and so on up to the shell, the top-level object. The "sensitive" attribute can be set to 0 to block all user interactions with an object and all its descendents. Try to select from, edit, or scroll j (with the pointer in l!) after executing the second statement, and try to select from, edit, or scroll any of the arrays after the third statement. The fourth statement shows that the display is still sensitive to changes made by program; only the user side is blocked, all viewer input being ignored: `j`k has¡ <(`selected;0 0); `j has (`sensitive;0); `l has (`sensitive;0); jûj+1 `l`j has¡ <(`sensitive;1); When the "freeze" attribute is 1, the display of the object and all its descendents will not be updated as a result of specifying values for it or setting attributes on it (although for the object itself some blanking may occur). When freeze is set to 0, the object is redrawn. You can use freeze to make several changes to an object without having its intermediate states flash on the screen. If you try editing, scrolling, and selecting after the fifth statement in this example, you will find all these actions work, although scrolling may just propagate the last line previously shown in the scrolled direction. Only the program side is blocked, the display of all changes by the program being deferred until freeze is set to 0: `a has (`resize;''); `b has (`freeze;1); `b has (`resize;''); `b has (`freeze;0); `l has (`freeze;1); `d has (`resize;''); nûn+1 `l has (`freeze;0); The remaining attributes in this set have to do with keyboard focus within a container. It can be given directly to any child with which the viewer can interact (not a label, e.g.) by setting the "focus" attribute for the child to any value. Move the pointer into l after executing this statement to see its effect: `m has `focus To move the focus from child to child, press Meta-Tab (Alt-Tab on IBM keyboards) or Shift-Meta-Tab (Shift-Alt-Tab on IBM keyboards) while the pointer is in the container. Objects of the various button and menu classes can be excluded from this traversal by setting the "acceptfocus" attribute to 0 or included by setting it to 1. Try traversing l before and after the statement excluding a from the traversal, but don't have the focus on a when you exclude it: free `a; aû(`j`k`m`n;(1;0;0;0)); `a has (`class;`radio; `resize;'.WH'; `mapped;1); lû4 2Ò`a`j `b`k `c`m `d`n `a has (`acceptfocus;0); The order of traversal is given in the "tablist" attribute and can be changed by giving a new value to tablist. All children are listed in the default value of tablist regardless of any ineligibility to accept focus, contingent (as for a) or absolute (as for the labels). The effective order of traversal is the order of the eligible children in tablist. When you specify tablist, you can omit any children you want and you can include children for which acceptfocus is 0 -- they will not actually be included in the traversal until you change the setting of acceptfocus. Try traversing the layout before and after the third statement below, setting acceptfocus for a to 1: `tablist of `l `l has (`tablist;`j`m`k`n`a); `a has (`acceptfocus;1); The tablist attribute (and the order of traversal) can be altered using the "tabfrom" and "tabto" attributes, whose values are the prior and following entries in tablist. These two attributes can also be queried, although if there are ineligible children listed in tablist the values of tabfrom and tabto may not be helpful for some children; `tabfrom of `a `a has (`tabfrom;`m); `j has (`tabto;`k); `tablist of `l < `.j `.k `.m `.a `.n free `l; Here is an example of a layout within a layout. Start by preparing the first two rows of the outer layout, the second row being itself a layout. A width is specified for the action buttons to make them a little more spacious: chcû(`Off`On;(1;0)) `chc has (`class;`choice;`title;'Feed is'); hmnû(`Font;,<(`font1`font2`font3;(;;))) `hmn is `hmenu; actû(`Save`Sort`Add`Print`Fields`Help`Drop`Quit;(;;;;;;;)) `act has(`class;`action; `title;''; `geometry;8; `realize;1; `xs;670); lû1 2Ò`hmn`act `l has (`class;`layout; `title;'';`h;1); Now define a table and place it and the previous material in a layout: caû1 9Ò'912827L2 '; cbû1Ò7.625; ccû1Ò20221115; cdû1Ò123.0314; ceû1Ò5.933; cfû1Ò12.81; cgû1Ò16.23; tblû`ca`cb`cc`cd`ce`cf`cg `tbl has (`class;`table; `title;''; `cols;7); `ca`cb`cc`cd has¡ (<`title),¡ <@0 `Cusip`Coupon`Maturity`Price; `ce`cf`cg has¡ (<`title),¡<¡(`Yield;'M Dur';'$ Dur'); `cb`cc`cd`ce`cf`cg has¡(<<`out),¡<¡(6.3;`mdy2;`328th;6.3;6.2;6.2); `ca`cb`cc`cd`ce`cf`cg has¡(<<`space),¡<¡(9;7;10;7;7;7;7); layû(`chc`l`tbl); `lay is `layout; `lay has (`shelltitle;'qs'; `title;''; `realize;1; `ys;300); show `lay; br{`lay;0} free `lay Here is another example of a layout, with color attributes used to accentuate its various parts: aû19930000+401 505 609 714 818 922 1027 1201 dûbû2+.75 .6 .7 .6 .75 .9 .7 .75 cû7+1.073 .904 1.123 .904 .754 .923 .804 .474 eûfû8Ò0 tû`a`b`c`d`e`f show `t is `table; br{`t;72 188} Showing t is premature on several counts, as is the next statement, but doing things in this order allows their effects to be shown better. `t has (`cols;4; `rows;8); `a has (`out;`mdy4; `space;10); `b`c`d has¡ <(`out;8.3); `t has (`cols;4); `a`b`c`d has¡ (<`title),¡`Auction`AucRate`YCR_R`ARR_R; `t has (`title;'MTA 5.50 2013'); `t has (`titlefg;`white; `fg;`white; `bg;`black; `scrollbg;`grey); actû(`tg`ex`pr;(;;)) `act has (`class;`action; `geometry;3; `title;''; `bg;`white); `act has (`label;('Toggle Daycount';'Exit';'Print')); lblû'ActAct rates looking forward' `lbl has (`class;`label; `fg;`white; `bg;`black); lû`t`act`lbl `l has (`class;`layout; `shelltitle;'RATE HISTORY'; `title;''); show `l; br{`l;0} _ex¡ Øfree `l; 6. The Hpane and Vpane Display Classes The hpane and vpane display classes are container classes that are like layouts except that they have movable dividers, or sashes, between their children. The viewer can control the proportion of the layout that children occupy simply by moving the dividers. Various attributes that constrain the arrangement of children, such as position and build, are disregarded. An hpane object has vertical dividers and its children should be arranged horizontally. A vpane object has horizontal dividers and its children should be arranged vertically. To move a divider, simply place the mouse pointer on it, press and hold the left mouse button, and then slide the divider left or right, or up or down. The old and new divider lines are shown continuously and the new arrangement is shown when you release the mouse button. A small button is provided on one end of each divider as a convenient place to locate the pointer. In the following vpane example, a viewer can adjust the number of headlines shown, with a corresponding adjustment in the space available for any selected story. We use some data from aux_vars.+ that there is no point in cluttering this tutorial with. The selected headline appears as the title of the story section: _load{'/usr/local/aplus-fsf-4.22/doc/tutorials/s.tutorials/aux_vars.+'}; `ld_vph has (`class;`view; `title;''; `bg;`white; `rows;10; `cols;74); tû76Ù' BT 10/01 13:14 Nortek Filing -2- Proceeds to Redeem Debt >NTK' `ld_vps has (`class;`view; `title;t; `bg;`white; `rows;9; `cols;76); vpû`ld_vph `ld_vps `vp has (`class;`vpane; `title;''; `shelltitle;'DJ NEWS -- MS FID'); show `vp; br{`vp;0} Move the sash up and down. Notice that scrollbars appear and disappear for the two sections as needed and that you can eliminate either section from view completely if you want. _ex¡ `t,Øfree `vp; In the following hpane example, a viewer can adjust the number of fields shown in two tables. The first four lines set up the table fields, the next four the tables, the next two the tableFields, and the last three the hpane: csûpsû10Ò0 `cs`ps has¡ <(`title;'strikes'; `out;'f7.2'); CBIDûCASKûCLSTûCBvolûCAvolûCLvolûCLDeltaû10Ò¢999999999 PBIDûPASKûPLSTûPBvolûPAvolûPLvolûPLDeltaû10Ò¢999999999 tcû`cs`CBID`CASK`CLST`CBvol`CAvol`CLvol`CLDelta tpû`ps`PBID`PASK`PLST`PBvol`PAvol`PLvol`PLDelta `tc has (`class;`table; `title;'Calls'; `cols;5; `rows;10); `tp has (`class;`table; `title;'Puts'; `cols;5); `cs`CBID`CASK`CLST`CBvol`CAvol`CLvol`CLDelta has¡<(`blank;' '; `space;7); `ps`PBID`PASK`PLST`PBvol`PAvol`PLvol`PLDelta has¡<(`blank;' '; `space;7); hpû1 2Ò`tc`tp `hp has (`class;`hpane; `shelltitle;'Ivy'; `title;''); show `hp; br{`hp;0} Try moving the sash from side to side. You can show just one table, two columns of one and all of the other, or other combinations. _ex¡ Øfree `hp; The dividers of an hpane layout always extend from the top to the bottom of the layout, so care must be taken when using hpane layouts with more than one row. Consider (a;b)û100+¡?¡2Ò<5 3 Ò100; cû100+?5 4Ò100; hû(`a`b;`c); show `h is `hpane; br{`h;0} The divider between objects a and b cuts through object c. Similarly, care must be taken when using vpane layouts with more than one column: _ex¡ Øfree `h; (a;b)û100+¡?¡2Ò<9 2 Ò100; cû100+?12 2Ò100; vû(`a`c;`b`c); show `v is `vpane; br{`v;0} If several objects line up on a divider boundary, then movement of the divider controls the display sizes of these objects. Thus movement of a divider can control the display sizes of an entire row or column of objects. Moreover, there can be several dividers. Scrutinize this example and move its dividers: _ex¡ Øfree `v; (a;b;c;d;e;f;g)û100+¡?¡7Ò<5 9Ò100; hû(`a`b`c;`d`e`f;`g) show `h is `hpane; br{`h;0} Where do dividers appear? In section 5c, on the arrangement of objects in a layout, we spoke of virtual rows and columns and the at attribute, whose value is defined in terms of them. Dividers appear between each adjacent pair of virtual columns for an hpane and of virtual rows for a vpane. Respecify h to be an unpleasant hpane whose arrangement of objects requires that they all span virtual columns: hû(`a`b`c;`d`e;`g); free `f; >Ø`at of¡ `a`d`g 0 0 1 2 1 0 1 3 2 0 1 6 Notice that there is no object boundary between the first and second virtual columns or between the fifth and sixth, although there are dividers there. free `h; Clearly, if we want dividers for each of the first and second rows, this is not the way to do it. The dividers need to be limited in length. The right way for this particular arrangement is to handle the virtual rows separately, to put two hpanes and g inside a layout: h1û1 3Ò`a`b`c; `h1 is `hpane; h2û1 2Ò`d`e; `h2 is `hpane; lû`h1`h2`g; `l is `layout; show `l; br{`l;0} free `l; Likewise, dividers may need to be limited in number, and a way to do that is to put layouts inside hpanes. Suppose we want to allow the viewer to divide the available space between two arrays and also to switch the variable that appears in the lower array, with the same columns shown as for the variable previously shown. We want a vpane containing array, radio, array. If we specified the vpane in that simple manner, then there would be two dividers and they would both have to be moved to take space from one array and give it to the other (while the radio would be alternately stretched and squashed). The solution is obvious: put the radio and the array it refers to inside a layout: eû10«dû10«cû10«bû10«aûÉ10 8 rû(`b`c`d`e;(1;0;0;0)); `r is `radio; lû`r`b; `l is `layout; vû`a`l; `v is `vpane; cbf{s;d;i;p;c;v}:{`v has (`freeze;1); poû1#.l; fcû`firstcol of po; .lû`r,p; free po; show p; p has (`firstcol;fc); `v has (`freeze;0);} `r has (`set;cbf; `geometry;4); `v`l`r`b`c`d`e has¡ <(`title;''); show `v; `v has (`xs;291); br{`v;0} Now move the divider, use the scroll bars, and press the radio buttons. There is no direct way for a program to determine exactly where a user has positioned a divider in an hpane or vpane layout. Sometimes there are indirect ways to approximate the position, such as checking the values of the rows and cols attributes of an object to determine how many rows and columns are currently shown. Execute these two statements before and after moving the divider: >`rows `ys of `a >`rows `ys of 1#l _ex¡ `cbf`r`b`c`d`e`f`g, Øfree `v;