DIRECTORY
Imager USING [Context, Rectangle, VEC],
IO USING [STREAM],
Rope USING [ROPE],
TIPUser USING [TIPTable],
ViewerClasses USING [Viewer, ViewerRec];
Types
Context: TYPE ~ Imager.Context;
Rectangle: TYPE ~ Imager.Rectangle;
ROPE: TYPE ~ Rope.ROPE;
VEC: TYPE ~ Imager.VEC;
Viewer: TYPE ~ ViewerClasses.Viewer;
ViewerRec: TYPE ~ ViewerClasses.ViewerRec;
TRC:
TYPE ~
REF TRCRep;
TRCRep:
TYPE ~
RECORD [
class: Class,
instance: REF,
listener: LIST OF Listener ← NIL
];
Class:
TYPE ~
REF ClassRep;
ClassRep:
TYPE ~
RECORD [
flavor: ATOM,
fcn: Fcn ←,
blockFcn: BlockFcn ← NIL,
copy: CopyProc ← NIL,
pickle: PickleProc ← NIL, --N.B. A class should not implement a PickleProc unless the class is registered!!! There is no way to Depickle an unregistered class
depickle: DepickleProc ← NIL,
notify: NotifyProc ← NIL,
tipTable: TIPUser.TIPTable ← NIL,
background: BackgroundProc ← NIL,
control: BuildControlViewerProc ← NIL,
classData: REF ← NIL --For certain types of subclassing
];
Fcn: TYPE ~ PROC [trc: TRC, a: REAL] RETURNS [b: REAL];
BlockFcn: TYPE ~ UNSAFE PROC [trc: TRC, from, to: UnsafeTable, count: NAT];
CopyProc: TYPE ~ PROC [trc: TRC] RETURNS [new: TRC];
PickleProc:
TYPE ~
PROC [trc:
TRC, stream:
IO.
STREAM, indentation:
ROPE ←
NIL];
With a PickleProc/DepickleProc pair, a class should be able to save and restore the instantial information for a TRC. Preferably, the pickled information should be human-readable, and a DepickleProc should be as free-form as possible. A DepickleProc also MUST know when it has finished reading its information, and not consume extra information from the STREAM.
indentation can be used by recursive classes to provide proper indentation...
DepickleProc: TYPE ~ PROC [class: Class, stream: IO.STREAM] RETURNS [trc: TRC];
NotifyProc: TYPE ~ PROC [viewer: Viewer, trc: TRC, input: LIST OF REF ANY];
BackgroundProc:
TYPE ~
PROC [trc:
TRC, context: Context, rectangle: Rectangle, whatChanged:
REF ←
NIL];
Class Implementor Notes:
This proc will should be called by the TrcViewers package to paint a $Trc viewer. Note that strokeWidth will be set to some "reasonable" value, though a Background may reset this if desired.
Also note that if whatChanged is not NIL, then it is what ViewerOps.PaintViewer received when called. The $Trc viewer will not do anything to the context other than setup (i.e. it will not actually draw anything), but just pass the call on to the BackgroundProc, thus allowing a NotifyProc to call ViewerOps.PaintViewer and allow a BackgroundProc to paint something simple.
BuildControlViewerProc:
TYPE ~
PROC [trc:
TRC, info: ViewerRec, paint:
BOOL]
RETURNS [viewer: Viewer];
Note that if viewer.openHeight contains a non-zero value, it can be considered as a hint from the class implementor as to how big the viewer should be.
Note also that the BuildControlViewerProc should be able to instantiate a trc where trc.instance~NIL. This is the only means that general trc utilities (which do not know themselves how to control a general trc) have to create a new trc without knowing about the specific trc classes.
Use FetchProp to profile defaults for setting up the control viewer. For example, there might be a few class which might wish to know of a $AISFileName which might, by convention have a ROPE value. Etc. See TrcDoc for current conventions.
Listener: TYPE ~ RECORD [proc: ListenerProc, listenerData: REF];
ListenerProc: TYPE ~ PROC [trc: TRC, listenerData: REF];
Table:
TYPE ~
REF TableRep;
TableRep: TYPE ~ RECORD [SEQUENCE n: NAT OF REAL];
UnsafeTable: TYPE ~ LONG POINTER TO RECORD [SEQUENCE COMPUTED NAT OF REAL];
Inline versions of class applications
ApplyFcn: Fcn ~
INLINE {
RETURN [trc.class.fcn[trc, a]];
};
ApplyBlockFcn: BlockFcn ~
UNCHECKED
INLINE {
trc.class.blockFcn[trc, from, to, count];
};
Copy: CopyProc ~
INLINE {
RETURN [trc.class.copy[trc]]
};
Pickle: PickleProc ~
INLINE {
trc.class.pickle[trc, stream, indentation];
};
Depickle: DepickleProc ~
INLINE {
RETURN [class.depickle[class, stream]];
};
PaintBackground: BackgroundProc ~
INLINE {
trc.class.background[trc, context, rectangle, whatChanged];
};
BuildControlViewer: BuildControlViewerProc ~
INLINE {
RETURN [trc.class.control[trc, info, paint]];
};
Actions on TRCs and Classes
RegisterClass:
PROC [class: Class];
Registers classes for public use.
ClassFromFlavor:
PROC [flavor:
ATOM]
RETURNS [class: Class];
Returns a class from the public registry.
InstallListener:
PROC [trc:
TRC, listener: Listener]
RETURNS [registration:
REF];
Once installed, the listener will be called when someone calls NotifyListeners on this TRC.
DeinstallListener:
PROC [registration:
REF];
Removes the listener.
NotifyListeners:
PROC [trc:
TRC, fork:
BOOL ←
FALSE];
Warns anyone who has tapped in that this trc has been changed.
If fork~TRUE, then separate processes will be forked, which may eliminated monitor lock-up problems.
EnumerateRegisteredClasses:
PROC [proc: ClassEnumProc];
ClassEnumProc: TYPE ~ PROC [class: Class] RETURNS [quit: BOOL ← FALSE];
Enumerates the registered classes in no particular order.
NotifyNewRegistrations:
PROC [proc:
PROC [clientData:
REF], clientData:
REF ←
NIL, firstTime:
BOOL ←
TRUE];
proc will be called when new packages are registered.
If firstTime~TRUE, then proc will be called once immediately.
PickleArbitraryTrc: PROC [trc: TRC, stream: IO.STREAM, indentation: ROPE ← NIL];
DepickleArbitraryTrc:
PROC [stream:
IO.
STREAM]
RETURNS [trc:
TRC];
These two go as a pair. The first puts the trc's class' flavor in the stream, followed by white space. The second (correspondingly) picks up a flavor, finds the corresponding class in the registry, and calls the depickle proc.
FetchProp:
PROC [viewer: Viewer, prop:
ATOM]
RETURNS [val:
REF
ANY];
Similar to ViewerOps.FetchProp, but with the following differences:
1. If ISTYPE[ViewerOps.FetchProp[viewer, prop], PropEvaluator], then return the result obtained by calling the eval proc with viewer, prop, and the eval data.
2. If ViewerOps.FetchProp[viewer, prop]~NIL, then recursively examine viewer.parent, etc.
PropEvaluator: TYPE ~ REF PropEvaluatorRep;
PropEvaluatorRep:
TYPE ~
RECORD [
proc: PROC [viewer: Viewer, prop: ATOM, data: REF] RETURNS [val: REF],
data: REF
];
Default Class Procs
These defaults are provided as a convenience to trc class implementors.
DefaultBlockFcn: BlockFcn;
Makes appropriate calls on trc.class.fcn
DefaultCopy: CopyProc;
DefaultPickle: PickleProc;
Puts NOTHING in the output stream. THEREFORE, should only be used by classes which are not parameterized. (E.g., use it for f(x)=x2, but not for f(x)=ax2.)
DefaultDepickle: DepickleProc; --Matches PickleProc
DefaultNotify: NotifyProc; --For classes with no direct screen interaction
DefaultBackground: BackgroundProc; --For classes with no background to paint
DefaultControl: BuildControlViewerProc; --For classes with nothing to control.
A handy template...
classClass: Trc.Class ~ NEW[Trc.ClassRep ← [
flavor: ATOM,
fcn: Fcn,
blockFcn: Trc.DefaultBlockFcn,
pickle: Trc.DefaultPickle,
depickle: Trc.DefaultDepickle,
notify: Trc.DefaultNotify,
tipTable: NIL,
background: Trc.DefaultBackground,
control: Trc.DefaultControl,
classData: NIL
]]