DIRECTORY AMTypes, AMBridge, Atom, Buttons, CD, CDCallSpecific, CDMenus, CDProperties, CDSequencer, CDViewer, Commander, Convert, IO, Menus, Process, Rope, TerminalIO, ViewRec, VFonts, ViewerClasses, ViewerOps; CDEMMPropertiesTool: CEDAR MONITOR IMPORTS AMTypes, AMBridge, Atom, Buttons, CDCallSpecific, CDMenus, CDProperties, CDSequencer, CDViewer, Commander, Convert, IO, Process, Rope, TerminalIO, ViewRec, VFonts, ViewerOps = BEGIN CDPropValue: TYPE = REF ANY; valueHandler: ViewRec.SimpleHandler = NEW [ViewRec.SimpleHandlerRep _ [ Parse: ParseValue, UnParse: UnParseValue, Max: MaxValue, Butt: NIL]]; valueInstance: REF CDPropValue = NEW[CDPropValue]; tvValueInstance: AMTypes.TypedVariable; lastRope: Rope.ROPE _ NIL; lastValueInstance: REF ANY _ NIL; ParseValue: PROC [asRope: Rope.ROPE, tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData: REF ANY] RETURNS [ok: BOOLEAN] -- ViewRec.ParseProc -- = BEGIN i: INT; isInt: BOOL _ TRUE; ok _ TRUE; lastRope _ asRope; i _ Convert.IntFromRope[asRope ! Convert.Error => {isInt _ FALSE; CONTINUE}]; valueInstance^ _ lastValueInstance _ (SELECT TRUE FROM isInt => NEW[INT _ i], asRope.Equal["NIL"] => NIL, asRope.Length>0 AND asRope.Fetch[0] = '" => Convert.RopeFromLiteral[asRope], asRope.Length>0 AND asRope.Fetch[0] = '$ => Convert.AtomFromRope[asRope], ENDCASE => asRope); AMTypes.Assign[tv, tvValueInstance ! AMTypes.Error => {ok _ FALSE; CONTINUE}]; END; UnParseValue: PROC [tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData: REF ANY] RETURNS [asRope: Rope.ROPE] -- ViewRec.UnParseProc -- = BEGIN AMTypes.Assign[tvValueInstance, tv]; asRope _ IO.PutR[IO.refAny[valueInstance^]]; END; MaxValue: PROC [tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData: REF ANY] RETURNS [maxWidthNeeded: INTEGER, lines: REAL _ 1] -- ViewRec.MaxProc -- = BEGIN maxWidthNeeded _ 32*VFonts.StringWidth["X"]; END; ValueRecognizer: PROC [ t: AMTypes.Type, --unreduced onlyRecognize: BOOLEAN,--don't bother to produce the handler and handlerData specs: ViewRec.BindingList, --what will apply to this element createOptions: ViewRec.CreateOptions--for aggregate containing this elt ] RETURNS [ IKnowYou: BOOLEAN, handler: ViewRec.Handler, handlerData: REF ANY _ NIL] -- ViewRec.Recognizer -- = BEGIN handler _ valueHandler; IKnowYou _ FALSE; WHILE NOT IKnowYou DO name: Rope.ROPE = AMTypes.TypeToName[t]; SELECT TRUE FROM Rope.Equal[name, "CDPropValue"] => {IKnowYou _ TRUE}; AMTypes.TypeClass[t] = definition => t _ AMTypes.Ground[t]; ENDCASE => EXIT; ENDLOOP; END; PropertyToolState: TYPE = RECORD [ prop: ATOM _ $SignalName, value: CDPropValue _ NIL ]; ButtonTable: TYPE = RECORD [ pts: REF PropertyToolState, buttons: SEQUENCE size: NAT OF RECORD [ b: Buttons.Button, p: PropertyToolState, age: INT _ 0]]; ButtonInfo: TYPE = RECORD [ b: REF ButtonTable, i: INT ]; pts: REF PropertyToolState _ NIL; oldPts: REF PropertyToolState = NEW[PropertyToolState _ []]; PropertyToolUpdater: PROC = BEGIN ptViewer: ViewerClasses.Viewer; buttons: REF ButtonTable = NEW[ButtonTable[9]]; first: BOOL _ TRUE; oldEntryName: Rope.ROPE _ "CDPropTool"; buttons.pts _ pts _ NEW[PropertyToolState _ []]; ptViewer _ ViewerOps.CreateViewer[flavor: $Container, info: [name: "CDPropTool", openHeight: 6*VFonts.FontHeight[]+50]]; FOR i: INT IN [0..buttons.size) DO buttons[i] _ [ b: Buttons.Create[ info: [ name: "SetPropOnSelected ", parent: ptViewer, wx: (IF i MOD 3 = 0 THEN 0 ELSE buttons[i-1].b.wx+buttons[i-1].b.ww+2), wy: (IF i/3 = 0 THEN 0 ELSE buttons[i-3].b.wy+buttons[i-3].b.wh+2) ], proc: ButtonSetPropOnSelected, clientData: NEW[ButtonInfo _ [b: buttons, i: i]]], p: [prop: NIL, value: NIL]]; ENDLOOP; [] _ ViewRec.ViewRef[agg: pts, viewerInit: [parent: ptViewer, wy: buttons[buttons.size-1].b.wy+buttons[buttons.size-1].b.wh+2]]; DO IF first OR ResolveState[].changed THEN BEGIN newEntryName: Rope.ROPE = Label[pts^]; ReplaceEntry: PROC [menu: ATOM] = BEGIN CDMenus.CreateEntry[menu: menu, entry: oldEntryName, key: NIL]; CDMenus.CreateEntry[menu: menu, entry: newEntryName, key: $CDPropToolSet]; END; ReplaceEntry[menu: $NameMenuOnlyApp]; ReplaceEntry[menu: $NameMenuFull]; ReplaceEntry[menu: $NameMenuOnlyDesign]; oldEntryName _ newEntryName; first _ FALSE; END; Process.Pause[Process.MsecToTicks[500]]; ENDLOOP; END; ResolveState: ENTRY PROC RETURNS [ changed: BOOL ] = BEGIN ENABLE UNWIND => pts _ NIL; cpts: PropertyToolState _ GetValidPTS[]; SELECT TRUE FROM cpts.prop = NIL => NULL; cpts.prop # oldPts.prop => pts.value _ Atom.GetProp[$CDPropTool, cpts.prop]; cpts.value # oldPts.value => Atom.PutProp[$CDPropTool, cpts.prop, cpts.value]; cpts.value # Atom.GetProp[$CDPropTool, cpts.prop] => pts.value _ Atom.GetProp[$CDPropTool, cpts.prop]; ENDCASE => NULL; changed _ cpts # oldPts^; oldPts^ _ cpts; END; StartPropertyTool: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] -- Commander.CommandProc -- = BEGIN CDSequencer.ImplementCommand[$CDPropToolSet, SetPropOnSelected]; IF pts = NIL THEN TRUSTED {Process.Detach[FORK PropertyToolUpdater[]]}; END; Label: PROC [ p: PropertyToolState ] RETURNS [ r: Rope.ROPE ] = BEGIN value: Rope.ROPE = IO.PutR[IO.refAny[pts.value]]; r _ IO.PutFR["%g_%g", IO.atom[pts.prop], IO.rope[(IF value.Length < 15 THEN value ELSE Rope.Cat[value.Substr[len: 15], "..."])]]; END; GetValidPTS: PROC RETURNS [ p: PropertyToolState ] = BEGIN propProcs: CDProperties.PropertyProcs; p _ pts^; IF p.prop = NIL OR (propProcs _ CDProperties.FetchProcs[p.prop]) = NIL OR propProcs.exclusive THEN { IF p.prop # $IllegalProp THEN TerminalIO.WriteRope[IO.PutFR["CDPropTool: Property %g is %g.\n", IO.atom[p.prop], IO.rope[(SELECT TRUE FROM propProcs = NIL => "not registered with ChipNDale", propProcs.exclusive => "not allowed to be set by users", ENDCASE => "not permitted")]]]; Atom.PutProp[$CDPropTool, $IllegalProp, NIL]; pts^ _ p _ [prop: $IllegalProp, value: NIL]; }; END; age: INT _ 0; ButtonSetPropOnSelected: PROC [ parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE ] -- Buttons.ButtonProc -- = BEGIN PutOnButton: PROC [bt: REF ButtonTable, p: PropertyToolState] = BEGIN oldest: INT _ 1; FOR i: INT IN [1..bt.size) DO IF bt[i].p.prop = p.prop THEN { same: BOOL; WITH p.value SELECT FROM r: Rope.ROPE => WITH bt[i].p.value SELECT FROM r2: Rope.ROPE => same _ r.Equal[r2]; ENDCASE => same _ FALSE; k: REF INT => WITH bt[i].p.value SELECT FROM k2: REF INT => same _ k^ = k2^; ENDCASE => same _ FALSE; ENDCASE => same _ p.value = bt[i].p.value; IF same THEN {bt[i].age _ age; RETURN}; }; IF bt[i].age < bt[oldest].age THEN oldest _ i; ENDLOOP; bt[oldest].p _ p; bt[oldest].age _ age; Buttons.ReLabel[button: bt[oldest].b, newName: Label[p]]; END; bi: REF ButtonInfo = NARROW[clientData]; cpts: PropertyToolState _ bi.b[bi.i].p; cdViewer: ViewerClasses.Viewer; design: CD.Design; age _ age+1; IF cpts.prop # NIL THEN { bi.b[bi.i].age _ age; Atom.PutProp[$CDPropTool, bi.b[bi.i].p.prop, bi.b[bi.i].p.value]; bi.b.pts^ _ cpts; } ELSE { cpts _ GetValidPTS[]; IF cpts.prop = $IllegalProp THEN RETURN; PutOnButton[bi.b, cpts]; }; IF mouseButton = red THEN { IF (cdViewer _ CDViewer.LastViewer[]) # NIL AND (design _ CDViewer.DesignOf[cdViewer].design) # NIL THEN CDSequencer.ExecuteCommand[comm: NEW[CDSequencer.CommandRec _ [ref: NEW[PropertyToolState _ cpts]]], design: design, command: $CDPropToolSet] ELSE TerminalIO.WriteRope["CDPropTool: Couldn't find design in which to set properties\n"] }; END; SetPropOnSelected: ENTRY PROC [ c: CDSequencer.Command ] -- CDSequencer.CommandProc -- = BEGIN ENABLE UNWIND => NULL; onOb: BOOL; count: INT _ 0; cpts: PropertyToolState; DoSetProp: PROC [design: CD.Design, aptr: CD.ApplicationPtr, x: REF] RETURNS [done: BOOL_TRUE, removeMe: BOOL_FALSE, include: CD.ApplicationList_NIL, repaintMe: BOOL_FALSE, repaintInclude: BOOL_FALSE] -- CDCallSpecific.CallProc -- = BEGIN IF onOb THEN CDProperties.PutPropOnObject[aptr.ob, cpts.prop, cpts.value] ELSE CDProperties.PutPropOnApplication[aptr, cpts.prop, cpts.value]; count _ count+1; END; cpts _ (IF ISTYPE[c.ref, REF PropertyToolState] THEN NARROW[c.ref, REF PropertyToolState]^ ELSE GetValidPTS[]); IF cpts.prop # $IllegalProp THEN { onOb _ (CDProperties.GetPropFromList[CDProperties.FetchProcs[cpts.prop].properties, $ObjectsOnly] # NIL); [] _ CDCallSpecific.CallForSelected[design: c.design, whatElse: DoSetProp]; TerminalIO.WriteRope[IO.PutFR["CDPropTool: %g set to %g in %g%d applications.\n", IO.atom[cpts.prop], IO.refAny[cpts.value], IO.rope[(IF onOb THEN "objects underlying " ELSE "")], IO.int[count]]]; }; END; TRUSTED {tvValueInstance _ AMBridge.TVForReferent[valueInstance]}; ViewRec.RegisterRecognizerBeforeReductions[r: ValueRecognizer, end: Front, applyBefore: EquivalenceClass]; [] _ CDProperties.RegisterProperty[$ObjectsOnly, $CDProperties]; CDProperties.InstallProcs[$ObjectsOnly, [ makeCopy: CDProperties.CopyVal, internalWrite: CDProperties.RopePWrite, internalRead: CDProperties.RopePRead]]; Commander.Register["CDPropTool", StartPropertyTool, "Tool for adding/changing ChipNDale properties"]; END. ήCDEMMPropertiesTool.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Last edited by: McCreight, May 9, 1985 1:41:05 pm PDT Last Edited by: Barth, June 28, 1985 4:05:01 pm PDT A p p l i c a t i o n s Κ ή˜šœ™Jšœ Οmœ1™