DIRECTORY
Containers USING [ChildXBound, ChildYBound],
Convert USING [RopeFromInt],
Graph USING [Entity, EntityGroup, EntityGroupList, EntityList, GraphHandle, GraphProc, NestedEntities, NestedEntitiesList, ROPE, Text, Texts, Viewer],
GraphPrivate USING [CallWithLock, RemoveEntity, RemoveText, ShowEntity, ShowText, UserEditAllowed],
GraphUtil USING [BlinkMsg, ControllerViewerExits, HandleNotNil],
InputFocus USING [SetInputFocus],
Rope USING [Concat, Fetch, IsEmpty, Length],
TiogaFileOps USING [AddLooks, CreateRoot, InsertAsLastChild, InsertNode, Ref, SetContents, Store],
TiogaButtons USING [CreateButton, CreateButtonFromNode, CreateViewer, LoadViewer, MarkViewerNotEdited, TiogaButton, TiogaButtonList, TiogaButtonProc],
TiogaOps USING [Break, FirstChild, GetProp, GetRope, InsertRope, LastChild, Lock, LockSel, Nest, Next, Ref, RestoreSelA, SaveSelA, SelectPoint, SetSelection, StepForward, Unlock, UnlockSel, ViewerDoc],
ViewerTools USING [SetContents];
MakeTable:
PUBLIC
PROC [handle: GraphHandle, file:
ROPE, sx, sy:
INTEGER] = {
called by NewController, which should have made sure the following not nil: handle, handle.controller, etc.
IF GraphUtil.HandleNotNil[handle]
THEN {
OPEN handle;
controller.table ← TiogaButtons.CreateViewer[
info: [
wx: sx, wy: sy, ww: 1000, wh: 1000,
menu: NIL,
parent: controller.viewer,
scrollable: TRUE,
border: FALSE,
caption: FALSE
]];
Containers.ChildXBound[controller.viewer, controller.table];
Containers.ChildYBound[controller.viewer, controller.table];
MakeTableFile[handle, file];
TiogaButtons.LoadViewer[controller.table, file];
CreateButtons[handle];
TiogaOps.Jump[controller.table, [controller.textsParent, 0]];
};
}; -- MakeTable
MakeTableFile:
PROC [handle: GraphHandle, tableFile:
ROPE] = {
root, prev: TiogaFileOps.Ref;
IF GraphUtil.HandleNotNil[handle]
THEN {
OPEN handle;
root ← TiogaFileOps.CreateRoot[];
prev ← TextsTable[handle, root];
FOR egl: EntityGroupList ← entityGroupList, egl.rest
UNTIL egl =
NIL
DO
prev ← NETable[handle, egl.first.ys, root, root, prev];
ENDLOOP;
TiogaFileOps.Store[root, tableFile];
};
}; -- MakeTableFile
NextNode:
PROC [root, prev: TiogaFileOps.Ref, rope:
ROPE, child:
BOOL, look:
ROPE ←
NIL]
RETURNS [new: TiogaFileOps.Ref] = {
new ← TiogaFileOps.InsertNode[prev, child];
TiogaFileOps.SetContents[new, rope];
IF
NOT look.IsEmpty[]
THEN
FOR i:
INT
IN [0..look.Length[])
DO
TiogaFileOps.AddLooks[new, 0, rope.Length[], look.Fetch[i], root];
ENDLOOP;
}; -- NextNode
LastChild:
PROC [root, parent, prev: TiogaFileOps.Ref, rope:
ROPE, look:
ROPE ←
NIL]
RETURNS [new: TiogaFileOps.Ref] = {
new ← TiogaFileOps.InsertAsLastChild[parent, prev];
TiogaFileOps.SetContents[new, rope];
IF
NOT look.IsEmpty[]
THEN
FOR i:
INT
IN [0..look.Length[])
DO
TiogaFileOps.AddLooks[new, 0, rope.Length[], look.Fetch[i], root];
ENDLOOP;
}; -- LastChild
TextsTable:
PROC [handle: GraphHandle, root: TiogaFileOps.Ref]
RETURNS [new: TiogaFileOps.Ref] = {
new ← NextNode[root, root, "", TRUE];
new ← NextNode[root, new, "Texts", FALSE, "lb"]; -- texts parent
new ← NextNode[root, new, "", TRUE]; -- leading blank line
FOR ts: Texts ← handle.allTexts, ts.rest
UNTIL ts =
NIL
DO
t: Text ← ts.first; -- error if nil.
new ← NextNode[
root: root, prev: new,
rope: IF t.text = NIL THEN Convert.RopeFromInt[t.id] ELSE t.text,
child: FALSE,
look: NIL
];
ENDLOOP;
}; -- TextsTable
EntityListTable:
PROC [handle: GraphHandle, entityList: EntityList, root, parent: TiogaFileOps.Ref]
RETURNS [new: TiogaFileOps.Ref] = {
new ← parent; -- which is also the previous node.
IF entityList # NIL THEN new ← NextNode[root, parent, "", TRUE];
FOR el: EntityList ← entityList, el.rest
UNTIL el =
NIL
DO
entity: Entity ← el.first; -- error if nil.
new ← LastChild[root: root, parent: parent, prev: new,
rope:
IF entity.name.IsEmpty[]
AND entity.comment.IsEmpty[]
THEN Convert.RopeFromInt[entity.id]
ELSE entity.name.Concat[entity.comment],
look: NIL
];
ENDLOOP;
}; -- EntityListTable
NETable:
PROC [handle: GraphHandle, ne: NestedEntities, root, parent, prev: TiogaFileOps.Ref]
RETURNS [new: TiogaFileOps.Ref] = {
new ← prev;
IF ne #
NIL
THEN {
topLevel: BOOL ← parent = root;
neNode: TiogaFileOps.Ref;
heading
new ← LastChild[root: root, parent: parent, prev: prev, rope: "", look: NIL];
neNode ← new ← NextNode[root: root, prev: new,
-- ne.node
rope: ne.name.Concat[ne.comment],
child: FALSE,
look: IF topLevel THEN "lb" ELSE "b"
];
now its entity list and children.
new ← EntityListTable[handle, ne.entityList, root, neNode];
FOR nel: NestedEntitiesList ← ne.children, nel.rest
UNTIL nel =
NIL
DO
new ← NETable[handle, nel.first, root, neNode, new];
ENDLOOP;
};
}; -- NETable
CreateButtons:
PROC [handle: GraphHandle] = {
OPEN handle;
root: TiogaOps.Ref ← TiogaOps.ViewerDoc[controller.table];
prev: TiogaOps.Ref;
TiogaOps.Lock[root];
TiogaOps.SaveSelA[];
prev ← TextsButtons[handle, root];
FOR egl: EntityGroupList ← entityGroupList, egl.rest
UNTIL egl =
NIL
DO
prev ← NEButtons[handle, egl.first.ys, root, root, prev];
ENDLOOP;
TiogaOps.Unlock[root];
TiogaOps.RestoreSelA[];
}; -- CreateButtons
TextsButtons:
PROC [handle: GraphHandle, root: TiogaOps.Ref]
RETURNS [last: TiogaOps.Ref] = {
OPEN handle;
last ← TiogaOps.FirstChild[root];
controller.textsParent ← last ← TiogaOps.StepForward[last];
last ← TiogaOps.StepForward[last];
FOR ts: Texts ← handle.allTexts, ts.rest
UNTIL ts =
NIL
DO
t: Text ← ts.first; -- error if nil.
last ← TiogaOps.StepForward[last];
[] ← TiogaButtons.CreateButtonFromNode[node: last,
proc: TextButtonProc,
clientData: NEW[GraphButtonDataRec ← [handle, t]]
];
ENDLOOP;
}; -- TextsButtons
EntityListButtons:
PROC [handle: GraphHandle, entityList: EntityList, root, parent: TiogaOps.Ref]
RETURNS [last: TiogaOps.Ref] = {
last ← parent; -- which is also the previous node.
IF entityList # NIL THEN last ← TiogaOps.StepForward[last];
FOR el: EntityList ← entityList, el.rest
UNTIL el =
NIL
DO
entity: Entity ← el.first; -- error if nil.
last ← TiogaOps.StepForward[last];
[] ← TiogaButtons.CreateButtonFromNode[node: last,
proc: EntityButtonProc,
clientData: NEW[GraphButtonDataRec ← [handle, entity]]
];
ENDLOOP;
}; -- EntityListButtons
NEButtons:
PROC [handle: GraphHandle, ne: NestedEntities, root, parent, prev: TiogaOps.Ref]
RETURNS [last: TiogaOps.Ref] = {
last ← prev;
IF ne #
NIL
THEN {
topLevel: BOOL ← parent = root;
last ← TiogaOps.StepForward[last];
ne.node ← last ← TiogaOps.StepForward[last];
last ← EntityListButtons[handle, ne.entityList, root, ne.node];
FOR nel: NestedEntitiesList ← ne.children, nel.rest
UNTIL nel =
NIL
DO
last ← NEButtons[handle, nel.first, root, ne.node, last];
ENDLOOP;
};
}; -- NEButtons
EntityGroupButtonProc: TiogaButtons.TiogaButtonProc = {
-- noop for now
handle: GraphHandle ← NARROW[ViewerOps.FetchProp[parent, $GraphController]];
group: EntityGroup ← NARROW[clientData];
some checking might be necessary.
SetIntField[controller.groupId, group.id];
Control[handle, resume, $Group];
SELECT moustButton FROM
red => IF control THEN Control[handle, display, $Group];
blue => IF control THEN Control[handle, remove, $Group];
ENDCASE;
}; -- EntityGroupButtonProc
NestedEntitiesButtonProc: TiogaButtons.TiogaButtonProc = {
-- noop for now.
}; -- NestedEntitiesButtonProc
EntityButtonProc: TiogaButtons.TiogaButtonProc = {
data: GraphButtonData ← NARROW[clientData];
proc: GraphProc = {
entity: Entity ← NARROW[data.ref];
SELECT mouseButton
FROM
red => {
ViewerTools.SetContents[handle.controller.entityId, Convert.RopeFromInt[entity.id]];
ShowEntity[handle, entity];
};
blue => RemoveEntity[handle, entity];
ENDCASE;
};
IF UserEditAllowed[data.handle] THEN CallWithLock[data.handle, proc];
}; -- EntityButtonProc
TextButtonProc: TiogaButtons.TiogaButtonProc = {
data: GraphButtonData ← NARROW[clientData];
proc: GraphProc = {
t: Text ← NARROW[data.ref];
SELECT mouseButton
FROM
red => {
ViewerTools.SetContents[handle.controller.textId, Convert.RopeFromInt[t.id]];
ShowText[handle, t];
};
blue => RemoveText[handle, t];
ENDCASE;
};
CallWithLock[data.handle, proc];
}; -- EntityButtonProc
}.