Trc.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Eric Nickell, April 10, 1986 1:02:22 am PST
DIRECTORY
Imager USING [Context, Rectangle, VEC],
IO USING [STREAM],
Properties USING [PropList],
Rope USING [ROPE],
TIPUser USING [TIPTable],
ViewerClasses USING [Viewer, ViewerRec];
Trc: CEDAR DEFINITIONS
~ BEGIN
Types
Context: TYPE ~ Imager.Context;
PropList: TYPE ~ Properties.PropList;
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,
depickle: DepickleProc ← NIL,
notify: NotifyProc ← NIL,
tipTable: TIPUser.TIPTable ← NIL,
background: BackgroundProc ← NIL,
control: BuildControlViewerProc ← NIL,
classData: REFNIL  --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: ROPENIL];
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: REFNIL];
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, propList: PropList ← NIL] 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.
propList provides a shotgun to tools using Trc. Class implementors have the option of examining the propList for keys (typically ATOMs) which various different classes might, by convention, have in common. 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, propList]];
};
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: BOOLFALSE];
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: BOOLFALSE];
Enumerates the registered classes in no particular order.
NotifyNewRegistrations: PROC [proc: PROC [clientData: REF], clientData: REFNIL, firstTime: BOOLTRUE];
proc will be called when new packages are registered.
If firstTime~TRUE, then proc will be called once immediately.
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
]]
Utilities
BuildTable: PROC [nElements: NAT, first, delta: REAL] RETURNS [table: Table];
Creates a linear table.
UnsafeTableFromTable: PROC [table: Table, start, count: NAT ← 0] RETURNS [unsafeTable: UnsafeTable];
If count~0, then it will be set to table.n-start.
END.