CDEMMPropertiesTool.mesa
Copyright © 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
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.ROPENIL;
lastValueInstance: REF ANYNIL;
ParseValue: PROC [asRope: Rope.ROPE, tv: AMTypes.TypedVariable, targType: AMTypes.Type, handlerData: REF ANY] RETURNS [ok: BOOLEAN] -- ViewRec.ParseProc -- =
BEGIN
i: INT;
isInt: BOOLTRUE;
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 ANYNIL] -- 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;
A p p l i c a t i o n s
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: BOOLTRUE;
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: REFNIL, msg: Rope.ROPENIL] -- 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 ANYNIL,
mouseButton: Menus.MouseButton ← red, shift, control: BOOLFALSE ] -- 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: BOOLTRUE, removeMe: BOOLFALSE, include: CD.ApplicationList←NIL,
repaintMe: BOOLFALSE, repaintInclude: BOOLFALSE] -- 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.