Copyright (C) 1992, Digital Equipment Corporation
All rights reserved.
See the file COPYRIGHT for a full description.
by Steve Glassman and Stephen Harrison
Last modified on Mon Jul 20 23:41:21 1992 by steveg
<*PRAGMA LL*>
Lists, Queues, Stacks and Buffers. Lumped together because they are all
linear displays of things.
INTERFACE LinearArray;
IMPORT
Axis, MG, MGV, PaintOp;
TYPE
T <: TPublic;
TPublic = MG.Group OBJECT
<* LL = v.mu *>
graphic : MG.T;
next, prev : T;
linkToNext, linkToPrev: LinkerRec;
METHODS
<* LL < v.mu *>
init (v: V; graphic: MG.T): T;
(* displays self using "graphic", sets the linker to the
default linker (if it is NIL), centers the graphic around
the origin, sets Pos(self) to the origin, and sets
visibility to 0.0 (invisible). *)
<* LL = v.mu *>
setNextPrev(v: V; np: NP; t: T);
setNextPrevLink(v: V; np: NP; READONLY link: LinkerRec);
END;
TYPE
NP = {Next, Prev, Label};
HT = {Head, Tail};
TYPE
V <: VPublic;
VPublic =
MGV.V OBJECT
<* LL = self.mu *>
dx, dy := 5.0;
(* separation distance between elements *)
axis := Axis.T.Hor;
(* axis of elements *)
alignment := Alignment.AboveLeft;
(* side of elements to locate elements that are "align"ed. *)
linker: Linker := NIL;
(* self.linker.new(from, to) returns a graphical element that acts as
a link connecting "from" and "t". The link ends should be
individually controllable so "from" and "to" can move separately.
If linker = NIL, linkerDefault is used and returns a MG.Line with
MG.LineEnds at "from" and "to". The visibility of "to" controls
the visibility of the default link. *)
(* internal state fields *)
head, tail : T := NIL;
headLabel, tailLabel: T := NIL;
labelLinks := FALSE;
aligned: T := NIL;
(* list of aligned elements, so they are displayed *)
cntElems := 0;
(* count of elements in the linear array, maintained by insert and
delete *)
width, height: REAL;
(* size of elements *)
METHODS
<* LL < self.mu *>
init (width, height: REAL): V;
(* dimensions of a box or label in the linear array *)
<* LL = self.mu *>
setLabel (ht: HT; graphic: MG.T);
(* show "graphic" at the head/tail of the "list", include a link
"self.labelLinks" is TRUE *)
clear ();
(* reset to have no elements *)
align (t, dest: T);
(* Creates and animation moving "t" to be aligned with "dest". *)
insert (t, prev: T);
(* Creates and animation to insert "t" after "prev". If "prev" = NIL
then insert as new head. Handles next, prev, and links. Updates
head and tail as necessary *)
delete (t: T);
(* Creates and animation to delete "t" from "self"'s list. Handles
next, prev, and links. Updates head and tail as necessary *)
END;
A vbt displaying a linear array of elements.
<* LL < v.mu *>
PROCEDURE Align (v: V; t, dest: T);
PROCEDURE Clear (v: V);
PROCEDURE Delete (v: V; t: T);
PROCEDURE Insert (v: V; t, prev: T);
PROCEDURE Link (v: V; from, to: T);
The three above procedures handle locking, new shapes, animation, and
redisplay for calls of the align, insert and delete methods
TYPE
Alignment = {None, AboveLeft, AboveRight, BelowLeft, BelowRight};
(*| Position of "align"ed elements relative to the destination
element. Head/Tail pointers (if any) are aligned on the opposite
side (or "BelowRight" is used if "None" was specified) *)
TYPE
LinkerRec = RECORD from, to: MG.T; fromT, toT: T END;
Linker =
OBJECT METHODS new (v: V; from, to: T; type: NP): LinkerRec END;
v.linker.new returns a pair of MG.T elements controlling a graphical
link between from
and to
. If either from
or to
is NIL
then a very short
link should be produced with both ends
controlled by the non-NIL end. type
maybe be used to distinguish
next, prev and label links.
VAR linkerDefault: Linker;
If v.linker = NIL, linkerDefault is used and returns a MG.Line
with MG.LineEnds at from
and to
. The visibility of to
controls the visibility of the default link.
TYPE
List <: V;
TYPE
DoublyLinkedList <: DoublyLinkedListPublic;
DoublyLinkedListPublic = List OBJECT
nextLinkColor, prevLinkColor: PaintOp.ColorScheme;
END;
(* Like a List except that linkToPrev is maintained and displayed *)
TYPE
QSB = V OBJECT
METHODS
<* LL = self.mu *>
push (t: T);
pop (): T;
END;
Queue <: QSB;
(* A FIFO - self.push pushes at the tail and self.pop pops from the head *)
Stack <: QSB;
(* A LIFO - self.push pushes at the head and self.pop pops from the head *)
TYPE
Buffer <: BufferPublic;
BufferPublic =
QSB OBJECT
<* LL = self.mu *>
pushSide, popSide: HT;
(* pushSide = HT.Tail, popSide = HT.Head => Queue behavior pushSide =
HT.Tail, popSide = HT.Tail => Stack behavior *)
slots : REF ARRAY OF MG.T := NIL;
headIndex, tailIndex: INTEGER := 0;
emptyColor: PaintOp.ColorScheme := NIL;
(* emptyColor rectangle will fill empty slots in the buffer. if no
color is given, then the empty slots will be invisible *)
METHODS
<* LL < self.mu *>
init (width, height: REAL; size: CARDINAL; pushSide, popSide: HT):
Buffer;
<* LL = self.mu *>
grow (newSize: CARDINAL);
END;
<* LL < v.mu *>
PROCEDURE Push (v: QSB; t: T);
PROCEDURE Pop (v: QSB);
PROCEDURE GrowBuffer(v: Buffer; newSize: INTEGER);
END LinearArray.