<*PRAGMA LL*>An
HVSplit.T
is a parent window that splits its screen into a
row or column of child windows, depending on the {\it axis} of
the split.
If the axis is horizontal, Split.Succ
enumerates the children
from west to east; if the axis is vertical, it enumerates them
from north to south.
An HVSplit
can be {\it adjustable} or {\it unadjustable}, a
property that affects the way its space is divided between its children.
The {\it size} of a child is the extent of its domain in the axis of split, the {\it cross-size} is its extent in the other axis. For example, for a vertical split, a child's size is its height and its cross-size is its width.
The children of an HVSplit
all have the same cross-size as the
parent. To determine the sizes of the children, the HVSplit
begins
by computing the range of desirable sizes and the preferred size
for each child by calling its shape method, passing the method the
cross-size, so that, for example, the height of a child of a vertical
split can depend on its width. At this point there are several cases.
If the sum of the minimum sizes of the children is greater than the size of the parent, then the split is said to be {\it overfull}. In this case the children are considered in order and given their minimum sizes, as long as there is room. The first child that doesn't fit is given all the space that's left, and the remaining children are given size zero.
If the split is not overfull, then the children are stretched
according to the TeX model of boxes and glue. The details depend
on whether the split is adjustable or unadjustable. For an
adjustable split, each child's {\it stretchability} is its maximum
desirable size minus its current size, and its {\it shrinkability}
is its current size minus its minimum desirable size. If the size
of the parent is increased by some amount X
, then the sizes of
the children are increased by amounts that total to X
and are
proportional to the children's stretchabilities. Similarly, if the
size of the parent is decreased by some amount X
, then the sizes
of the children are decreased by amounts that total to X
and are
proportional to the children's shrinkabilities.
For a non-adjustable split, all the children's sizes are first set to their preferred sizes, and then they are stretched or shrunk the same as an adjustable split. Thus for a non-adjustable split each redistribution of space depends only on the children's shape methods, not on their current sizes.
A non-adjustable split is best if the layout can be controlled purely
by stretchability and shrinkability. If the layout is also changed
under user or program control, an adjustable split is required. For
example, in a column of editable text windows, you should make the
vertical split adjustable, since if the user makes one window big,
and then the parent changes size slightly, you do not want the big
window child to snap back to being small. On the other hand if you
are using a horizontal split to center a ButtonVBT
between two
stretchy TextureVBTs
, you should make it unadjustable, since in
this case you always want to compute the division of space from the
children's original shapes.
If the sum of the maximum sizes of the children is less than the size of the parent, the split is said to be {\it underfull}. There are no special rules for the underfull case: the TeX stretching algorithm is used without change. This produces a state in which the children are stretched larger than their maximum sizes.
A split is {\it infeasible} if it is overfull or underfull, and {\it feasible} otherwise.
The shape of an HVSplit
is computed as follows: its maximum,
minimum, and preferred sizes are obtained by adding up the
corresponding values of its children. The cross-size range is the
intersection of the cross-size ranges of its children (if this
intersection is empty, the children's maximum cross-sizes are
increased until the intersection is non-empty). The preferred
cross-size of v
is the maximum of the preferred cross-sizes
of its children, projected into v
's cross-size range.
INTERFACEThe callHVSplit ; IMPORT VBT, Split, Axis, Interval; TYPE T <: Public; Private <: Split.T; Public = Private OBJECT METHODS <* LL.sup <= VBT.mu *> init(hv: Axis.T; saveBits := FALSE; parlim := -1; adjustable := TRUE): T END;
v.init(...)
initializes v
as an HVSplit
with axis
hv
and no children.
If saveBits
is TRUE
, the implementation will try to save the
children's old bits when reshaping; if the children don't use them
anyway, it is faster to let saveBits
default to FALSE
. The value of
parlim
is the minimum area of a child for which a separate thread
will be forked to reshape
or repaint
; if it is -1
, it is set
to an appropriate default (see the VBTTuning
interface).
PROCEDURE New( hv: Axis.T; saveBits := FALSE; parlim := -1; adjustable := TRUE): T; <* LL.sup <= VBT.mu *>
New(...)
is equivalent toNEW(T).init(...)
.
PROCEDURE AxisOf(v: T): Axis.T; <* LL.sup = VBT.mu *>
Return the axis of v
.
\subsubsection{Inserting children}
See the Split
interface to insert and reorder children.
PROCEDURE Cons( hv: Axis.T; ch0, ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9: VBT.T := NIL; saveBits := FALSE; parlim := -1; adjustable := TRUE): T; <* LL.sup = VBT.mu *> (* Create an "HVSplit" with axis "hv" and children "ch0", "ch1", .... *)
Cons
is equivalent to the following:
result := New(hv, saveBits, parlim, adjustable); Split.AddChild(result, ch0, ch1, ..., ch9); RETURN result
PROCEDURE ConsArray( hv: Axis.T; READONLY ch: ARRAY OF VBT.T; saveBits := FALSE; parlim := -1; adjustable := TRUE): T; <* LL.sup = VBT.mu *>
Create anHVSplit
with axishv
and childrench[0]
,ch[1]
, ....
ConsArray
ignores any NILs
in the array ch
. It is equivalent to:
VAR result := New(hv, saveBits, parlim, adjustable); BEGIN Split.AddChildArray(result, ch); RETURN result END
\subsubsection{Adjusting the division of space}
The {\it division point after a child} is the sum of the sizes of all children up to and including the child.
PROCEDURE Adjust(v: T; ch: VBT.T; totsz: INTEGER) RAISES {Split.NotAChild}; <* LL.sup = VBT.mu *>
Change the sizes of the children ofv
so that the division point afterch
is as close tototsz
as possible, and markv
for redisplay.
Adjust
respects the size constraints on the children, and resizes
children near the division point in preference to children far from
the division point. For example, a sufficiently small adjustment
will be made by resizing only ch
and its successor. An adjustment
large enough to make one of these children reach its max or min size
will also resize the neighbor of that child, and so forth.
Adjust
is a no-op if the split is infeasible or non-adjustable.
PROCEDURE FeasibleRange(v: T; ch: VBT.T): Interval.T RAISES {Split.NotAChild}; <* LL.sup = VBT.mu *>
Return the interval of feasible positions for the division point
after ch
.
PROCEDURE AvailSize(v: T): CARDINAL; <* LL.sup = VBT.mu *>
Return the largest size of a child that can be inserted intov
without makingv
infeasible.
If the split is infeasible,
AvailSize
returns 0 and FeasibleRange
returns the empty interval. Both procedures assume the
total size available is the total of all child sizes.
END HVSplit.