FILE: [Ivy]<Spreitzer>ViewRec>ViewRec.Mesa
last edited by Spreitzer March 11, 1983 12:10 pm
Last Edited by: Maxwell, November 16, 1982 3:28 pm
DIRECTORY
AMTypes, List, Rope, ViewerClasses, VFonts;
ViewRec: CEDAR DEFINITIONS
IMPORTS VFonts =
BEGIN
Errors:
NotARecord: ERROR;
raised by the create procs if not handed a record
NoSelectedProc: ERROR;
raised by CallSelectedProc
AlreadyHandled: ERROR;
raised by registration procs
BadID: ERROR [id: Id];
raised by create procs and GetEltHandle.
NotFound: ERROR [name: Path];
raised by GetEltHandle.
Familiar Types:
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
TypedVariable: TYPE = AMTypes.TypedVariable;
Type: TYPE = AMTypes.Type;
New Types:
RecordViewer: TYPE = REF RecordViewerRep;
RecordViewerRep: TYPE;
BindingList: TYPE = LIST OF Binding;
Binding: TYPE = RECORD [
name: Id,
it: SELECT type: BindingType FROM
Value => [val: TypedVariable, visible, editable: BOOLEANFALSE],
Editable => [editable: BOOLEANFALSE],
Notify => [notify: NotifyClientProc, clientData: REF ANYNIL],
TryRecognizer => [recognizer: Recognizer],
Group => [sublist, altSublist: BindingList ← NIL],
ENDCASE];
Id: TYPE = REF ANY; --actually UNION [ROPE, REF TEXT, REF INT (origin 1)];
Path: TYPE = LIST OF Id; --outermost first
BindingType: TYPE = {Value, Editable, Notify, TryRecognizer, Group};
NotifyClientProc: TYPE = PROC [clientData: REF ANY];
NotifyList: TYPE = LIST OF NotifyRequest;
NotifyRequest: TYPE = RECORD [proc: NotifyClientProc, clientData: REF ANY];
Int: TYPE = REF INT;
these control layout, which is done at create time:
CreateOptions: TYPE = RECORD [
procFont: VFonts.Font ← NIL, --NIL means use Viewers default
doitFont: VFonts.Font ← NIL, --for the Doit button in Proc's args rec
stateFont: VFonts.Font ← NIL, --for the State label in Proc's args rec
nameFont: VFonts.Font ← NIL, --for first half of name:value pairs
labelFont: VFonts.Font ← NIL, --for the label of the RecordViewer
bordElts: BOOLEANFALSE, --draw border around every Name-Value pair
bordRecs: BOOLEANTRUE, --border a Value if it is a RECORD
bordProcs: BOOLEANTRUE, --border PROCEDUREs
bordDoit: BOOLEANTRUE, --border the Doit button in a Proc's args rec
bordState: BOOLEANFALSE, --border the State label in a Proc's args
vSep: CARDINAL ← 2,  --spacing between lines of stuff
hSep: CARDINAL ← 5,  --spacing between things on a line
vPad: CARDINAL ← 3,  --height of Value boxes, beyond font height
hPad: CARDINAL ← 13,  --width of Value boxes, beyond string width
nvSep: CARDINAL ← 3,  --seperation between Name and Value
vStilts: CARDINAL ← 1,  --artificially raise the Name Label this much
feedBackHeight: CARDINAL ← 40, --how high the FeedBack Window is
minRecordWidth: CARDINAL ← 100, --lower bound for RECORDs
defaultTargetWidth: CARDINAL ← 400,
doAllRecords: BOOLEANFALSE,--if TRUE, every record is judged simple enough to attempt to display; components will still be judged individually
other: List.AList ← NIL  --passed to complex handlers
];
OtherStuffProc: TYPE = PROC [in: Viewer] RETURNS [stuff: LIST OF Viewer];
DoitProc: TYPE = PROC [rv: RecordViewer, data: REF ANY];
Creating RecordViewers:
ViewTV: PROC [rec: TypedVariable,
specs: BindingList ← NIL,
label: ROPE ← NIL,
otherStuff: OtherStuffProc ← NIL,
toDo: DoitProc ← NIL,
toDoData: REF ANYNIL,
parent: RecordViewer ← NIL,
sample: BOOLEANTRUE,
holdOff: BOOLEANFALSE,
highlightSelectedProc: BOOLEANTRUE,
createOptions: CreateOptions ← [],
viewerInit: ViewerClasses.ViewerRec ← [],
paint: BOOLEANTRUE]
RETURNS [rv: RecordViewer];
This is it: Create a RecordViewer on "rec".
"specs" says some random things about components:
a Value binding will cause that component to be initialized to the given value; furhtermore, this prevents that component from making the record it is part of too complicated to handle.
Setting "visible" FALSE will prevent the bound component from appearing on the screen.
Setting "editable" FALSE will ensure that it will not be editable.
a Notify binding causes ViewRec to call the given NotifyClientProc whenever ViewRec changes the value of that component (and maybe some other times as well).
Group bindings are the method by which components of nested records are addressed.
the "altSublist" applies to the return record of procedures; the "sublist" applies to embedded records and the argument record of procedures.
if the last char of "label" is CR, it will be the sole occupant of the first line.
The OtherStuffProc produces a set of viewers to put at the beginning of the RecordViewer.
The DoitProc is called when CONTROL-RETURN is typed in a Value Viewer by the User; toDoData is passed to it.
the "parent" is independant of the Viewers ancestry; used for finding feedBack.
"sample" causes this RecordViewer to be put on a list of RV's to be sampled in the background to keep its display up to date.
"holdOff" makes procs uncallable.
"highlightSelectedProc" causes current Proc Button to display Black on Grey.
"viewerInit" is for the usual Viewers initing stuff, with the additional use of ww:
the RecordViewer lays itself out to the inner width of the Viewer created,
unless ww#0 and viewerInit.parent=NIL, in which case ww is used,
or unless ww=0 and (viewerInit.parent#NIL OR iconic), in which case createOptions.minRecordViewerWidth is used.
if "paint", then painted when done.
ViewRef: PROC [rec: REF ANY,
specs: BindingList ← NIL,
label: ROPENIL,
otherStuff: OtherStuffProc ← NIL,
toDo: DoitProc ← NIL,
toDoData: REF ANYNIL,
parent: RecordViewer ← NIL,
sample: BOOLEANTRUE,
holdOff: BOOLEANFALSE,
highlightSelectedProc: BOOLEANTRUE,
createOptions: CreateOptions ← [],
viewerInit: ViewerClasses.ViewerRec ← [],
paint: BOOLEANTRUE]
RETURNS [rv: RecordViewer];
ViewRef is just like ViewTV, except it takes a REF to the record.
ViewInterface: PROC [name: ROPE,
specs: BindingList ← NIL,
label: ROPE ← NIL,
otherStuff: OtherStuffProc ← NIL,
toDo: DoitProc ← NIL,
toDoData: REF ANYNIL,
parent: RecordViewer ← NIL,
sample: BOOLEANTRUE,
holdOff: BOOLEANFALSE,
highlightSelectedProc: BOOLEANTRUE,
createOptions: CreateOptions ← [],
viewerInit: ViewerClasses.ViewerRec ← [],
paint: BOOLEANTRUE]
RETURNS [RecordViewer];
makes a top-level RecordViewer on an Interface Record from a DEFINITIONs module
ViewSelf: PROC;
invokes ViewInterface on ViewRec
BindingList manipulations:
BindAllOfATypeFromTVs: PROC [
recType: Type,
handle: TypedVariable,
name: ROPE ← NIL,
visible, editable: BOOLEANFALSE]
RETURNS [BindingList];
returns a binding list where everything in "recType" whose type = type of "handle", and whose name = "name", gets bound to "handle", with visible and editable flags;
IF name = NIL, THEN the name test is ignored.
BindAllOfATypeFromRefs: PROC [rec, handle: REF ANY, name: ROPE ← NIL, visible, editable: BOOLEANFALSE]
RETURNS [BindingList];
uses the type of referent of "rec", and the referent of "handle", in call on BindAllOfATypeFromTVs
BindingListAppend: PROC [a, b: BindingList] RETURNS [c: BindingList];
maybe alters last CONS cell in "a":
Things to do with RecordViewers once they have been created:
GetEltHandle: PROC [rv: RecordViewer, name: Path] RETURNS [eh: REF ANY];
RAISES NotFound[tail(i)[name]] when lost at i'th step.
SampleRV: PROC [rv: RecordViewer];
ensures that the current values are displayed
RedisplayElt: PROC [eh: REF ANY];
CallSelectedProc: PROC [in: RecordViewer] RETURNS [refused: BOOLEAN];
DisplayMessage: PROC [rv: RecordViewer, msg: ROPE];
puts a message in feedBack window (or MessageWindow if no fb);
this message is appended to the others already there, unless it is:
clearMessagePlace: READONLY ROPE;
this message will clear out wherever messages are going to.
TestAndResetUserAbort: PROC [rv: RecordViewer, threshold: CARDINAL ← 100] RETURNS [abort: CARDINAL --will be 0 or >= threshold--];
TestUserAbort: PROC [rv: RecordViewer] RETURNS [abort: CARDINAL];
SetUserAbort: PROC [rv: RecordViewer, newLevel: CARDINAL ← 100];
IncrementUserAbort: PROC [rv: RecordViewer, deltaLevel: INTEGER];
ProcessAbort: PROC [rv: RecordViewer] RETURNS [found: BOOLEAN];
Calls Process.Abort on the running proc, if any.
SIMULA-style coersions between CLASSes:
RVQuaViewer: PROC [RecordViewer] RETURNS [Viewer];
ViewerIsRV: PROC [Viewer] RETURNS [BOOLEAN];
ViewerQuaRV: PROC [Viewer] RETURNS [RecordViewer];
For the fun of it:
Help: PROC;
opens a viewer on the document
Introducing new ways of displaying things:
RegisterRecognizerByType: PROC [r: Recognizer, end: AddPlace, type: Type--unreduced--, reductions: Reductions];
RegisterRecognizerBeforeReductions: PROC [r: Recognizer, end: AddPlace, applyBefore: Reductions];
RegisterRecognizerToApplyAfterAll: PROC [r: Recognizer, end: AddPlace];
Reductions: TYPE = {EquivalenceClass, StripSubranges, TypeClass};
AddPlace: TYPE = {Front, Back--of list of others already there--};
Recognizer: TYPE = PROC [t: Type--unreduced--, onlyRecognize: BOOLEAN--don't bother to produce the handler and handlerData--] RETURNS [IKnowYou: BOOLEAN, handler: Handler, handlerData: REF ANYNIL];
Handler: TYPE = REF ANY; --actually UNION {SimpleHandler, ComplexHandler}
SimpleHandler: TYPE = REF SimpleHandlerRep;
SimpleHandlerRep: TYPE = RECORD [
Parse: ParseProc, --NIL => read-only operation
UnParse: UnParseProc,
Max: MaxProc,
Butt: ButtProc ← NIL, --NIL => no meaning for Right (Blue) mouse button.
blueDoc: ROPENIL--tells what can be done with Right Button
];
ParseProc: TYPE = PROC [asRope: ROPE, tv: TypedVariable, targType: Type, handlerData: REF ANY] RETURNS [ok: BOOLEAN];
UnParseProc: TYPE = PROC [tv: TypedVariable, targType: Type, handlerData: REF ANY] RETURNS [asRope: ROPE];
MaxProc: TYPE = PROC [tv: TypedVariable, targType: Type, handlerData: REF ANY] RETURNS [maxWidthNeeded: INTEGER, lines: REAL ← 1];
ButtProc: TYPE = PROC [tv: TypedVariable, targType: Type, handler: SimpleHandler, handlerData: REF ANY, shift: BOOLEAN] RETURNS [new: TypedVariable, msg: ROPENIL];
ComplexHandler: TYPE = REF ComplexHandlerRep;
ComplexHandlerRep: TYPE = RECORD [
producer: ComplexProducer,
updater: Updater];
ComplexProducer: TYPE = PROC [tv: TypedVariable, context: Context, handlerData: REF ANY] RETURNS [v: Viewer, clientData: REF ANY];
Updater: TYPE = PROC [tv: TypedVariable, v: Viewer, handlerData, clientData: REF ANY];
Context: TYPE = RECORD [
main: Viewer,
for: RecordViewer,
name: ROPE,
createOptions: CreateOptions,
notifies: NotifyList];
FinishPendingBusiness: PROC RETURNS [okToProceed: BOOLEAN];
Upon user action in a Complex Viewer, first call this proc to get permission to handle it.
SetPendingBusiness: PROC [proc: FinishProc ← NIL, data: REF ANYNIL];
FinishProc: TYPE = PROC [data: REF ANY] RETURNS [okToProceed: BOOLEAN];
RecognizeRope, RecognizeNumber, RecognizeEnumerations: Recognizer;
For Wizardly experimentation:
BehaviorOptions: TYPE = RECORD [
delayParms: DelayParms ← [] --controls delay in sampling process
];
for experimenting with how to schedule the sampling process
DelayParms: TYPE = RECORD [
min: REAL ← 40,
max: REAL ← 3000,
offset: REAL ← 0,
dActive: REAL ← 0,
dExtant: REAL ← 0,
dElt: REAL ← 0,
dMicroseconds: REAL ← 4E-3,
interp: ParmInterpretation ← Milliseconds,
priority: DelayPriority ← Normal];
ParmInterpretation: TYPE = {ScanLines, Milliseconds};
DelayPriority: TYPE = {Normal, Background, Foreground};
delayed: READONLY REAL; --running average of sample time, weights are z**n
z: REAL;
behavior: BehaviorOptions;
these are the bits actually used
SetBehavior: PROC [newBehavior: BehaviorOptions ← []];
to set them all at once
END.