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
     scrs.SCREEN-34 12
     br{w;m}:{w has (`yx;scr-m+`yxs of w);}
     a12 2
     w1`a1
     show `w1 is `window  show `a1; br{`w1;0}

Try the various scrollbars after each of these statements:

     a150 2
     a1a250 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(,`char97+(426)773500;`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_010 4'blah'
     var_11+10
     var_2150+.01?10100000
     var_3:var_2var_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:

     albl1000+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:

     j100+200
     t1j(,@0)100
     t2j(,@0)975+(1000000-j*2)*.5
     t31 220 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:

     p14 2 90 10  90 70  0 70  0 10
     p3(4 230 10)+ p2(4 230 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:

     abcden3
     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:

     a1a2a3a4a5a6a7a8a9a1010 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:

     l3 2`a1`a2 `a3`a4 `a5`a6; `l has `naturalsize; br{`l;0}
     l4 3`a1`a1`a2 `a1`a1`a3 ``a4` `a5``a6; `l has `naturalsize; br{`l;0}
     {l4 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);
      l2 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
     l2 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;
     l3 2 `a1`a2`a3`a4`a5`a6;  ll3 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:

     abcdefghij14 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:

     l3 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.3sz);
     `l has (`yxs;sz);
     `c has (`w;1);
     `f has (`h;1);
     `l has (`yxs;1.3sz);
     `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.3sz);
     `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);
     j10+k10+m10+n14 17
     l4 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);
     jj+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;'');
     nn+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);
     l4 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);
     l1 2`hmn`act
     `l has (`class;`layout; `title;'';`h;1);

Now define a table and place it and the previous material in a layout:

     ca1 9'912827L2 '; cb17.625; cc120221115; cd1123.0314;
     ce15.933; cf112.81; cg116.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:

     a19930000+401 505 609 714 818 922 1027 1201
     db2+.75 .6 .7 .6 .75 .9 .7 .75
     c7+1.073 .904 1.123 .904 .754 .923 .804 .474
     ef80
     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.18/doc/tutorials/s.tutorials/aux_vars.+'};
     `ld_vph has (`class;`view; `title;''; `bg;`white; `rows;10; `cols;74);
     t76' 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:

     csps100
     `cs`ps has <(`title;'strikes'; `out;'f7.2');
     CBIDCASKCLSTCBvolCAvolCLvolCLDelta10Ң999999999
     PBIDPASKPLSTPBvolPAvolPLvolPLDelta10Ң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);
     hp1 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; c100+?5 4100;
     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; c100+?12 2100;
     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 9100;
     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:

     h11 3`a`b`c; `h1 is `hpane;
     h21 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:

     e10d10c10b10a10 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);
         po1#.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;