<*PRAGMA LL*>A
ProperSplit.T
is a type of VBT.Split
that contains a
circularly-linked list of its children. All of Trestle's built-in
splits that are not filters are subclasses of ProperSplit
.
INTERFACEIfProperSplit ; IMPORT VBT, Split; TYPE T <: Public; Public = VBT.Split OBJECT <* LL >= {SELF, VBT.mu} *> lastChild: Child := NIL END; Child = OBJECT <* LL >= {SELF.ch.parent, VBT.mu} *> pred, succ: Child := NIL; ch: VBT.T END;
ch
is a child of a ProperSplit.T
, then ch.upRef
must be of
type ProperSplit.Child
, and ch.upRef.ch
must equal ch
. The
succ
and pred
links represent a doubly-linked list of the
children. The succ
links are circular; the pred
links are
linear. The parent's lastChild
field is is NIL
if there are
no children; otherwise it points to the last child in succ
order.
The locking level comments imply that to write any of the links,
a thread must have both VBT.mu
and the parent locked.
If v
is a T
, the call v.beChild(ch)
sets ch.upref
to NEW(Child)
if it is NIL
. In any case it sets
ch.upref.ch := ch
and calls VBT.Split.beChild(v, ch)
.
A T
provides replace, insert, and move methods that preserve the linked
list structure of children, but allocates no screen space or event
dispatching to the children. These methods use the procedures below;
the replace method uses the default insert method to add the new child,
which may be inappropriate for some class layout policies.
The following procedures are useful for implementing subtypes
of ProperSplit.T
:
PROCEDURE Insert(v: T; pred: Child; newch: VBT.T); <* LL >= {VBT.mu, v, newch} *>
Insertnewch
as a new child afterpred
, and markv
for redisplay.
The child
newch
must be detached and of the appropriate
screentype. The argument pred
can be NIL
to indicate
insertion at the head of the list. Insert
calls the beChild
method of newCh
.
PROCEDURE PreInsert(v: T; pred, ch: VBT.T): Child RAISES {Split.NotAChild}; <* LL.sup = VBT.mu *>
Rescreench
to havev
's screentype (if necessary), cause a checked runtime error ifch
is attached, raiseSplit.NotAChild
ifpred
is non-nil and not a child ofv
, and finally returnpred.upRef
, orNIL
ifpred
isNIL
.
PROCEDURE Move(v: T; pred, ch: Child); <* LL >= {VBT.mu, v} *>
Movech
in the list of children so that it followspred
and markv
for redisplay.
PROCEDURE Delete(v: T; ch: Child); <* LL >= {VBT.mu} AND LL.sup < v *>
Removech
from the list of children, detachch.ch
, and markv
for redisplay.
END ProperSplit.