FILE: RoseDisplayOps.Mesa
Last Edited by: Spreitzer, November 28, 1983 2:16 pm
Last Edited by: Barth, November 28, 1983 2:39 pm
DIRECTORY
AMTypes, AMBridge, Atom, Browsers, Buttons, List, ViewerClasses, ViewerTools, Labels, Rope, IO, OrderedSymbolTableRef, HierarchicalDisplays, MessageWindow, Process, Rosemary, RoseConditions, RoseDisplayInsides, RoseStateIO, TiogaOps, Trees, VFonts, ViewerHelp, ViewerOps, ViewRec;
RoseDisplayOps: MONITOR
IMPORTS AMTypes, AMBridge, Atom, Buttons, Rope, VT: ViewerTools, HD: HierarchicalDisplays, List, MessageWindow, OSTR: OrderedSymbolTableRef, Process, Rosemary, RC: RoseConditions, RoseDisplayInsides, RoseStateIO, TiogaOps, Trees, ViewerHelp, ViewerOps, VR: 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.Gensym[];
treeHandler: VR.SimpleHandler ← NEW [VR.SimpleHandlerRep ← [
UnParse: UnParseTree,
Max: MaxTree]];
treeNodeListHandler: VR.SimpleHandler ← NEW [VR.SimpleHandlerRep ← [
UnParse: UnParseTreeNodeList,
Max: MaxTreeNodeList]];
stHandler: VR.SimpleHandler ← NEW [VR.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: VR.UnParseProc = CHECKED
BEGIN
AMTypes.Assign[lhs: treeAsTV, rhs: tv];
asRope ← Trees.Format[who: treeAsTree^, style: Algebraic];
END;
MaxTree: VR.MaxProc = CHECKED
{RETURN [lines: 2, maxWidthNeeded: 1024]};
RecognizeTree: VR.Recognizer = CHECKED
{RETURN [TRUE, treeHandler, NIL]};
UnParseTreeNodeList: VR.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: VR.MaxProc = CHECKED
{RETURN [lines: 3, maxWidthNeeded: 1024]};
RecognizeTreeNodeList: VR.Recognizer = CHECKED
{RETURN [TRUE, treeNodeListHandler, NIL]};
UnParseST: VR.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\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: VR.MaxProc = CHECKED
{RETURN [lines: 10, maxWidthNeeded: 1024]};
RecognizeST: VR.Recognizer = CHECKED
{RETURN [TRUE, stHandler, NIL]};
CompareNamedConditions: OSTR.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] =
{HD.Pack[display.rootDisplay]};
LookForChange: HD.ChildNotifyProc--PROC [child: Child]-- = TRUSTED
BEGIN
WITH child SELECT FROM
leaf: HD.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
VT.SetContents[
leaf.value,
ne.node.type.toRope[
where: ne.node.visible.SocketToWP[],
typeData: ne.node.type.typeData]];
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: HD.InternalNode => BEGIN
cb: CellBrowser ← NARROW[in.instanceData];
IF cb.changed THEN
BEGIN
Buttons.SetDisplayStyle[
child.nameButton,
IF cb.cell.realCellStuff.schedNext = Rosemary.notInSchedule
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
HD.EnumerateChildren[LookForChange];
END;
longing: INTEGER ← 0;
NoticeStart: ENTRY Rosemary.GlobalNotifyProc = CHECKED
{IF (longing ← longing + 1) > 0 THEN trackChanges ← longIncremental};
NoticeStop: ENTRY Rosemary.GlobalNotifyProc = CHECKED
{IF (longing ← longing - 1) < 1 AND NOT trackChanges THEN
{LookForChanges[]; trackChanges ← TRUE}};
IncrNotify: ENTRY ViewRec.NotifyClientProc--PROC [clientData: REF ANY]-- =
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[]};
Rosemary.NotifyGlobalEvent[setIncrementalDisplay];
END;
longIncremental: BOOLEANFALSE;
trackChanges: BOOLEANTRUE;
setIncrementalDisplay: ATOM ← Atom.Gensym[];
NoticeSetIncrementalDisplay: Rosemary.GlobalNotifyProc =
CHECKED BEGIN
display: Display ← NARROW[clientData];
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, HD.Leaf]) THEN RETURN [recordAtom: FALSE, quit: FALSE];
recordAtom ← FALSE; quit ← TRUE;
[] ← NoticeEdit[NARROW[asAny]];
END;
NoticeEdit: PROC [leaf: HD.Leaf] RETURNS [success: BOOLEAN] =
BEGIN
ne: NodeElt ← NARROW[leaf.instanceData];
SELECT ne.parent.display.ctlPanel.mode FROM
Value => BEGIN
ModifyIt: Rosemary.ModifyProc = TRUSTED
BEGIN
wp ← ne.node.visible.SocketToWP[];
success ← ne.node.type.fromRope[rope: VT.GetContents[leaf.value], where: wp, typeData: ne.node.type.typeData];
END;
wp: Rosemary.WordPtr;
IF ne.node.visible.cell = NIL THEN ERROR;
VT.InhibitUserEdits[leaf.value];
Rosemary.AllowToModify[cell: ne.node.visible.cell, modifier: ModifyIt];
Buttons.SetDisplayStyle[leaf.nameButton, IF success THEN $BlackOnWhite ELSE $WhiteOnBlack];
IF success THEN
BEGIN
leaf.value.newVersion ← FALSE;
VT.SetContents[leaf.value, ne.node.type.toRope[where: wp, typeData: ne.node.type.typeData]];
END;
VT.EnableUserEdits[leaf.value];
IF NOT success THEN leaf.value.newVersion ← TRUE;
END;
Test => BEGIN
tp: Rosemary.TestProc;
td: REF ANY;
VT.InhibitUserEdits[leaf.value];
[success, tp, td] ← ne.node.type.parseTest[rope: VT.GetContents[leaf.value], typeData: ne.node.type.typeData];
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.node.type.unParseTest[testProc: tp, testData: td, typeData: ne.node.type.typeData, subject: NIL]];
leaf.value.newVersion ← FALSE;
END;
VT.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: HD.ChildNotifyProc = TRUSTED
BEGIN
IF NOT NoticeEdit[NARROW[child]] THEN AOKFALSE;
END;
AOKTRUE;
HD.EnumerateChildren[to: Notice, internals: FALSE, changedOnly: TRUE];
END;
Interrupt: PROC [display: Display] = {Rosemary.stop ← TRUE};
Proceed: ENTRY PROC [display: Display] =
BEGIN
display.stopResponse ← Resume;
display.ctlPanel.status ← Normal;
BROADCAST display.notice;
END;
Abort: ENTRY PROC [display: Display] =
BEGIN
display.stopResponse ← Abort;
display.ctlPanel.status ← Normal;
BROADCAST display.notice;
END;
GetStopResponse: SAFE PROC [display: Display, msg: ROPE, data: REF ANY] RETURNS [sr: StopResponse] = CHECKED
BEGIN
Rosemary.NotifyGlobalEvent[$Stop];
sr ← ReallyGetStopResponse[display, msg, data];
Rosemary.NotifyGlobalEvent[$Start];
END;
ReallyGetStopResponse: ENTRY SAFE PROC [display: Display, msg: ROPE, data: REF ANY] RETURNS [sr: StopResponse] = CHECKED
BEGIN
display.ctlPanel.status ← Interrupted;
display.rv.DisplayMessage[msg];
WHILE display.ctlPanel.status = Interrupted DO
WAIT display.notice;
ENDLOOP;
Rosemary.stop ← FALSE;
sr ← display.stopResponse;
END;
Run: PROC [display: Display] =
BEGIN
Rosemary.NotifyGlobalEvent[$Start];
Rosemary.Run[Rosemary.CellToStr[display.rootCell]
!Rosemary.Stop => CHECKED
BEGIN
SELECT GetStopResponse[display, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END;
UNWIND => Rosemary.NotifyGlobalEvent[$Stop]];
Rosemary.NotifyGlobalEvent[$Stop];
END;
SingleStep: PROC [display: Display] =
BEGIN
Rosemary.NotifyGlobalEvent[$Start];
Rosemary.SingleStep[Rosemary.CellToStr[display.rootCell]
!Rosemary.Stop => CHECKED
BEGIN
SELECT GetStopResponse[display, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END;
UNWIND => Rosemary.NotifyGlobalEvent[$Stop]];
Rosemary.NotifyGlobalEvent[$Stop];
END;
Test: PROC [display: Display, cellPathName: ROPE] =
BEGIN
Rosemary.NotifyGlobalEvent[$Start];
Rosemary.Test[Rosemary.LookupCell[from: display.rootCell, path: PathNameToPath[cellPathName]], display.parms
!Rosemary.Stop => CHECKED
BEGIN
SELECT GetStopResponse[display, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END;
UNWIND => Rosemary.NotifyGlobalEvent[$Stop]];
Rosemary.NotifyGlobalEvent[$Stop];
END;
ListSchedule: PROC [display: Display] RETURNS [asRope: ROPE] =
BEGIN
Work: PROC [str: Rosemary.Structure] RETURNS [asRope: ROPE] =
BEGIN
asRope ← NIL;
FOR sc: Cell ← str.schedFirst, sc.realCellStuff.schedNext WHILE sc # NIL DO
IF asRope # NIL THEN asRope ← asRope.Cat[", "];
asRope ← asRope.Cat[CellPathName[sc]];
IF sc.realCellStuff.state # NIL AND ISTYPE[sc.realCellStuff.state, Rosemary.Structure] THEN asRope ← asRope.Cat["(", Work[NARROW[sc.realCellStuff.state]], ")"];
ENDLOOP;
END;
str: Rosemary.Structure ← Rosemary.CellToStr[display.rootCell];
asRope ← Work[str];
END;
CellPathName: PROC [cell: Cell] RETURNS [cellPathName: ROPE] =
BEGIN
cellPathName ← cell.name;
FOR cell ← cell.parent, cell.parent WHILE cell # NIL DO
cellPathName ← cell.name.Cat[".", cellPathName];
ENDLOOP;
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;
NoticeEditsAndRunIfOK: PROC [display: Display] RETURNS [AOK: BOOLEAN] =
BEGIN
IF (AOK ← NoticeEdits[display]) THEN Run[display];
END;
SetMode: PROC [display: Display, mode: DisplayMode] =
BEGIN
SetValue: HD.ChildNotifyProc = TRUSTED
BEGIN
leaf: HD.Leaf ← NARROW[child];
WITH leaf.instanceData SELECT FROM
ne: NodeElt => BEGIN
val: ROPE ← ne.node.type.toRope[where: ne.node.visible.SocketToWP[], typeData: ne.node.type.typeData];
VT.InhibitUserEdits[leaf.value];
VT.SetContents[leaf.value, val];
leaf.value.newVersion ← FALSE;
VT.EnableUserEdits[leaf.value];
Buttons.SetDisplayStyle[leaf.nameButton, $BlackOnWhite];
ne.badString ← FALSE;
END;
cs: CellState => NULL;
ENDCASE => ERROR;
END;
SetTest: HD.ChildNotifyProc = TRUSTED
BEGIN
leaf: HD.Leaf ← NARROW[child];
WITH leaf.instanceData SELECT FROM
ne: NodeElt => BEGIN
val: ROPE ← ne.node.type.unParseTest[testProc: ne.testProc, testData: ne.testData, typeData: ne.node.type.typeData, subject: NIL];
VT.InhibitUserEdits[leaf.value];
VT.SetContents[leaf.value, val];
leaf.value.newVersion ← FALSE;
VT.EnableUserEdits[leaf.value];
Buttons.SetDisplayStyle[leaf.nameButton, $BlackOnWhite];
ne.badString ← FALSE;
END;
cs: CellState => NULL;
ENDCASE => ERROR;
END;
HD.EnumerateChildren[to: IF mode = Value THEN SetValue ELSE SetTest, internals: FALSE];
END;
ModeNotify: VR.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: ROPEVT.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;
RC.PostOnCell[
cell: display.rootCell,
condition: nc.cond];
VR.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};
RC.UnPostOnCell[
cell: display.rootCell,
condition: nc.cond];
nc.posted ← FALSE;
VR.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 ← RC.PostIncrementally[nc.cond];
VR.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};
RC.UnPostIncrementally[nc.ic];
nc.ic ← NIL;
nc.postedIncrementally ← FALSE;
VR.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;
VR.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 [cell: Cell, info: ViewerClasses.ViewerRec ← [], paint: BOOLEANTRUE] RETURNS [display: Display] =
BEGIN
OtherStuff: VR.OtherStuffProc--PROC [in: Viewer] RETURNS [stuff: LIST OF Viewer]-- = CHECKED
BEGIN
stuff ← LIST[VR.RVQuaViewer[VR.ViewRef[
agg: display.parms ← NEW [Rosemary.TestParmsRep ← []],
createOptions: [mayInitiateRelayout: FALSE, feedBackHeight: 0],
viewerInit: [parent: in],
paint: FALSE]]];
END;
rvv: Viewer;
ctlPanel: ControlPanel ← NEW [ControlPanelRep ← [
conditions: OSTR.CreateTable[CompareNamedConditions],
incrementalDisplay: longIncremental,
Pack: Pack,
NoticeEdits: NoticeEdits,
NoticeEditsAndRunIfOK: NoticeEditsAndRunIfOK,
Run: Run,
SingleStep: SingleStep,
Test: Test,
ListSchedule: ListSchedule,
Interrupt: Interrupt,
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 ← [
rootCell: cell,
ctlPanel: ctlPanel,
conditionHandle: NIL,
conditionsHandle: NIL,
rootDisplay: HD.CreateRoot[
viewerInit: [
parent: NIL,
iconic: FALSE,
scrollable: TRUE,
name: cell.name.Cat[".display"]],
paint: paint],
rv: NIL]];
display.rv ← VR.ViewRef[
agg: ctlPanel,
specs: VR.BindingListAppend[
LIST[
["mode", Notify[notify: ModeNotify, clientData: display]],
["incrementalDisplay", Notify[notify: IncrNotify, clientData: display]],
["conditionStack", TryRecognizer[RecognizeTreeNodeList]],
["condition", TryRecognizer[RecognizeTree]],
["conditions", TryRecognizer[RecognizeST]],
["status", Value[val: NIL, visible: TRUE, dontAssign: TRUE]] ] ,
VR.BindAllOfATypeFromRefs[rec: ctlPanel, handle: NEW [Display ← display]] ],
otherStuff: OtherStuff,
createOptions: [exclusiveProcs: FALSE],
viewerInit: [parent: NIL, iconic: FALSE, scrollable: TRUE, name: cell.name.Cat[".ops"]],
paint: paint];
rvv ← VR.RVQuaViewer[display.rv];
--Now a bad idea?:--
--ViewerOps.SetOpenHeight[viewer: rvv, clientHeight: 100];--
--ViewerOps.ComputeColumn[rvv.column];--
--[] ← rvv.class.scroll[self: rvv, op: up, amount: 200];--
display.conditionHandle ← display.rv.GetEltHandle[LIST["condition"]];
display.conditionsHandle ← display.rv.GetEltHandle[LIST["conditions"]];
Process.InitializeCondition[
condition: @display.notice,
ticks: Process.SecondsToTicks[5]];
Rosemary.AddGlobalEventWatcher[setIncrementalDisplay, [NoticeSetIncrementalDisplay, display]];
ViewerHelp.AttachHelper[
helper: ViewerHelp.ShowNamedNodeInFile["Rosemary.doc"],
to: display.rv.RVQuaViewer[], end: back];
END;
cellClass: PUBLIC HD.ChildClass ← NEW [HD.ChildClassRep ← [
buttonProc: DullButtonProc,
NotifyOnRemove: NoticeCellRemoval]];
nodeClass: PUBLIC HD.ChildClass ← NEW [HD.ChildClassRep ← [
buttonProc: DullButtonProc,
NotifyOnRemove: NoticeNodeRemoval]];
DullButtonProc: Buttons.ButtonProc = TRUSTED
BEGIN
leaf: HD.Leaf;
ne: NodeElt;
IF (IF clientData = NIL THEN TRUE ELSE NOT ISTYPE[clientData, HD.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 => VT.SetSelection[leaf.value];
yellow => AddAnd[ne, shift];
blue => AddOr[ne, shift];
ENDCASE => ERROR;
END;
AddOr: PROC [ne: NodeElt, invert: BOOLEAN] =
BEGIN
display: Display ← ne.org.display;
nt: RC.NodeTest ← NEW [RC.NodeTestRep ← [
node: ne.node,
nodeName: ne.name,
cell: ne.org.cell,
testData: ne.testData,
testProc: ne.testProc]];
leaf: TreeNode ← Trees.Leaf[nt, RC.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: RC.NodeTest ← NEW [RC.NodeTestRep ← [
node: ne.node,
nodeName: ne.name,
cell: ne.org.cell,
testData: ne.testData,
testProc: ne.testProc]];
leaf: TreeNode ← Trees.Leaf[nt, RC.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];
VR.RedisplayElt[display.conditionHandle];
END;
NoticeCellRemoval: HD.ChildNotifyProc = CHECKED
BEGIN
cb: CellBrowser ← NARROW[child.instanceData];
cb.cell.other ← List.PutAssoc[key: cb.display, val: NIL, aList: cb.cell.other];
IF cb.cell.type = Real THEN Rosemary.RemoveCellEventWatcher[cb.cell, $Schedule, [NotifyCellView, child]];
END;
NoticeNodeRemoval: HD.ChildNotifyProc = TRUSTED
BEGIN
ne: NodeElt ← NARROW[child.instanceData];
displays: NodeDisplayList ← NARROW[List.Assoc[key: nodeDisplaysProp, aList: ne.node.other]];
nd: NodeDisplay;
found: BOOLEAN;
leaf: HD.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.other ← List.PutAssoc[key: nodeDisplaysProp, val: displays, aList: ne.node.other];
Rosemary.RemoveNodeWatcher[node: ne.node, watcher: [NotifyNodeView, leaf], priority: 1];
END;
NotifyNodeView: PUBLIC Rosemary.NodeNotifyProc = TRUSTED
BEGIN
leaf: HD.Leaf ← NARROW[clientData];
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 ← node.type.toRope[where: node.visible.SocketToWP[], typeData: node.type.typeData];
VT.SetContents[v, val];
END;
NotifyCellView: PUBLIC Rosemary.CellNotifyProc = TRUSTED
BEGIN
dc: HD.Child ← NARROW[clientData];
IF trackChanges THEN Buttons.SetDisplayStyle[dc.nameButton, IF cell.realCellStuff.schedNext = Rosemary.notInSchedule 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] =
{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];
Rosemary.AddGlobalEventWatcher[event: $Stop, watcher: [NoticeStop]];
Rosemary.AddGlobalEventWatcher[event: $Start, watcher: [NoticeStart]];
END;
Setup[];
END.