DIRECTORY AMTypes, Buttons, List, Menus, Rope, ViewerClasses, VFonts; ViewRec: CEDAR DEFINITIONS IMPORTS VFonts = BEGIN NotAnAggregate: ERROR; NoSelectedProc: ERROR; AlreadyHandled: ERROR; BadID: ERROR [id: Id]; NotFound: ERROR [name: Path]; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; TypedVariable: TYPE = AMTypes.TypedVariable; Type: TYPE = AMTypes.Type; 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, dontAssign: BOOLEAN _ FALSE], Notify => [notify: NotifyClientProc, clientData: REF ANY _ NIL], TryRecognizer => [recognizer: Recognizer], Group => [sublist, altSublist: BindingList _ NIL], ENDCASE]; Id: TYPE = REF ANY; --actually UNION [ROPE, REF TEXT, REF INT (origin 1) (negatives mean count from end), all]; all: REF ANY; Path: TYPE = LIST OF Id; --outermost first BindingType: TYPE = {Value, 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, and a few other things, which are done at create time.-- 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: BOOLEAN _ FALSE, --draw border around every Name-Value pair bordRecs: BOOLEAN _ TRUE, --border a Value if it is a RECORD bordImmProcs: BOOLEAN _ TRUE, --border immediate PROCEDUREs bordPreProcs: BOOLEAN _ TRUE, --border prepared PROCEDUREs bordDoit: BOOLEAN _ TRUE, --border the Doit button in a Proc's args rec bordState: BOOLEAN _ 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 _ 13, --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: BOOLEAN _ TRUE, mayInitiateRelayout: BOOLEAN _ TRUE, maxEltsHeight: CARDINAL _ 290, --limits display for elements maxArgsHeight: CARDINAL _ 310, --limits PROC arg display height doAllRecords: BOOLEAN _ FALSE, --if TRUE, every record is judged simple enough to attempt to display; components will still be judged individually exclusiveProcs: BOOLEAN _ TRUE, --makes procs mutually exclusive holdOff: BOOLEAN _ FALSE, --prevents actually calling PROCs highlightSelectedProc: BOOLEAN _ TRUE, --causes current Proc Button to display Black on Grey other: List.AList _ NIL --for expansion ]; OtherStuffProc: TYPE = PROC [in: Viewer] RETURNS [stuff: LIST OF Viewer]; ButtonClick: TYPE = RECORD [ button: Buttons.Button _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOLEAN _ FALSE]; EltHandle: TYPE = REF ANY; --type system lets us down ViewTV: PROC [agg: TypedVariable, specs: BindingList _ NIL, label: ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toButt: ButtonClick _ [], parent: RecordViewer _ NIL, asElement: EltHandle _ NIL, sample: BOOLEAN _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], paint: BOOLEAN _ TRUE] RETURNS [rv: RecordViewer]; ViewRef: PROC [agg: REF ANY, specs: BindingList _ NIL, label: ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toButt: ButtonClick _ [], parent: RecordViewer _ NIL, asElement: EltHandle _ NIL, sample: BOOLEAN _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], paint: BOOLEAN _ 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: BOOLEAN _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], paint: BOOLEAN _ TRUE] RETURNS [RecordViewer]; ViewSelf: PROC; 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: BOOLEAN _ 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: BOOLEAN _ FALSE] RETURNS [bl: BindingList]; BindingListAppend: PROC [a, b: BindingList] RETURNS [c: BindingList]; ReLayout: PROC [rv: RecordViewer, targetWidth: INTEGER _ 0, paint: BOOLEAN]; SampleRV: PROC [rv: RecordViewer]; RedisplayElt: PROC [eh: REF ANY]; CallSelectedProc: PROC [in: RecordViewer] RETURNS [refused: BOOLEAN]; 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: BOOLEAN]; GetEltHandle: PROC [rv: RecordViewer, name: Path] RETURNS [eh: EltHandle]; RVQuaViewer: PROC [RecordViewer] RETURNS [Viewer]; ViewerIsRV: PROC [Viewer] RETURNS [BOOLEAN]; ViewerQuaRV: PROC [Viewer] RETURNS [RecordViewer]; 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: BOOLEAN,--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: BOOLEAN, 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: 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: 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: BOOLEAN _ 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]; FinishPendingBusiness: PROC RETURNS [okToProceed: BOOLEAN]; SetPendingBusiness: PROC [proc: FinishProc _ NIL, data: REF ANY _ NIL]; FinishProc: TYPE = PROC [data: REF ANY] RETURNS [okToProceed: BOOLEAN]; RecognizeRope, RecognizeAtom, RecognizeNumber, RecognizeEnumeration, RecognizeRecord, RecognizeSequence--also works on ARRAYs--: Recognizer; SimpleEnough: PROC [rt: --an aggregate--Type, specs: BindingList, createOptions: CreateOptions] RETURNS [ok: BOOLEAN, count--of visible elements--: CARDINAL]; RightFont: PROC [f: VFonts.Font] RETURNS [rf: VFonts.Font] = INLINE {RETURN [IF f = NIL THEN VFonts.defaultFont ELSE f]}; 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. dFILE: [Ivy]Top>ViewRec.DF=>ViewRec.Mesa last edited by Spreitzer October 30, 1983 6:22 pm Last Edited by: Maxwell, November 16, 1982 3:28 pm Errors: raised by the create procs if not handed a record, structure (unpainted record), sequence, or array. raised by CallSelectedProc raised by registration procs raised by create procs and GetEltHandle. raised by GetEltHandle. Familiar Types: New Types: A handle on the display of an element of an aggregate. Creating RecordViewers: This is it: Create a RecordViewer on "agg". "specs" says some random things about components: 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). 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 aggregates and the argument record of procedures. A TryRecognizer binding is how Clients may specify their own ways of handling components (see the section on "Introducing new ways of displaying things"). 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 ButtonClick 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 this is being applied to an aggregate embedded in an aggregate viewed with ViewRec, pass the EltHandle for this 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. "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]. if "paint", then painted when done. ViewRef is just like ViewTV, except it takes a REF to a record. makes a top-level RecordViewer on an Interface Record from a DEFINITIONs module invokes ViewInterface on ViewRec BindingList manipulations: 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: 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. 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. 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šœ2™2Jšœ1™1Jšœ2™2J˜codešΟk ˜ K˜;—K˜K˜šΠbxœœ ˜K˜Kšœ ˜K˜—Kš˜K˜šΟl™K˜šœœ˜Kšœd™d—K˜šœœ˜Kšœ™—K˜šœœ˜K™—K˜šœœ ˜K™(—K™šœ œ˜K™—K™—K™šŸ™K˜Kšœœœ˜Kšœœ˜$Kšœœ˜,Kšœœ˜K˜—K˜šŸ ™ K˜Kšœœœ˜)Kšœœ˜K˜Kšœ œœœ ˜$šœ œœ˜Kšœ ˜ šœœ˜!Kšœ=œœ˜NKšœ1œœœ˜@Kšœ*˜*Kšœ-œ˜2Kšœ˜ ——K˜KšœœœœΟc[˜oK˜Kšœœœ˜ K˜Kšœœœœ ˜*K˜Kšœ œ)˜:K˜Kš Οnœœœœœ˜4K˜Kšœ œœœ˜)Kš œœœ&œœ˜KK˜Kšœœœœ˜K˜Kš P˜Pšœœœ˜Kšœœ ˜?Kšœœ #˜CKšœœ (˜EKšœœ (˜FKšœœ $˜AKšœœ #˜AKšœ œœ *˜EKšœ œœ "˜—K˜Kš‘œœœ œ˜EK˜š‘œœœ˜3K™K˜šœœœ˜!K™;——K˜š ‘ œœœœ œ˜K˜—K˜Kš‘ œœœ œ2œœœœ˜uKš‘ œœœ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™Z—K˜š ‘œœœœœœ˜GK˜Kš‘ œœœœœœœ˜G—K˜Kš ‘ œ‘ œ‘œ‘œ‘œ‘ œ ˜ŒK˜Kš‘ œœ œ8œœ œœ˜žK˜š‘ œœœ˜CKš œœœœœœ˜5—K˜—K™šŸ$™$K˜šœœœ˜ 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šœ˜K˜—…—':H|