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: BOOLEAN ← FALSE
];
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: BOOLEAN ← FALSE;
trackChanges: BOOLEAN ← TRUE;
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 AOK ← FALSE;
END;
AOK ← TRUE;
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 ROPE ← LIST[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: ROPE ← VT.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:
BOOLEAN ←
TRUE]
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.