FILE: RoseDisplayOps.Mesa
Last Edited by: Spreitzer, July 13, 1984 11:16:53 pm PDT
Last Edited by: Barth, June 9, 1983 11:19 am
DIRECTORY AMBridge, AMTypes, Atom, Buttons, HierarchicalDisplays, IO, Labels, List, MessageWindow, OrderedSymbolTableRef, PrincOps, PrincOpsUtils, Process, Rope, RoseConditions, RoseCreate, RoseDisplayInsides, RoseEvents, RoseRun, RoseStateIO, RoseTypes, TiogaOps, Trees, VFonts, ViewerClasses, ViewerIO, ViewerOps, ViewerTools, ViewRec;
RoseDisplayOps: MONITOR
IMPORTS AMBridge, AMTypes, Atom, Buttons, HierarchicalDisplays, IO, List, MessageWindow, OrderedSymbolTableRef, PrincOpsUtils, Process, Rope, RoseConditions, RoseDisplayInsides, RoseEvents, RoseRun, RoseStateIO, RoseTypes, TiogaOps, Trees, VFonts, ViewerIO, ViewerOps, ViewerTools, ViewRec
EXPORTS RoseDisplayInsides =
BEGIN OPEN RoseDisplayInsides;
IncrementalCondition: TYPE = RoseConditions.IncrementalCondition;
NamedCondition: TYPE = REF NamedConditionRep;
NamedConditionRep: TYPE = RECORD [
name: ROPE,
cond: Condition,
ic: IncrementalCondition ← NIL,
posted, postedIncrementally: BOOLEANFALSE
];
leafProp: PUBLIC ATOM ← Atom.MakeAtom["January 6, 1984 9:19 pm Spreitzer"];
treeHandler: ViewRec.SimpleHandler ← NEW [ViewRec.SimpleHandlerRep ← [
UnParse: UnParseTree,
Max: MaxTree]];
treeNodeListHandler: ViewRec.SimpleHandler ← NEW [ViewRec.SimpleHandlerRep ← [
UnParse: UnParseTreeNodeList,
Max: MaxTreeNodeList]];
stHandler: ViewRec.SimpleHandler ← NEW [ViewRec.SimpleHandlerRep ← [
UnParse: UnParseST,
Max: MaxST]];
nodeAsNode: REF Node ← NEW [Node ← NIL];
nodeAsTV: AMTypes.TypedVariable ← AMBridge.TVForReferent[nodeAsNode];
treeAsTree: REF TreeNode ← NEW [TreeNode ← NIL];
treeAsTV: AMTypes.TypedVariable ← AMBridge.TVForReferent[treeAsTree];
tnlAsTNL: REF TreeNodeList ← NEW [TreeNodeList ← NIL];
tnlAsTV: AMTypes.TypedVariable ← AMBridge.TVForReferent[tnlAsTNL];
stAsST: REF SymbolTable ← NEW [SymbolTable ← NIL];
stAsTV: AMTypes.TypedVariable ← AMBridge.TVForReferent[stAsST];
UnParseTree: ViewRec.UnParseProc = CHECKED
BEGIN
AMTypes.Assign[lhs: treeAsTV, rhs: tv];
asRope ← Trees.Format[who: treeAsTree^, style: Algebraic];
END;
MaxTree: ViewRec.MaxProc = CHECKED
{RETURN [lines: 2, maxWidthNeeded: 1024]};
RecognizeTree: ViewRec.Recognizer = CHECKED
{RETURN [TRUE, treeHandler, NIL]};
UnParseTreeNodeList: ViewRec.UnParseProc = CHECKED
BEGIN
AMTypes.Assign[lhs: tnlAsTV, rhs: tv];
asRope ← NIL;
FOR tnl: TreeNodeList ← tnlAsTNL^, tnl.rest WHILE tnl # NIL DO
this: ROPE ← Trees.Format[who: tnl.first, style: Algebraic];
asRope ← IF asRope = NIL THEN this ELSE asRope.Cat[", ", this];
ENDLOOP;
asRope ← Rope.Cat["(", asRope, ")"];
END;
MaxTreeNodeList: ViewRec.MaxProc = CHECKED
{RETURN [lines: 3, maxWidthNeeded: 1024]};
RecognizeTreeNodeList: ViewRec.Recognizer = CHECKED
{RETURN [TRUE, treeNodeListHandler, NIL]};
UnParseST: ViewRec.UnParseProc = CHECKED
BEGIN
EatIt: SAFE PROC [asAny: REF ANY] RETURNS [abort: BOOLEAN] = CHECKED
BEGIN
nc: NamedCondition ← NARROW[asAny];
abort ← FALSE;
IF asRope # NIL THEN asRope ← asRope.Concat["\n"];
asRope ← asRope.Cat[nc.name, "(", IF nc.posted THEN "p" ELSE ""].Cat[
IF nc.postedIncrementally THEN "i" ELSE "", "): ",
Trees.Format[who: nc.cond, style: Algebraic]];
END;
AMTypes.Assign[lhs: stAsTV, rhs: tv];
asRope ← NIL;
stAsST^.EnumerateIncreasing[EatIt];
END;
MaxST: ViewRec.MaxProc = CHECKED
{RETURN [lines: 5, maxWidthNeeded: 1024]};
RecognizeST: ViewRec.Recognizer = CHECKED
{RETURN [TRUE, stHandler, NIL]};
CompareNamedConditions: OrderedSymbolTableRef.CompareProc = CHECKED
BEGIN
k1, k2: ROPE;
k1 ← WITH r1 SELECT FROM
nc: NamedCondition => nc.name,
r: ROPE => r,
ENDCASE => ERROR;
k2 ← WITH r2 SELECT FROM
nc: NamedCondition => nc.name,
r: ROPE => r,
ENDCASE => ERROR;
RETURN [k1.Compare[k2]];
END;
Pack: PROC [display: Display] = {
IF display.mucking > 0 THEN display.rv.DisplayMessage["Not now"]
ELSE HierarchicalDisplays.Pack[display.rootDisplay]};
LookForChange: HierarchicalDisplays.ChildNotifyProc--PROC [child: Child]-- = TRUSTED
BEGIN
WITH child SELECT FROM
leaf: HierarchicalDisplays.Leaf => IF ISTYPE[leaf.instanceData, NodeElt] THEN BEGIN
ne: NodeElt ← NARROW[leaf.instanceData];
IF NOT ne.changed THEN RETURN;
ne.changed ← FALSE;
SELECT ne.parent.display.ctlPanel.mode FROM
Value => BEGIN
ViewerTools.SetContents[
leaf.value,
ne.format.FormatValue[
ne.node,
ne.format,
ne.node.ValWP[]]];
leaf.value.newVersion ← FALSE;
IF ne.badString THEN
BEGIN
Buttons.SetDisplayStyle[button: leaf.nameButton, style: $BlackOnWhite];
ne.badString ← FALSE;
END;
END;
Test => NULL;
ENDCASE => ERROR;
END;
in: HierarchicalDisplays.InternalNode => BEGIN
cb: CellBrowser ← NARROW[in.instanceData];
IF cb.changed THEN
BEGIN
Buttons.SetDisplayStyle[
child.nameButton,
IF cb.cell.realCellStuff.schedNext = RoseTypes.notInCellList
THEN $BlackOnWhite
ELSE IF cb.cell = cb.cell.parent.CellToStr[].schedFirst
THEN $WhiteOnBlack
ELSE $BlackOnGrey];
cb.changed ← FALSE;
END;
END;
ENDCASE => ERROR;
END;
LookForChanges: SAFE PROC [] =
CHECKED BEGIN
HierarchicalDisplays.EnumerateChildren[LookForChange];
END;
longing: INTEGER ← 0;
NoticeStart: ENTRY RoseTypes.NotifyProc = CHECKED
{IF (longing ← longing + 1) > 0 THEN trackChanges ← longIncremental};
NoticeStop: ENTRY RoseTypes.NotifyProc = CHECKED
{IF (longing ← longing - 1) < 1 AND NOT trackChanges THEN
{LookForChanges[]; trackChanges ← TRUE}};
NoticeDisplayStart: ENTRY RoseTypes.NotifyProc = CHECKED
{display: Display ← NARROW[watcherData]; display.ctlPanel.status ← Running};
NoticeDisplayInterrupt: ENTRY RoseTypes.NotifyProc = CHECKED
{display: Display ← NARROW[watcherData]; display.ctlPanel.status ← Interrupted};
NoticeDisplayStop: ENTRY RoseTypes.NotifyProc = CHECKED
{display: Display ← NARROW[watcherData]; display.ctlPanel.status ← Idle};
ActivityLogNotify: ENTRY SAFE PROC [clientData: REF ANY] --ViewRec.NotifyClientProc-- =
CHECKED BEGIN
display: Display ← NARROW[clientData];
log: BOOL ← display.ctlPanel.logActivity;
IF log # display.loggingActivity THEN {
IF log
THEN {
RoseEvents.AddWatcher[$SimpleChanged, [NotifyActivity, display]];
RoseEvents.AddWatcher[$NewSpecialSwitchInstructions, [NotifyActivity, display]];
}
ELSE {
RoseEvents.RemoveWatcher[$SimpleChanged, [NotifyActivity, display]];
RoseEvents.RemoveWatcher[$NewSpecialSwitchInstructions, [NotifyActivity, display]];
};
display.loggingActivity ← log};
END;
NotifyActivity: SAFE PROC [event: ATOM, watched, watcherData, arg: REF ANY] --RoseTypes.NotifyProc-- =
CHECKED BEGIN
display: Display ← NARROW[watcherData];
ar: RoseRun.ActivityReport ← NARROW[arg];
display.log.PutF["%g.%g(=%g.%g)", IO.rope[LongName[ar.socket.cell]], IO.rope[ar.socket.cell.class.ports[ar.socket.index].name], IO.rope[LongName[ar.node.cellIn]], IO.rope[ar.node.name]];
SELECT event FROM
$SimpleChanged => {
fmt: RoseTypes.Format ← ar.node.type.procs.GetFormat[ar.node.type, ""];
display.log.PutF[" ← %g\n", IO.rope[fmt.FormatValue[ar.node, fmt, RoseTypes.SocketToWP[ar.socket]]]];
};
$NewSpecialSwitchInstructions => display.log.PutRope[" got new instructions\n"];
ENDCASE => ERROR;
END;
LongName: SAFE PROC [cell: Cell] RETURNS [ln: ROPE] = CHECKED {
ln ← cell.name;
FOR cell ← cell.parent, cell.parent WHILE cell # NIL DO
ln ← cell.name.Cat[".", ln];
ENDLOOP};
NotifyNodeUD: PUBLIC SAFE PROC [event: ATOM, watched, watcherData, arg: REF ANY] --RoseTypes.NotifyProc-- = CHECKED
BEGIN
node: Node ← NARROW[watched];
cell: Cell ← NARROW[arg];
display: Display ← NARROW[watcherData];
fmt: RoseTypes.Format ← node.type.procs.GetFormat[node.type, "UD"];
IF event # $NewNodeUD THEN ERROR;
display.log.PutF["New UD for %g", IO.rope[LongName[node.cellIn].Cat[".", node.name]]];
IF cell # NIL THEN display.log.PutF[" from %g", IO.rope[LongName[cell]]];
IF fmt # NIL THEN display.log.PutF[":%g", IO.rope[fmt.FormatValue[node, fmt, NIL]]];
display.log.PutRope["\n"];
END;
IncrNotify: ENTRY SAFE PROC [clientData: REF ANY] --ViewRec.NotifyClientProc-- =
CHECKED BEGIN
display: Display ← NARROW[clientData];
IF display.ctlPanel.incrementalDisplay = longIncremental THEN RETURN;
longIncremental ← display.ctlPanel.incrementalDisplay;
IF longing > 0 AND trackChanges # longIncremental THEN
{IF (trackChanges ← longIncremental) THEN LookForChanges[]};
RoseEvents.Notify[event: setIncrementalDisplay, handleAborted: TRUE];
END;
longIncremental: BOOLEANFALSE;
trackChanges: BOOLEANTRUE;
setIncrementalDisplay: ATOM ← Atom.MakeAtom["Spreitzer January 6, 1984 9:19 pm"];
NoticeSetIncrementalDisplay: RoseTypes.NotifyProc =
CHECKED BEGIN
display: Display ← NARROW[watcherData];
display.ctlPanel.incrementalDisplay ← longIncremental;
END;
TiogaNoticeEdit: TiogaOps.CommandProc --PROC [viewer: Viewer ← NIL] RETURNS [recordAtom: BOOL ← TRUE, quit: BOOL ← FALSE]-- = TRUSTED
BEGIN
asAny: REF ANY ← ViewerOps.FetchProp[viewer: viewer, prop: leafProp];
IF (IF asAny = NIL THEN TRUE ELSE NOT ISTYPE[asAny, HierarchicalDisplays.Leaf]) THEN RETURN [recordAtom: FALSE, quit: FALSE];
recordAtom ← FALSE; quit ← TRUE;
[] ← NoticeEdit[NARROW[asAny]];
END;
NoticeEdit: PROC [leaf: HierarchicalDisplays.Leaf] RETURNS [success: BOOLEAN] =
BEGIN
ne: NodeElt ← NARROW[leaf.instanceData];
SELECT ne.parent.display.ctlPanel.mode FROM
Value => BEGIN
ModifyIt: RoseRun.ModifyProc--PROC [cell: Cell] RETURNS [subtle: BOOLEAN ← FALSE]-- = CHECKED
BEGIN
ts: IO.STREAMIO.RIS[ViewerTools.GetContents[leaf.value]];
wp ← ne.node.ValWP[];
success ← ne.format.ParseValue[ne.node, ne.format, wp, ts];
ts.Close[];
END;
wp: RoseTypes.WordPtr;
IF ne.node.visible.cell = NIL THEN ERROR;
ViewerTools.InhibitUserEdits[leaf.value];
IF ne.node.type.simple THEN
RoseRun.AllowToModify[cell: ne.node.visible.cell, modifier: ModifyIt, mayRescheduleSelf: TRUE]
ELSE {
[] ← ModifyIt[NIL];
IF success THEN RoseRun.ValueChanged[ne.node]};
Buttons.SetDisplayStyle[leaf.nameButton, IF success THEN $BlackOnWhite ELSE $WhiteOnBlack];
IF success THEN
BEGIN
leaf.value.newVersion ← FALSE;
--VT.SetContents[leaf.value, ne.format.FormatValue[ne.node.type, ne.format, wp]];--
END;
ViewerTools.EnableUserEdits[leaf.value];
IF NOT success THEN leaf.value.newVersion ← TRUE;
END;
Test => BEGIN
tp: RoseTypes.NodeTestProc;
td: REF ANY;
ts: IO.STREAM;
ViewerTools.InhibitUserEdits[leaf.value];
ts ← IO.RIS[ViewerTools.GetContents[leaf.value]];
[success, tp, td] ← ne.format.ParseTest[ne.node.type, ne.format, ts];
ts.Close[];
Buttons.SetDisplayStyle[leaf.nameButton, IF success THEN $BlackOnWhite ELSE $WhiteOnBlack];
IF success THEN
BEGIN
ne.testData ← td;
ne.testProc ← tp;
--VT.SetContents[leaf.value, ne.format.FormatTest[ne.node.type, ne.format, tp, td]];--
leaf.value.newVersion ← FALSE;
END;
ViewerTools.EnableUserEdits[leaf.value];
IF NOT success THEN leaf.value.newVersion ← TRUE;
END;
ENDCASE => ERROR;
ne.badString ← NOT success;
END;
NoticeEdits: PROC [display: Display] RETURNS [AOK: BOOLEAN] =
BEGIN
Notice: HierarchicalDisplays.ChildNotifyProc = TRUSTED
BEGIN
IF NOT NoticeEdit[NARROW[child]] THEN AOKFALSE;
END;
AOKTRUE;
HierarchicalDisplays.EnumerateChildren[to: Notice, internals: FALSE, changedOnly: TRUE];
END;
Interrupt: PROC [display: Display] = {RoseRun.stop ← TRUE};
Disable: PROC [display: Display] RETURNS [ok: BOOL] =
BEGIN
fh: PrincOps.FrameHandle ← display.stopped;
ok ← (fh # NIL) AND RoseRun.DisableThisStop[fh];
END;
Proceed: PROC [display: Display] =
BEGIN
Inner: ENTRY PROC = {
display.stopResponse ← Resume;
display.ctlPanel.status ← Running;
BROADCAST display.notice;
};
IF NoticeEdits[display] THEN Inner[];
END;
Abort: PROC [display: Display] =
BEGIN
Inner: ENTRY PROC = {
display.stopResponse ← Abort;
display.ctlPanel.status ← Running;
BROADCAST display.notice;
};
IF NoticeEdits[display] THEN Inner[];
END;
GetStopResponse: SAFE PROC [display: Display, msg: ROPE, data: REF ANY] RETURNS [sr: StopResponse] = CHECKED
BEGIN
RoseEvents.Notify[event: $Interrupt, handleAborted: TRUE];
sr ← ReallyGetStopResponse[display, msg, data];
RoseEvents.Notify[event: $Start, handleAborted: TRUE];
END;
ReallyGetStopResponse: ENTRY SAFE PROC [display: Display, msg: ROPE, data: REF ANY] RETURNS [sr: StopResponse] = CHECKED
BEGIN ENABLE UNWIND => {};
IF display.ctlPanel.status # Interrupted THEN ERROR;
TRUSTED {display.stopped ← PrincOpsUtils.MyLocalFrame[]};
display.rv.DisplayMessage[msg];
WHILE display.ctlPanel.status = Interrupted DO
WAIT display.notice;
ENDLOOP;
RoseRun.stop ← FALSE;
sr ← display.stopResponse;
display.stopped ← NIL;
END;
Run: PROC [display: Display] =
BEGIN
IF NOT NoticeEdits[display] THEN RETURN;
RoseEvents.Notify[event: $Start, handleAborted: TRUE];
BEGIN ENABLE
BEGIN
RoseTypes.Stop => CHECKED
BEGIN
SELECT GetStopResponse[display, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END;
UNWIND => RoseEvents.Notify[event: $Stop, handleAborted: TRUE];
END;
IF display.type = Ordinary THEN RoseRun.Run[display.sim] ELSE RoseRun.Test[sim: display.sim, cth: display.cth, parms: display.parms];
END;
RoseEvents.Notify[event: $Stop, handleAborted: TRUE];
END;
SingleStep: PROC [display: Display] RETURNS [stepType: RoseRun.StepType] =
BEGIN
IF display.type = Test
THEN {display.rv.DisplayMessage["Can't single-step a CellTest"]; RETURN};
IF NOT NoticeEdits[display] THEN RETURN;
RoseEvents.Notify[event: $Start, handleAborted: TRUE];
stepType ← RoseRun.StepSim[display.sim
!RoseTypes.Stop => CHECKED
BEGIN
SELECT GetStopResponse[display, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END;
UNWIND => RoseEvents.Notify[event: $Stop, handleAborted: TRUE]];
RoseEvents.Notify[event: $Stop, handleAborted: TRUE];
END;
PathNameToPath: PROC [pathName: ROPE] RETURNS [path: LIST OF ROPE] =
BEGIN
dotIndex: INT;
last: LIST OF ROPELIST[pathName];
path ← last;
WHILE (dotIndex ← last.first.Find["."]) >= 0 DO
last.rest ← LIST[last.first.Substr[dotIndex+1, last.first.Length[] - (dotIndex+1)]];
last.first ← last.first.Substr[0, dotIndex];
last ← last.rest;
ENDLOOP;
END;
SetMode: PROC [display: Display, mode: DisplayMode] =
BEGIN
SetValue: HierarchicalDisplays.ChildNotifyProc = TRUSTED
BEGIN
leaf: HierarchicalDisplays.Leaf ← NARROW[child];
WITH leaf.instanceData SELECT FROM
ne: NodeElt => BEGIN
val: ROPE ← ne.format.FormatValue[ne.node, ne.format, ne.node.ValWP[]];
ViewerTools.InhibitUserEdits[leaf.value];
ViewerTools.SetContents[leaf.value, val];
leaf.value.newVersion ← FALSE;
ViewerTools.EnableUserEdits[leaf.value];
Buttons.SetDisplayStyle[leaf.nameButton, $BlackOnWhite];
ne.badString ← FALSE;
END;
cs: CellState => NULL;
ENDCASE => ERROR;
END;
SetTest: HierarchicalDisplays.ChildNotifyProc = TRUSTED
BEGIN
leaf: HierarchicalDisplays.Leaf ← NARROW[child];
WITH leaf.instanceData SELECT FROM
ne: NodeElt => BEGIN
val: ROPE ← ne.format.FormatTest[ne.node.type, ne.format, ne.testProc, ne.testData];
ViewerTools.InhibitUserEdits[leaf.value];
ViewerTools.SetContents[leaf.value, val];
leaf.value.newVersion ← FALSE;
ViewerTools.EnableUserEdits[leaf.value];
Buttons.SetDisplayStyle[leaf.nameButton, $BlackOnWhite];
ne.badString ← FALSE;
END;
cs: CellState => NULL;
ENDCASE => ERROR;
END;
HierarchicalDisplays.EnumerateChildren[to: IF mode = Value THEN SetValue ELSE SetTest, internals: FALSE];
END;
ModeNotify: ViewRec.NotifyClientProc = TRUSTED
{display: Display ← NARROW[clientData];
SetMode[display, display.ctlPanel.mode]};
ClearStack: PROC [display: Display] =
{display.ctlPanel.conditionStack ← NIL};
ClearCondition: PROC [display: Display] =
{display.ctlPanel.condition ← NIL};
GetCondition: PROC [display: Display] RETURNS [nc: NamedCondition] =
BEGIN
name: ROPE ← ViewerTools.GetSelectionContents[];
asAny: REF ANY;
IF name.Length[] < 1 THEN RETURN [NIL];
asAny ← display.ctlPanel.conditions.Lookup[name];
nc ← NARROW[asAny];
END;
PostCondition: PROC [display: Display] =
BEGIN
nc: NamedCondition ← GetCondition[display];
IF nc = NIL THEN {display.rv.DisplayMessage["Select a condition name"]; RETURN};
IF nc.posted THEN {display.rv.DisplayMessage["Already posted!"]; RETURN};
nc.posted ← TRUE;
RoseConditions.PostOnCell[
cell: display.rootCell,
condition: nc.cond];
ViewRec.RedisplayElt[display.conditionsHandle];
END;
RemoveCondition: PROC [display: Display] =
BEGIN
nc: NamedCondition ← GetCondition[display];
IF nc = NIL THEN {display.rv.DisplayMessage["Select a condition name"]; RETURN};
RoseConditions.UnPostOnCell[
cell: display.rootCell,
condition: nc.cond];
nc.posted ← FALSE;
ViewRec.RedisplayElt[display.conditionsHandle];
END;
PostIncremental: PROC [display: Display] =
BEGIN
nc: NamedCondition ← GetCondition[display];
IF nc = NIL THEN {display.rv.DisplayMessage["Select a condition name"]; RETURN};
IF nc.postedIncrementally THEN {display.rv.DisplayMessage["Already posted incrementally!"]; RETURN};
nc.postedIncrementally ← TRUE;
nc.ic ← RoseConditions.PostIncrementally[nc.cond];
ViewRec.RedisplayElt[display.conditionsHandle];
END;
RemoveIncremental: PROC [display: Display] =
BEGIN
nc: NamedCondition ← GetCondition[display];
IF nc = NIL THEN {display.rv.DisplayMessage["Select a condition name"]; RETURN};
IF NOT nc.postedIncrementally THEN {display.rv.DisplayMessage["Not posted incrementally!"]; RETURN};
RoseConditions.UnPostIncrementally[nc.ic];
nc.ic ← NIL;
nc.postedIncrementally ← FALSE;
ViewRec.RedisplayElt[display.conditionsHandle];
END;
AddNamedCondition: PROC [display: Display, name: ROPE] =
BEGIN
nc: NamedCondition;
nc ← NEW [NamedConditionRep ← [
name: name,
cond: display.ctlPanel.condition]];
IF nc.cond = NIL THEN {display.rv.DisplayMessage["empty condition!"]; RETURN};
IF name.Length[] < 1 THEN {display.rv.DisplayMessage["empty name!"]; RETURN};
IF display.ctlPanel.conditions.Lookup[name] # NIL THEN {display.rv.DisplayMessage["already exists!"]; RETURN};
display.ctlPanel.conditions.Insert[nc];
display.ctlPanel.condition ← NIL;
ViewRec.RedisplayElt[display.conditionsHandle];
END;
DeleteNamedCondition: PROC [display: Display, name: ROPE ] =
BEGIN
old: REF ANY;
IF name.Length[] < 1 THEN {display.rv.DisplayMessage["empty name!"]; RETURN};
IF display.ctlPanel.conditions.Lookup[name] = NIL THEN {display.rv.DisplayMessage["not found"]; RETURN};
IF (old ← display.ctlPanel.conditions.Delete[name]) = NIL THEN ERROR;
END;
NewDisplay: PROC [sim: RoseTypes.Simulation, info: ViewerClasses.ViewerRec ← [], cth: RoseTypes.CellTestHandle ← NIL, paint: BOOLEANTRUE] RETURNS [display: Display] =
BEGIN
OtherStuff: ViewRec.OtherStuffProc--PROC [in: Viewer] RETURNS [stuff: LIST OF Viewer]-- = CHECKED
BEGIN
stuff ← IF display.type = Test
THEN LIST[ViewRec.RVQuaViewer[ViewRec.ViewRef[
agg: display.parms ← NEW [RoseRun.TestParmsRep ← []],
createOptions: [mayInitiateRelayout: FALSE, feedBackHeight: 0],
viewerInit: [parent: in],
paint: FALSE]]]
ELSE NIL;
END;
rvv: Viewer;
ctlPanel: ControlPanel ← NEW [ControlPanelRep ← [
conditions: OrderedSymbolTableRef.CreateTable[CompareNamedConditions],
incrementalDisplay: longIncremental,
Pack: Pack,
NoticeEdits: NoticeEdits,
Run: Run,
SingleStep: SingleStep,
Interrupt: Interrupt,
Disable: Disable,
Proceed: Proceed,
Abort: Abort,
ClearStack: ClearStack,
ClearCondition: ClearCondition,
Or: Or,
PostCondition: PostCondition,
RemoveCondition: RemoveCondition,
PostIncremental: PostIncremental,
RemoveIncremental: RemoveIncremental,
AddNamedCondition: AddNamedCondition,
DeleteNamedCondition: DeleteNamedCondition,
Save: Save,
Restore: Restore]];
display ← NEW [DisplayRep ← [
sim: sim,
rootCell: sim.root,
cth: cth,
type: IF cth = NIL THEN Ordinary ELSE Test,
ctlPanel: ctlPanel,
log: ViewerIO.CreateViewerStreams[name: sim.root.name.Concat[" log"]].out,
conditionHandle: NIL,
conditionsHandle: NIL,
rootDisplay: HierarchicalDisplays.CreateRoot[
viewerInit: [
parent: NIL,
iconic: FALSE,
scrollable: TRUE,
name: sim.root.name.Cat[".display"]],
paint: paint],
rv: NIL]];
display.rv ← ViewRec.ViewRef[
agg: ctlPanel,
specs: ViewRec.BindingListAppend[
LIST[
["mode", Notify[notify: ModeNotify, clientData: display]],
["incrementalDisplay", Notify[notify: IncrNotify, clientData: display]],
["logActivity", Notify[notify: ActivityLogNotify, clientData: display]],
["conditionStack", TryRecognizer[RecognizeTreeNodeList]],
["condition", TryRecognizer[RecognizeTree]],
["conditions", TryRecognizer[RecognizeST]],
["status", Value[val: NIL, visible: TRUE, dontAssign: TRUE]] ] ,
ViewRec.BindAllOfATypeFromRefs[rec: ctlPanel, handle: NEW [Display ← display]] ],
otherStuff: OtherStuff,
createOptions: [exclusiveProcs: FALSE],
viewerInit: [parent: NIL, iconic: FALSE, scrollable: TRUE, name: sim.root.name.Cat[".ops"]],
paint: paint];
rvv ← ViewRec.RVQuaViewer[display.rv];
display.conditionHandle ← display.rv.GetEltHandle[LIST["condition"]];
display.conditionsHandle ← display.rv.GetEltHandle[LIST["conditions"]];
Process.InitializeCondition[
condition: @display.notice,
ticks: Process.SecondsToTicks[5]];
RoseEvents.AddWatcher[event: setIncrementalDisplay, watcher: [NoticeSetIncrementalDisplay, display]];
RoseEvents.AddWatcher[event: $Stop, watcher: [NoticeDisplayStop, display]];
RoseEvents.AddWatcher[event: $Interrupt, watcher: [NoticeDisplayInterrupt, display]];
RoseEvents.AddWatcher[event: $Start, watcher: [NoticeDisplayStart, display]];
END;
cellClass: PUBLIC HierarchicalDisplays.ChildClass ← NEW [HierarchicalDisplays.ChildClassRep ← [
buttonProc: DullButtonProc,
NotifyOnRemove: NoticeCellRemoval]];
nodeClass: PUBLIC HierarchicalDisplays.ChildClass ← NEW [HierarchicalDisplays.ChildClassRep ← [
buttonProc: DullButtonProc,
NotifyOnRemove: NoticeNodeRemoval]];
DullButtonProc: Buttons.ButtonProc = TRUSTED
BEGIN
leaf: HierarchicalDisplays.Leaf;
ne: NodeElt;
IF (IF clientData = NIL THEN TRUE ELSE NOT ISTYPE[clientData, HierarchicalDisplays.Leaf]) THEN
BEGIN
MessageWindow.Append[message: "Don't do that", clearFirst: TRUE];
RETURN;
END;
leaf ← NARROW[clientData];
ne ← NARROW[leaf.instanceData];
SELECT mouseButton FROM
red => ViewerTools.SetSelection[leaf.value];
yellow => IF control THEN SetFormat[ne, leaf] ELSE AddAnd[ne, shift];
blue => IF control THEN TellFormat[ne] ELSE AddOr[ne, shift];
ENDCASE => ERROR;
END;
TellFormat: PROC [ne: NodeElt] =
BEGIN
ne.org.display.rv.DisplayMessage[ViewRec.clearMessagePlace];
ne.org.display.rv.DisplayMessage[IO.PutFR[
"Current format is %g, choices are %g",
IO.refAny[ne.format.key],
IO.refAny[ne.node.type.procs.ListFormats[ne.node.type]]]];
END;
SetFormat: PROC [ne: NodeElt, leaf: HierarchicalDisplays.Leaf] =
BEGIN
fmtKey: ROPE ← ViewerTools.GetSelectionContents[];
fmt: RoseTypes.Format ← ne.node.type.procs.GetFormat[ne.node.type, fmtKey];
IF fmt # NIL THEN {
ne.format ← fmt;
TellFormat[ne];
NotifyNodeView[$NewFormat, ne.node, leaf, NIL];
ViewerOps.MoveViewer[viewer: leaf.value,
x: leaf.value.wx, y: leaf.value.wy,
w: ne.format.MaxWidth[ne.node.type, ne.format, VFonts.defaultFont] + 20,
h: leaf.value.wh, paint: FALSE];
}
ELSE {
ne.org.display.rv.DisplayMessage[ViewRec.clearMessagePlace];
ne.org.display.rv.DisplayMessage[IO.PutFR[
"Format %g unrecognized",
IO.refAny[fmtKey]]]};
END;
AddOr: PROC [ne: NodeElt, invert: BOOLEAN] =
BEGIN
display: Display ← ne.org.display;
nt: RoseConditions.NodeTest ← NEW [RoseConditions.NodeTestRep ← [
node: ne.node,
nodeName: ne.name,
nodeFormat: ne.format,
cell: ne.org.socket.cell,
testData: ne.testData,
testProc: ne.testProc]];
leaf: TreeNode ← Trees.Leaf[nt, RoseConditions.test];
IF nt.testProc = NIL THEN {display.rv.DisplayMessage["invalid test"]; RETURN};
IF invert THEN leaf ← Trees.Not[leaf];
Push[display, Pop[display].Or[display.ctlPanel.condition]];
display.ctlPanel.condition ← leaf;
END;
AddAnd: PROC [ne: NodeElt, invert: BOOLEAN] =
BEGIN
display: Display ← ne.org.display;
nt: RoseConditions.NodeTest ← NEW [RoseConditions.NodeTestRep ← [
node: ne.node,
nodeName: ne.name,
nodeFormat: ne.format,
cell: ne.org.socket.cell,
testData: ne.testData,
testProc: ne.testProc]];
leaf: TreeNode ← Trees.Leaf[nt, RoseConditions.test];
IF nt.testProc = NIL THEN {display.rv.DisplayMessage["invalid test"]; RETURN};
IF invert THEN leaf ← Trees.Not[leaf];
display.ctlPanel.condition ← Trees.And[display.ctlPanel.condition, leaf];
ViewRec.RedisplayElt[display.conditionHandle];
END;
NoticeCellRemoval: HierarchicalDisplays.ChildNotifyProc = CHECKED
BEGIN
cb: CellBrowser ← NARROW[child.instanceData];
cb.cell.props ← List.PutAssoc[key: cb.display, val: NIL, aList: cb.cell.props];
IF cb.cell.type = Real THEN RoseEvents.RemoveWatcher[watched: cb.cell, event: $Schedule, watcher: [NotifyCellView, child]];
END;
NoticeNodeRemoval: HierarchicalDisplays.ChildNotifyProc = TRUSTED
BEGIN
ne: NodeElt ← NARROW[child.instanceData];
displays: NodeDisplayList ← NARROW[List.Assoc[key: nodeDisplaysProp, aList: ne.node.props]];
nd: NodeDisplay;
found: BOOLEAN;
leaf: HierarchicalDisplays.Leaf ← NARROW[child];
[displays, nd, found] ← NDLSearch[ndl: displays, org: ne.org, remove: TRUE];
IF (IF found THEN nd.dc # child ELSE TRUE) THEN ERROR;
ne.node.props ← List.PutAssoc[key: nodeDisplaysProp, val: displays, aList: ne.node.props];
RoseEvents.RemoveWatcher[watched: ne.node, watcher: [NotifyNodeView, leaf], event: $ChangeEarly];
END;
NotifyNodeView: PUBLIC RoseTypes.NotifyProc = TRUSTED
BEGIN
node: Node ← NARROW[watched];
leaf: HierarchicalDisplays.Leaf ← NARROW[watcherData];
ne: NodeElt ← NARROW[leaf.instanceData];
v: Viewer ← leaf.value;
val: ROPE;
IF ne.org.display.ctlPanel.mode # Value THEN RETURN;
IF NOT trackChanges THEN {ne.changed ← TRUE; RETURN};
IF ne.badString THEN
BEGIN
Buttons.SetDisplayStyle[button: leaf.nameButton, style: $BlackOnWhite];
ne.badString ← FALSE;
END;
val ← ne.format.FormatValue[node, ne.format, node.ValWP[]];
ViewerTools.SetContents[v, val];
END;
NotifyCellView: PUBLIC RoseTypes.NotifyProc = TRUSTED
BEGIN
cell: Cell ← NARROW[watched];
dc: HierarchicalDisplays.Child ← NARROW[watcherData];
IF trackChanges THEN Buttons.SetDisplayStyle[dc.nameButton, IF cell.realCellStuff.schedNext = RoseTypes.notInCellList THEN $BlackOnWhite ELSE IF cell = cell.parent.CellToStr[].schedFirst THEN $WhiteOnBlack ELSE $BlackOnGrey]
ELSE NARROW[dc.instanceData, CellBrowser].changed ← TRUE;
END;
Or: PROC [display: Display] =
{display.ctlPanel.condition ← Pop[display].Or[display.ctlPanel.condition]};
Push: PUBLIC PROC [display: Display, cond: Condition] =
{display.ctlPanel.conditionStack ← CONS[cond, display.ctlPanel.conditionStack]};
Pop: PUBLIC PROC [display: Display] RETURNS [cond: Condition] =
BEGIN
IF display.ctlPanel.conditionStack = NIL THEN RETURN [NIL];
cond ← display.ctlPanel.conditionStack.first;
display.ctlPanel.conditionStack ← display.ctlPanel.conditionStack.rest;
END;
Save: PROC [display: Display, fileName: ROPE] RETURNS [errMsg: ROPE] =
{IF NOT NoticeEdits[display] THEN RETURN ["Invalid edits not yet fixed"];
errMsg ← RoseStateIO.Save[display.rootCell, fileName]};
Restore: PROC [display: Display, fileName: ROPE] RETURNS [errMsg: ROPE] =
{errMsg ← RoseStateIO.Restore[display.rootCell, fileName]};
Setup: PROC =
BEGIN
TiogaOps.RegisterCommand[name: $InsertLineBreak, proc: TiogaNoticeEdit];
RoseEvents.AddWatcher[event: $Stop, watcher: [NoticeStop]];
RoseEvents.AddWatcher[event: $Interrupt, watcher: [NoticeStop]];
RoseEvents.AddWatcher[event: $Start, watcher: [NoticeStart]];
END;
Setup[];
END.