Copyright (C) 1994, Digital Equipment Corp.
Created by Marc Najork
MODULE GroupGO EXPORTS GroupGO, GroupGOPrivate, GroupGOProxy;
IMPORT AnimServer, GO, GOPrivate, GraphicsBase, GraphicsBasePrivate, Prop;
REVEAL
T = Private BRANDED OBJECT
OVERRIDES
init := Init; (* GroupGO.Public *)
add := Add; (* GroupGO.Public *)
remove := Remove; (* GroupGO.Public *)
flush := Flush; (* GroupGO.Public *)
content := Content; (* GroupGO.Public *)
findName := FindName; (* GO.Public *)
draw := Draw; (* GO.Private *)
needsTransparency := NeedsTransparency; (* GO.Private *)
adjust := Adjust; (* GO.Private *)
damageIfDependent := DamageIfDependent; (* GO.Private *)
END;
PROCEDURE Init (self : T; initSize : INTEGER) : T =
BEGIN
(*** No protection needed ***)
EVAL GO.T.init (self);
self.children := NEW (REF ARRAY OF GO.T, initSize); (* grow as needed *)
self.last := -1;
self.damaged := FALSE; (* groups are not damaged at creation *)
IF MkProxyT # NIL THEN
MkProxyT (self);
END;
RETURN self;
END Init;
PROCEDURE New (initSize : INTEGER) : T =
BEGIN
RETURN NEW (T).init (initSize);
END New;
PROCEDURE Add (self : T; o : GO.T) =
BEGIN
(*** Must be protected from interference with the animation server ***)
LOCK AnimServer.internalLock DO
self.damaged := TRUE;
INC (self.last);
IF self.last > LAST (self.children^) THEN
WITH n = NUMBER (self.children^),
tmp = NEW (REF ARRAY OF GO.T, 2 * n) DO
SUBARRAY (tmp^, 0, n) := self.children^;
self.children := tmp;
END;
END;
self.children[self.last] := o;
END;
END Add;
PROCEDURE Remove(self : T; o : GO.T) RAISES {BadElement} =
BEGIN
(*** Must be protected from interference with the animation server ***)
LOCK AnimServer.internalLock DO
self.damaged := TRUE;
WITH B = self.children^ DO
FOR i := 0 TO self.last DO
IF B[i] = o THEN
B[i] := B[self.last];
B[self.last] := NIL;
DEC (self.last);
RETURN;
END;
END;
END;
RAISE BadElement;
END;
END Remove;
PROCEDURE Flush (self : T) =
BEGIN
(*** Must be protected from interference with the animation server ***)
LOCK AnimServer.internalLock DO
self.damaged := TRUE;
FOR i := 0 TO self.last DO
self.children[i] := NIL;
END;
self.last := -1;
END;
END Flush;
PROCEDURE Content (self : T) : REF ARRAY OF GO.T =
BEGIN
WITH res = NEW (REF ARRAY OF GO.T, self.last + 1) DO
res^ := SUBARRAY (self.children^, 0, self.last + 1);
RETURN res;
END;
END Content;
PROCEDURE FindName (self : T; name : TEXT) : GO.T =
BEGIN
(* No interference with the animation server. Possible interference with
other client threads; client code has to provide adequate protection. *)
IF GO.T.findName (self, name) # NIL THEN
RETURN self;
ELSE
FOR i := 0 TO self.last DO
WITH go = self.children[i].findName (name) DO
IF go # NIL THEN
RETURN go;
END;
END;
END;
END;
RETURN NIL;
END FindName;
***************************************************************************
Private Methods:
These procedures are called only from the animation server thread.
Their locking level is {AnimServer.externalLock,AnimServer.internalLock}
***************************************************************************
PROCEDURE Draw (self : T; state : GraphicsBase.T) =
BEGIN
state.push (self);
FOR i := 0 TO self.last DO
self.children[i].draw (state);
END;
(* Indicate that damages have been repaired *)
self.damaged := FALSE;
state.pop (self);
END Draw;
PROCEDURE NeedsTransparency (self : T; t : REAL) : BOOLEAN =
BEGIN
IF self.trans # FIRST(REAL) THEN
t := self.trans;
END;
FOR i := 0 TO self.last DO
IF self.children[i].needsTransparency (t) THEN
RETURN TRUE;
END;
END;
RETURN FALSE;
END NeedsTransparency;
PROCEDURE Adjust (self : T; time : LONGREAL) =
BEGIN
(*** adjust properties of self ***)
GO.T.adjust (self, time);
FOR i := 0 TO self.last DO
self.children[i].adjust (time);
IF self.children[i].damaged THEN
self.damaged := TRUE;
END;
END;
END Adjust;
PROCEDURE DamageIfDependent (self : T; pn : Prop.Name) =
BEGIN
FOR i := 0 TO self.last DO
self.children[i].damageIfDependent (pn);
IF self.children[i].damaged THEN
self.damaged := TRUE;
END;
END;
END DamageIfDependent;
BEGIN
END GroupGO.