WhiteboardDBPrivateImpl.mesa
Copyright (C) 1984 by Xerox Corporation. All rights reserved.
Last edited by
Donahue, May 1, 1985 11:17:29 am PDT
(Changed the implementation so that this interface never catches any errors -- they will all be caught at the WhiteboardDB level and turned into WBErrors)
(Added Grid size property to whiteboards)
Last Edited by: Winkler, December 18, 1984 10:50:36 am PST
DIRECTORY
Atom,
DB,
FileNames USING[GetShortName],
Rope,
ViewerTools,
WhiteboardDBPrivate;
WhiteboardDBPrivateImpl: CEDAR PROGRAM
IMPORTS DB, FileNames, Atom, Rope
EXPORTS WhiteboardDBPrivate =
BEGIN OPEN WhiteboardDBPrivate;
ROPE: TYPE = Rope.ROPE;
WBSegment: PUBLIC ROPENIL;
wbType: PUBLIC ATOM ← $Whiteboard;
Database schema and initialization
WBEntity: DB.Domain; -- the domain of whiteboards
Each whiteboard has a version property (which is changed whenever the contents of the whiteboard changes) and a "grid size" property
versionProp: DB.Attribute;
gridProp: DB.Attribute;
WBItem: DB.Domain; -- the domain of entities that are displayed on whiteboards
Note: DB.Entity; -- notes (text boxes) are a subclass of WBItems
Icon: DB.Entity; -- Icons are the other class of WBItems
A Note has attributes: [contents: ROPE, format: ROPE]
contents: DB.Attribute;
format: DB.Attribute;
An Icon has attributes: [iconName: ROPE, iconLabel: ROPE, iconType: ROPE, iconIcon: ROPE, iconArgument: ROPE -- this is for tools only]
iconName: DB.Attribute;
iconLabel: DB.Attribute;
iconType: DB.Attribute;
iconIcon: DB.Attribute;
iconArgument: DB.Attribute;
The information about the position of WBItems on a whiteboard is given by the container relation Container[of: WBEntity, is: WBItem, x, y, w, h: INT]
container: DB.Relation;
containerIs: DB.Attribute;
containerOf: DB.Attribute;
containerX: DB.Attribute;
containerY: DB.Attribute;
containerW: DB.Attribute;
containerH: DB.Attribute;
CloseTransaction: PROC [] = {
trans: DB.Transaction = DB.GetSegmentInfo[$Whiteboard].trans;
caughtAborted: BOOLFALSE;
IF trans # NIL THEN
DB.CloseTransaction[trans ! DB.Aborted => { caughtAborted ← TRUE; CONTINUE }];
IF caughtAborted THEN DB.AbortTransaction[trans] };
Initialize: PUBLIC PROC[DBFile: ROPE] =
BEGIN
IF NOT Rope.Equal[WBSegment, DBFile] THEN {
IF WBSegment = NIL THEN WBSegment ← DBFile
ELSE {WBSegment ← DBFile; CloseTransaction[] } };
ResetSchema[]
END;
ResetSchema: PUBLIC PROC[] = {
IF DB.GetSegmentInfo[$Whiteboard].trans # NIL THEN RETURN;
SetUpSegment[WBSegment];
IF NOT DB.Null[Note] THEN RETURN;
Note ← DB.DeclareDomain["Note", $Whiteboard];
Icon ← DB.DeclareDomain["WBIcon", $Whiteboard];
WBItem ← DB.DeclareDomain["WBItems", $Whiteboard];
DB.DeclareSubType[of: WBItem, is: Note];
DB.DeclareSubType[of: WBItem, is: Icon];
WBEntity ← DB.DeclareDomain["Whiteboard", $Whiteboard];
contents ← DB.DeclareProperty["contents", Note, DB.RopeType, $Whiteboard];
format ← DB.DeclareProperty["format", Note, DB.RopeType, $Whiteboard];
iconName ← DB.DeclareProperty["entity", Icon, DB.RopeType, $Whiteboard];
iconLabel ← DB.DeclareProperty["label", Icon, DB.RopeType, $Whiteboard];
iconType ← DB.DeclareProperty["type", Icon, DB.RopeType, $Whiteboard];
iconIcon ← DB.DeclareProperty["icon", Icon, DB.RopeType, $Whiteboard];
iconArgument ← DB.DeclareProperty["argument", Icon, DB.RopeType, $Whiteboard];
for whiteboards
versionProp ← DB.DeclareProperty["version", WBEntity, DB.IntType, $Whiteboard];
gridProp ← DB.DeclareProperty["gridSize", WBEntity, DB.IntType, $Whiteboard];
container ← DB.DeclareRelation["container", $Whiteboard];
containerIs ← DB.DeclareAttribute[container, "is", WBEntity];
containerOf ← DB.DeclareAttribute[container, "of", WBItem];
containerX ← DB.DeclareAttribute[container, "x", DB.IntType];
containerY ← DB.DeclareAttribute[container, "y", DB.IntType];
containerW ← DB.DeclareAttribute[container, "w", DB.IntType];
containerH ← DB.DeclareAttribute[container, "h", DB.IntType];
[] ← DB.DeclareIndex[container, LIST[containerIs]] };
SetUpSegment: PROC [segmentFile: ROPE] ~ {
segment: ATOM = $Whiteboard;
segmentNumber: NAT = 310B;
readOnly: BOOLFALSE;
DB.Initialize[nCachePages: 256];
try opening the segment for writing
DB.DeclareSegment[segmentFile, segment, segmentNumber, FALSE];
DB.OpenTransaction[$Whiteboard !
DB.Error => TRUSTED {
IF code = ProtectionViolation THEN { readOnly ← TRUE; CONTINUE } ELSE REJECT } ];
IF readOnly THEN {
attempt to open for writing failed; open it for reading only
DB.CloseTransaction[DB.GetSegmentInfo[segment].trans];
DB.DeclareSegment[segmentFile, segment, segmentNumber, TRUE, FALSE];
DB.OpenTransaction[segment] };
};
Operations on Whiteboards.
DeclareWhiteboard: PUBLIC PROC[name: ROPE] RETURNS[wb: Whiteboard] = {
wb ← DB.DeclareEntity[WBEntity, name] };
GetVersion: PUBLIC PROC[wb: Whiteboard] RETURNS[version: INT] = {
version ← DB.V2I[DB.GetP[wb, versionProp]] };
SetVersion: PUBLIC PROC[wb: Whiteboard, version: INT] = {
[] ← DB.SetP[wb, versionProp, DB.I2V[version]] };
GetGridSize: PUBLIC PROC[wb: Whiteboard] RETURNS[gridSize: INT] = {
gridSize ← DB.V2I[DB.GetP[wb, gridProp]];
IF gridSize <= 0 THEN gridSize ← 1 };
SetGridSize: PUBLIC PROC[wb: Whiteboard, gridSize: INT] = {
[] ← DB.SetP[wb, gridProp, DB.I2V[gridSize]] };
NameOf: PUBLIC PROC[wb: Whiteboard] RETURNS[name: ROPE] = {
name ← DB.NameOf[wb] };
DestroyWhiteboard: PUBLIC PROC[wb: Whiteboard] = {
IF DB.Null[wb] THEN RETURN;
DB.DestroyEntity[wb];
destroy all internal references
FOR wbList: LIST OF Whiteboard ← Enumerate[], wbList.rest UNTIL wbList = NIL DO
nextWB: Whiteboard = wbList.first;
name: ROPE = NameOf[nextWB];
children: ChildSet = Children[nextWB, TRUE];
FOR child: WhiteboardDBPrivate.WBItem ← NextChild[children], NextChild[children] UNTIL child = NIL DO
IF Rope.Equal[name, GetIconProps[child].name] THEN DB.DestroyEntity[child]
ENDLOOP
ENDLOOP };
Exists: PUBLIC PROC[name: ROPE] RETURNS[BOOL] = {
RETURN[NOT DB.Null[DB.DeclareEntity[WBEntity, name, OldOnly]]] };
Enumerate: PUBLIC PROC[] RETURNS[wbList: LIST OF Whiteboard] = {
wbSet: DB.EntitySet = DB.DomainSubset[WBEntity];
FOR wb: DB.Entity ← DB.NextEntity[wbSet], DB.NextEntity[wbSet] UNTIL wb = NIL DO
wbList ← CONS[wb, wbList]
ENDLOOP;
DB.ReleaseEntitySet[wbSet] };
Generic operations on Whiteboard Items.
FetchWBItem: PUBLIC PROC[name: ROPE, type: ItemType] RETURNS[item: WhiteboardDBPrivate.WBItem] = {
item ← IF type = note THEN DB.DeclareEntity[Note, name, OldOnly]
ELSE DB.DeclareEntity[Icon, name, OldOnly] };
Parent: PUBLIC PROC[item: WhiteboardDBPrivate.WBItem] RETURNS[wb: Whiteboard] = {
wb ← DB.V2E[DB.GetF[DB.DeclareRelship[container, LIST[[containerOf, item]]], containerIs]] };
Children: PUBLIC PROC[wb: Whiteboard, onlyWhiteboards: BOOLFALSE] RETURNS[children: ChildSet] = {
rs: DB.RelshipSet = DB.RelationSubset[container, LIST[[containerIs, wb]]];
children ← NEW[ChildSetObject ← [rs, onlyWhiteboards]] };
NextChild: PUBLIC PROC[children: ChildSet] RETURNS[child: WhiteboardDBPrivate.WBItem] = {
rs: DB.RelshipSet = children.rs;
IF rs # NIL THEN {
IF NOT children.screen THEN {
next: DB.Relship = DB.NextRelship[rs];
IF next = NIL THEN RETURN[NIL];
child ← DB.V2E[DB.GetF[next, containerOf]] }
ELSE
FOR next: DB.Relship ← DB.NextRelship[rs], DB.NextRelship[rs] UNTIL next = NIL DO
child ← DB.V2E[DB.GetF[next, containerOf]];
IF TypeOf[child] = icon AND GetIconProps[child].type = wbType THEN EXIT
ELSE child ← NIL
ENDLOOP;
IF child = NIL THEN {DB.ReleaseRelshipSet[rs]; children.rs ← NIL} }
ELSE child ← NIL };
TypeOf: PUBLIC PROC[item: WhiteboardDBPrivate.WBItem] RETURNS[type: ItemType] = {
type ← IF DB.Eq[DB.DomainOf[item], Note] THEN note ELSE icon };
Position: PUBLIC PROC[item: WhiteboardDBPrivate.WBItem] RETURNS[x, y: INT] = {
cRS: DB.Relship = DB.DeclareRelship[container, LIST[[containerOf, item]]];
x ← DB.V2I[DB.GetF[cRS, containerX]];
y ← DB.V2I[DB.GetF[cRS, containerY]] };
Size: PUBLIC PROC[item: WhiteboardDBPrivate.WBItem] RETURNS[w, h: INT] = {
cRS: DB.Relship = DB.DeclareRelship[container, LIST[[containerOf, item]]];
w ← DB.V2I[DB.GetF[cRS, containerW]];
h ← DB.V2I[DB.GetF[cRS, containerH]] };
Move: PUBLIC PROC[item: WhiteboardDBPrivate.WBItem, newX, newY: INT] = {
cRS: DB.Relship = DB.DeclareRelship[container, LIST[[containerOf, item]]];
DB.SetF[cRS, containerX, DB.I2V[newX]];
DB.SetF[cRS, containerY, DB.I2V[newY]] };
Destroy: PUBLIC PROC[item: WhiteboardDBPrivate.WBItem] = {
IF NOT DB.Null[item] THEN DB.DestroyEntity[item] };
Operations on Whiteboard Notes.
NewNote: PUBLIC PROC[parent: Whiteboard, x, y, w, h: INT, content: ViewerTools.TiogaContents] RETURNS[newNote: WBNote] = {
note: WBNote = DB.DeclareEntity[Note];
props: DB.Relship = DB.DeclareRelship[container, LIST[[containerOf, note]]];
DB.SetF[props, containerIs, parent];
DB.SetF[props, containerX, DB.I2V[x]];
DB.SetF[props, containerY, DB.I2V[y]];
DB.SetF[props, containerW, DB.I2V[w]];
DB.SetF[props, containerH, DB.I2V[h]];
[] ← DB.SetP[note, contents, DB.S2V[content.contents]];
[] ← DB.SetP[note, format, DB.S2V[content.formatting]];
RETURN[note] };
GetContents: PUBLIC PROC[note: WBNote] RETURNS[content: ViewerTools.TiogaContents] = {
content ← NEW[ViewerTools.TiogaContentsRec ← []];
content.contents ← DB.V2S[DB.GetP[note, contents]];
content.formatting ← DB.V2S[DB.GetP[note, format]] };
SetContents: PUBLIC PROC[note: WBNote, content: ViewerTools.TiogaContents] = {
[] ← DB.SetP[note, contents, DB.S2V[content.contents]];
[] ← DB.SetP[note, format, DB.S2V[content.formatting]] };
Grow: PUBLIC PROC[note: WBNote, newW, newH: INT] = {
props: DB.Relship = DB.DeclareRelship[container, LIST[[containerOf, note]]];
DB.SetF[props, containerW, DB.I2V[newW]];
DB.SetF[props, containerH, DB.I2V[newH]]
};
Operations on Whiteboard Icons.
NewIcon: PUBLIC PROC[parent: Whiteboard, x, y: INT, name, label, icon, argument: ROPE, type: ATOM] RETURNS[newIcon: WBIcon] = {
wbIcon: WhiteboardDBPrivate.WBIcon = DB.DeclareEntity[Icon];
props: DB.Relship = DB.DeclareRelship[container, LIST[[containerOf, wbIcon]]];
DB.SetF[props, containerIs, parent];
DB.SetF[props, containerX, DB.I2V[x]];
DB.SetF[props, containerY, DB.I2V[y]];
DB.SetF[props, containerW, DB.I2V[64]];
DB.SetF[props, containerH, DB.I2V[64]];
[] ← DB.SetP[wbIcon, iconIcon, DB.S2V[icon]];
[] ← DB.SetP[wbIcon, iconName, DB.S2V[name]];
[] ← DB.SetP[wbIcon, iconLabel, DB.S2V[label]];
[] ← DB.SetP[wbIcon, iconArgument, DB.S2V[argument]];
[] ← DB.SetP[wbIcon, iconType, DB.S2V[Atom.GetPName[type]]];
RETURN[wbIcon] };
GetDisplayProps: PUBLIC PROC[wbIcon: WBIcon] RETURNS[label, icon: ROPE] = {
label ← DB.V2S[DB.GetP[wbIcon, iconLabel]];
icon ← DB.V2S[DB.GetP[wbIcon, iconIcon]];
IF Rope.Equal[icon, ""] THEN {
icon ← DefaultIcon[wbIcon];
[] ← DB.SetP[wbIcon, iconLabel, DB.S2V[icon]] };
IF Rope.Equal[label, ""] THEN {
type: ATOM;
name: ROPE;
[name, type] ← GetIconProps[wbIcon];
label ← IF type = $Text THEN FileNames.GetShortName[name] ELSE name;
[] ← DB.SetP[wbIcon, iconLabel, DB.S2V[label]] } };
GetToolArgument: PUBLIC PROC[wbIcon: WBIcon] RETURNS[argument: ROPE] = {
argument ← DB.V2S[DB.GetP[wbIcon, iconArgument]]
};
DefaultIcon: PROC[wbIcon: WBIcon] RETURNS[iconName: ROPE] = {
name: ROPE;
type: ATOM;
[name, type] ← GetIconProps[wbIcon];
SELECT type FROM
wbType => iconName ← "Whiteboard";
$ToolRope => iconName ← "Typescript";
$Text => iconName ← "Document";
$Tool => iconName ← name;
ENDCASE => iconName ← "Acorn" };
GetIconProps: PUBLIC PROC[wbIcon: WBIcon] RETURNS[name: ROPE, type: ATOM] = {
name ← DB.V2S[DB.GetP[wbIcon, iconName]];
type ← Atom.MakeAtom[DB.V2S[DB.GetP[wbIcon, iconType]]] };
SetProps: PUBLIC PROC[wbIcon: WBIcon, name, label, icon: ROPE, type: ATOM] = {
[] ← DB.SetP[wbIcon, iconIcon, DB.S2V[icon]];
[] ← DB.SetP[wbIcon, iconName, DB.S2V[name]];
[] ← DB.SetP[wbIcon, iconLabel, DB.S2V[IF label = NIL THEN name ELSE label]];
[] ← DB.SetP[wbIcon, iconType, DB.S2V[Atom.GetPName[type]]]};
END...