DIRECTORY AMTypes, Buttons, List, Menus, Rope, ViewerClasses, VFonts; ViewRec: CEDAR DEFINITIONS IMPORTS VFonts = BEGIN ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; TypedVariable: TYPE = AMTypes.TypedVariable; Type: TYPE = AMTypes.Type; ViewRef: PROC [ agg: REF ANY, specs: BindingList _ NIL, label: ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toButt: ButtonClick _ [], parent: RecordViewer _ NIL, asElement: EltHandle _ NIL, sample: BOOL _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], wDir: ROPE _ NIL, paint: BOOL _ TRUE ] RETURNS [rv: RecordViewer]; NotAnAggregate: ERROR; OtherStuffProc: TYPE = PROC [in: Viewer] RETURNS [stuff: LIST OF Viewer]; ButtonClick: TYPE = RECORD [ button: Buttons.Button _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE]; EltHandle: TYPE = REF ANY; --type system lets us down RecordViewer: TYPE = REF RecordViewerPrivate; RecordViewerPrivate: TYPE; ViewTV: PROC [agg: TypedVariable, specs: BindingList _ NIL, label: ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toButt: ButtonClick _ [], parent: RecordViewer _ NIL, asElement: EltHandle _ NIL, sample: BOOL _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], wDir: ROPE _ NIL, paint: BOOL _ TRUE] RETURNS [rv: RecordViewer]; ViewInterface: PROC [name: ROPE, specs: BindingList _ NIL, label: ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toButt: ButtonClick _ [], parent: RecordViewer _ NIL, asElement: EltHandle _ NIL, sample: BOOL _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], wDir: ROPE _ NIL, paint: BOOL _ TRUE] RETURNS [RecordViewer]; ViewSelf: PROC; CreateOptions: TYPE = RECORD [ immProcFont: VFonts.Font _ NIL, --NIL means use Viewers default preProcFont: VFonts.Font _ NIL, --font for prepared procedure names 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: BOOL _ FALSE, --draw border around every Name-Value pair bordRecs: BOOL _ TRUE, --border a Value if it is a RECORD bordImmProcs: BOOL _ TRUE, --border immediate PROCEDUREs bordPreProcs: BOOL _ TRUE, --border prepared PROCEDUREs bordDoit: BOOL _ TRUE, --border the Doit button in a Proc's args rec bordState: BOOL _ FALSE, --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 _ 1, --width of Value boxes, beyond string width nvSep: CARDINAL _ 3, --seperation between Name and Value vStilts: INTEGER _ -1, --artificially lower the Name Label this much feedBackHeight: CARDINAL _ 40, --how high the FeedBack Window is minFeedBackWidth: CARDINAL _ 100, --unless height is 0, of course minRecordWidth: CARDINAL _ 100, --lower bound for RECORDs defaultTargetWidth: CARDINAL _ 400, relayoutable: BOOL _ TRUE, mayInitiateRelayout: BOOL _ TRUE, maxEltsHeight: CARDINAL _ 290, --limits display for elements maxArgsHeight: CARDINAL _ 310, --limits PROC arg display height doAllRecords: BOOL _ FALSE, --if TRUE, every record is judged simple enough to attempt to display; components will still be judged individually exclusiveProcs: BOOL _ TRUE, --makes procs mutually exclusive holdOff: BOOL _ FALSE, --prevents actually calling PROCs highlightSelectedProc: BOOL _ TRUE, --causes current Proc Button to display Black on Grey other: List.AList _ NIL --for expansion ]; RightFont: PROC [f: VFonts.Font] RETURNS [rf: VFonts.Font] = INLINE {RETURN [IF f = NIL THEN VFonts.defaultFont ELSE f]}; BindingList: TYPE = LIST OF Binding; Binding: TYPE = RECORD [ name: Id, it: SELECT type: BindingType FROM Value => [val: TypedVariable, visible, editable, dontAssign: BOOL _ FALSE], Notify => [notify: NotifyClientProc, clientData: REF ANY _ NIL], TryRecognizer => [recognizer: Recognizer], Group => [sublist, altSublist: BindingList _ NIL], ENDCASE]; BindingType: TYPE = {Value, Notify, TryRecognizer, Group}; Id: TYPE = REF ANY; --actually UNION [ROPE, REF TEXT, REF INT (origin 1) (negatives mean count from end), all]; BadID: ERROR [id: Id]; all: Id; Int: TYPE = REF INT; NotifyClientProc: TYPE = PROC [clientData: REF ANY]; BindAllOfATypeFromTVs: PROC [ aggType, eltType: Type, name: ROPE _ NIL, b: Binding --fill the "it" field with what you want ] RETURNS [BindingList]; BindAllOfATypeFromRefs: PROC [rec, handle: REF ANY, name: ROPE _ NIL, visible, editable, dontAssign: BOOL _ FALSE] RETURNS [BindingList]; BindAllOfANameInType: PROC [agType: Type, name: ROPE, b: Binding] RETURNS [bl: BindingList]; BindAllOfANameFromRef: PROC [agInst: REF ANY, name: ROPE, val: REF ANY, visible, editable, dontAssign: BOOL _ FALSE] RETURNS [bl: BindingList]; BindingListAppend: PROC [a, b: BindingList] RETURNS [c: BindingList]; GetWorkingDirectory: PROC [rv: RecordViewer] RETURNS [wDir: ROPE]; SetWorkingDirectory: PROC [rv: RecordViewer, new: ROPE] RETURNS [old: ROPE]; ReLayout: PROC [rv: RecordViewer, targetWidth: INTEGER _ 0, paint, forkResize: BOOL]; SampleRV: PROC [rv: RecordViewer]; RedisplayElt: PROC [eh: REF ANY]; CallSelectedProc: PROC [in: RecordViewer] RETURNS [refused: BOOL]; NoSelectedProc: ERROR; DisplayMessage: PROC [rv: RecordViewer, msg: ROPE]; clearMessagePlace: READONLY ROPE; SetUserAbort: PROC [who: REF ANY, newLevel: CARDINAL _ 100]; IncrementUserAbort: PROC [who: REF ANY, deltaLevel: INTEGER]; TestUserAbort: PROC [who: REF ANY] RETURNS [abort: CARDINAL]; TestAndMaybeResetUserAbort: PROC [who: REF ANY, threshold: CARDINAL _ 100] RETURNS [abort: CARDINAL --will be 0 or >= threshold--]; ProcessAbort: PROC [who: REF ANY] RETURNS [found: BOOL]; GetEltHandle: PROC [rv: RecordViewer, name: Path] RETURNS [eh: EltHandle]; Path: TYPE = LIST OF Id; --outermost first NotFound: ERROR [name: Path]; RVQuaViewer: PROC [RecordViewer] RETURNS [Viewer]; ViewerIsRV: PROC [Viewer] RETURNS [BOOL]; ViewerQuaRV: PROC [Viewer] RETURNS [RecordViewer]; IsRV: PROC [REF ANY] RETURNS [BOOL]; NarrowToRV: PROC [REF ANY] RETURNS [RecordViewer]; Help: PROC; GetName: PROC [tv: TypedVariable --record or structure--] RETURNS [name: ROPE]; 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: BOOL, --don't bother to produce the handler and handlerData specs: BindingList, --what will apply to this element createOptions: CreateOptions--for aggregate containing this elt ] RETURNS [ IKnowYou: BOOL, handler: Handler, handlerData: REF ANY _ NIL]; 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: ROPE _ NIL --tells what can be done with Right Button ]; ParseProc: TYPE = PROC [asRope: ROPE, tv: TypedVariable, targType: Type, handlerData: REF ANY] RETURNS [ok: BOOL]; 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: BOOL] RETURNS [new: TypedVariable, msg: ROPE _ NIL]; ComplexHandler: TYPE = REF ComplexHandlerRep; ComplexHandlerRep: TYPE = RECORD [ producer: ComplexProducer, relayouter: ReLayouter _ NIL, updater: Updater, elementGiver: ElementGiver _ NIL ]; ComplexProducer: TYPE = PROC [tv: TypedVariable, context: Context, handlerData: REF ANY] RETURNS [v: Viewer, clientData: REF ANY, sampleable: BOOL _ TRUE]; ReLayouter: TYPE = PROC [v: Viewer, maxWidth: INTEGER, handlerData, clientData: REF ANY]; Updater: TYPE = PROC [tv: TypedVariable, v: Viewer, handlerData, clientData: REF ANY]; ElementGiver: TYPE = PROC [agg: TypedVariable, which: Id, handlerData, clientData: REF ANY] RETURNS [eh: EltHandle]; Context: TYPE = RECORD [ main: Viewer, for: RecordViewer, maxWidth: INTEGER, name: ROPE, thisElement: EltHandle, createOptions: CreateOptions, notifies: NotifyList, bindings: BindingList, toButt: ButtonClick]; NotifyList: TYPE = LIST OF NotifyRequest; NotifyRequest: TYPE = RECORD [proc: NotifyClientProc, clientData: REF ANY]; FinishPendingBusiness: PROC RETURNS [okToProceed: BOOL]; SetPendingBusiness: PROC [proc: FinishProc _ NIL, data: REF ANY _ NIL]; FinishProc: TYPE = PROC [data: REF ANY] RETURNS [okToProceed: BOOL]; RecognizeRope, RecognizeAtom, RecognizeNumber, RecognizeEnumeration, RecognizeRecord, RecognizeSequence--also works on ARRAYs--: Recognizer; RecognizeBoolShort: Recognizer; SimpleEnough: PROC [rt: --an aggregate--Type, specs: BindingList, createOptions: CreateOptions] RETURNS [ok: BOOL, count--of visible elements--: CARDINAL]; BehaviorOptions: TYPE = RECORD [ delayParms: DelayParms _ [] --controls delay in sampling process ]; DelayParms: TYPE = RECORD [ min: REAL _ 200, max: REAL _ 3000, offset: REAL _ 0, dActive: REAL _ 0, dExtant: REAL _ 0, dElt: REAL _ 0, dMicroseconds: REAL _ 4E-3, --wait 4 times as long as you work priority: DelayPriority _ Normal]; DelayPriority: TYPE = {Normal, Background, Foreground}; delayed: READONLY REAL; --running average of sample time, weights are z**n z: REAL; behavior: BehaviorOptions; SetBehavior: PROC [newBehavior: BehaviorOptions _ []]; END. δFILE: [Cedar]Top>ViewRec.DF=>ViewRec.Mesa last edited by Spreitzer November 11, 1985 6:32:18 pm PST Last Edited by: Maxwell, November 16, 1982 3:28 pm Familiar Types: Creating RecordViewers: The following procedure creates a RecordViewer on the referent of "agg". For simple usage, default all other arguments. See section on binding lists. A label to put in the upper left corner of the viewer. NIL means don't label. You can force following sub-viewers to be below the label by making the label end in CR; the CR won't appear in the text of the label. A way to include other viewers in the created RecordViewer; they go after the label and before anything else. "toButt" is invoked when CONTROL-RETURN is typed in a Value Viewer by the User. The "parent" is independant of the Viewers ancestry; it is used for finding a FeedBack Window. If ViewRef is being applied to an aggregate logically embedded in another aggregate which is itself being viewed with ViewRec, pass the EltHandle for "agg" in "asElement" (to make Next and Previous work correctly). "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. For control of layout, and a few other things, which are done at create time; default gives reasonable behavior. "viewerInit" is for the usual Viewers initing stuff, except: for 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. for name: If name = NIL, then we try GetName[agg]. The working directory to be current for procedures invoked from this RecordViewer; NIL means use working directory current at create time (now). if "paint", then painted when done. raised by the create procs if not handed a record, structure (unpainted record), sequence, or array. A handle on the display of an element of an aggregate. ViewTV is just like ViewRef, except it takes a TypedVariable for the subject. makes a top-level RecordViewer on an Interface Record from a DEFINITIONs module invokes ViewInterface on ViewRec CreateOptions: These control layout, and a few other things, which are done at create time. BindingLists: What are Binding Lists? Binding lists provide a way to say random things about components of an aggregate: A Value binding will cause that component to be initialized to the given value; furthermore, this prevents that component from making the aggregate it is part of too complicated to handle. Setting "dontAssign" prevents this intialization. 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). A TryRecognizer binding is how clients may specify their own ways of handling components (see the section on "Introducing new ways of displaying things"). Group bindings are the method by which components of nested aggregates are addressed. the "altSublist" applies to the return record of procedures; the "sublist" applies to embedded aggregates and the argument record of procedures. raised by create procs and GetEltHandle. returns a binding list where everything in "aggType" whose type = "eltType", and whose name = "name", gets bound according to the b.it; IF name = NIL, THEN the name test is ignored. Uses BindAllOfATypeFromTVs to make Value Bindings. The value used is the REFERENT of handle (NOT handle itself). For instance, to bind all Viewer variables to the value in v1, say "handle: NEW [Viewer _ v1]", not "handle: v1". This is destructive (i.e. non-functional: it may alter CDR of last CONS cell in "a"). Things to do with RecordViewers once they have been created: If ideal height changes, forkResize tells whether to fork the operation of letting Viewers know this (meaningful only for an rv that's a top-level viewer). Ensures that the current values are displayed Ensures that the current value of this component is displayed. The msg is displayed wherever messages from this RecordViewer are displayed; the message is appended to the others already there, unless it is: this message will clear out wherever messages are going to. If who gets a RecordViewer, one of its procedure invocations (if any) is the subject; If who gets an EltHandle, the running invocation of that procedure is the subject. If it was >= threshold, it is reset to 0, and the old value returned; otherwise it is left as it was, and 0 is returned. Calls Process.Abort on the running proc, if any. GetEltHandle raises NotFound[tail(i)[name]] when lost at i'th step. SIMULA-style coersions between CLASSes: For the fun of it: opens a viewer on the document Finds a field named "name", if any, and returns contents as rope, if possible. Returns NIL if not possible. Introducing new ways of displaying things: Responsible for putting up the viewer for the element. Called when change of value detected. If this element is an aggregate, this is for getting its elements. Upon user action in a Complex Viewer, first call this proc to get permission to handle it. The standard ones; already registered. Displays booleans as simply T or F. Non-standard; not initially registered. For controling the sampling process: These parameters determine the number of milliseconds to pause: these are the bits actually used to set them all at once Κ-˜JšœΟmœ™6Jšœ9™9Jšœ2™2J˜IcodešΟk œ<˜EK˜šΠbxœžœž ˜Kšžœ ˜—Kšž˜headšœ™Kšžœžœžœ˜Kšœžœ˜$Kšœžœ˜,Kšœžœ˜—šœ™Kšœx™xK˜šΟnœžœ˜Kšœžœžœ˜ šœžœ˜Kšœ™—šœžœžœ˜K™Φ—šœžœ˜!K™m—˜K™O—šœžœ˜Kšœ^™^—šœžœ˜KšœΦ™Φ—šœžœžœ˜Kšœ}™}—˜"Kšœp™p—˜)šœ<™<šœ™KšœJ™JKšœ@™@Kšœo™o—™ K™(———šœžœžœ˜K™—šœžœž˜Kšœ#™#—Kšœ˜Kšžœ˜—K˜šœžœ˜Kšœd™d—K˜Kš  œžœžœžœ žœžœ ˜IK˜šœ žœžœ˜Kšœžœ˜K˜%Kšœžœžœ˜—K˜šœ žœžœžœΟc˜5J™6—K˜Kšœžœžœ˜-Kšœžœ˜K˜š œžœ˜!Kšœžœ˜Kšœžœžœ˜Kšœžœ˜!K˜Kšœžœ˜Kšœžœ˜Kšœžœžœ˜K˜"K˜)Kšœžœžœ˜Kšœžœžœ˜Kšžœ˜K˜KšœM™M—K˜š  œžœ ˜ Kšœžœ˜Kšœžœ˜Kšœžœ˜!K˜Kšœžœ˜Kšœžœ˜Kšœžœžœ˜K˜"K˜)Kšœžœžœ˜Kšœžœžœ˜Kšžœ˜K˜KšœO™O—K˜š œžœ˜Kšœ ™ ——šœ™IbodyšœL™LK˜šœžœžœ˜Kšœžœ‘˜?Kšœžœ‘#˜CKšœžœ‘(˜EKšœžœ‘(˜FKšœžœ‘$˜AKšœžœ‘#˜AKšœ žœžœ‘*˜CKšœ žœžœ‘"˜:Kšœžœžœ‘˜8Kšœžœžœ‘˜7Kšœ žœžœ‘-˜EKšœ žœžœ‘)˜BKšœžœ‘ ˜5Kšœžœ‘"˜7Kšœžœ‘+˜@Kšœžœ‘+˜@Kšœžœ‘#˜9Kšœ žœ‘-˜EKšœžœ‘!˜@Kšœžœ‘˜AKšœžœ‘˜9Kšœžœ˜#Kšœžœžœ˜Kšœžœžœ˜!Kšœžœ‘˜—K˜š œžœžœ žœ˜BK˜Kšœžœ˜—K˜š œžœžœ˜3K™K˜šœžœžœ˜!K™;——K˜š   œžœžœžœ žœ˜K˜—K˜Kš  œžœžœ žœ2žœžœžœžœ˜rKš  œžœžœ2žœžœžœ žœ˜jKš œžœžœ2žœžœžœžœ žœ˜‚Kš œžœžœJžœžœ žœžœžœžœ˜£K˜Kšœžœžœ˜-šœžœžœ˜"šœ˜J™6K˜—šœžœ˜K˜—šœ˜J™%K˜—šœž˜ J™B—Kšœ˜—K˜Kš œžœžœ4žœžœžœžœžœžœžœ˜›K˜Kš   œžœžœžœžœžœ˜YK˜Kš  œžœžœ9žœžœ˜VK˜Kš   œžœžœ:žœžœžœ˜tK˜šœ žœžœ˜K˜ K˜Kšœ žœ˜Kšœžœ˜ K˜K˜K˜K˜K˜—K˜Kšœ žœžœžœ˜)Kš œžœžœ&žœžœ˜KK˜š œžœžœžœ˜8K™Z—K˜š  œžœžœžœžœžœ˜GK˜Kš  œžœžœžœžœžœžœ˜D—K˜š   œ  œ œ œ œ ‘œ ˜ŒK™&—K˜š œ ˜K™#K™'—K˜Kš  œžœ‘œ8žœžœ‘œžœ˜›—šœ$™$šœžœžœ˜ Kšœ‘$˜@K˜K˜—K™?šœ žœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ ‘"˜>K˜"K˜—Kšœžœ$˜7K˜Kšœ žœžœ‘2˜JKšœžœ˜K˜˜Kšœ ™ —K˜š  œžœ%˜6Kšœ™—K˜—Kšžœ˜K˜—…—'tL