<> <> <> <> <<(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)>> <<(Added create date property)>> <> DIRECTORY AlpTransaction, Atom, BasicTime, DB, FileNames USING[GetShortName], Rope, TextFind, ViewerTools, WhiteboardDBPrivate; WhiteboardDBPrivateImpl: CEDAR PROGRAM IMPORTS DB, FileNames, Atom, Rope, TextFind, AlpTransaction EXPORTS WhiteboardDBPrivate = BEGIN OPEN WhiteboardDBPrivate; ROPE: TYPE = Rope.ROPE; WBSegment: PUBLIC ROPE _ NIL; readOnly: PUBLIC BOOL _ TRUE; wbType: PUBLIC ATOM _ $Whiteboard; whiteboardTrans: DB.Transaction; volumeGroupID: AlpTransaction.VolumeGroupID; <> WBEntity: DB.Domain; -- the domain of whiteboards <> versionProp: DB.Attribute; gridProp: DB.Attribute; createDateProp: 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 <> contents: DB.Attribute; format: DB.Attribute; <> iconName: DB.Attribute; iconLabel: DB.Attribute; iconType: DB.Attribute; iconIcon: DB.Attribute; iconArgument: DB.Attribute; <> container: DB.Relation; containerIs: DB.Attribute; containerOf: DB.Attribute; containerX: DB.Attribute; containerY: DB.Attribute; containerW: DB.Attribute; containerH: DB.Attribute; CloseTransaction: PUBLIC PROC [] = { abort: BOOL _ FALSE; IF whiteboardTrans = NIL THEN whiteboardTrans _ DB.GetSegmentInfo[wbType].trans; IF whiteboardTrans = NIL THEN RETURN; DB.CloseTransaction[whiteboardTrans ! DB.Aborted => { abort _ TRUE; CONTINUE }; DB.Error, DB.Failure => CONTINUE ]; IF abort THEN DB.AbortTransaction[whiteboardTrans]; whiteboardTrans _ NIL }; OpenTransaction: PUBLIC PROC [] = { IF whiteboardTrans = NIL THEN DB.OpenTransaction[wbType]; whiteboardTrans _ DB.GetSegmentInfo[wbType].trans }; AbortTransaction: PUBLIC PROC [] = { IF whiteboardTrans # NIL THEN DB.AbortTransaction[whiteboardTrans]; whiteboardTrans _ NIL }; MarkTransaction: PUBLIC PROC [unlock: BOOL _ TRUE] = { IF whiteboardTrans # NIL THEN { alpTrans: AlpTransaction.Handle = NARROW[whiteboardTrans]; DB.MarkTransaction[whiteboardTrans]; IF unlock THEN AlpTransaction.UnlockOwnerDB[alpTrans, volumeGroupID] } }; Initialize: PUBLIC PROC[DBFile: ROPE] RETURNS[serverDown: BOOL] = BEGIN serverDown _ FALSE; IF NOT Rope.Equal[WBSegment, DBFile, FALSE] THEN { ENABLE DB.Failure => {WBSegment _ NIL; serverDown _ TRUE; CONTINUE}; WBSegment _ DBFile; CloseTransaction[]; SetUpSegment[] }; END; ResetSchema: PUBLIC PROC[] = { OpenTransaction[]; 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]; <> versionProp _ DB.DeclareProperty["version", WBEntity, DB.IntType, $Whiteboard]; gridProp _ DB.DeclareProperty["gridSize", WBEntity, DB.IntType, $Whiteboard]; createDateProp _ DB.DeclareProperty["createDate", WBEntity, DB.TimeType, $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]]; volumeGroupID _ AlpTransaction.GetNextVolumeGroup[handle: NARROW[whiteboardTrans]] }; SetUpSegment: PROC [] ~ { segmentNumber: NAT = 310B; readOnly _ FALSE; DB.Initialize[nCachePages: 256]; <> DB.DeclareSegment[WBSegment, wbType, segmentNumber, FALSE]; OpenTransaction[ ! DB.Error => TRUSTED { IF code = ProtectionViolation THEN { readOnly _ TRUE; CONTINUE } ELSE GOTO AlreadyDone } ]; IF readOnly THEN { <> CloseTransaction[]; DB.DeclareSegment[WBSegment, wbType, segmentNumber, TRUE, FALSE] } ELSE CloseTransaction[] -- throw away this worthless transaction EXITS AlreadyDone => CloseTransaction[! DB.Error, DB.Failure => CONTINUE] }; <> 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]] }; GetCreateDate: PUBLIC PROC[wb: Whiteboard] RETURNS[date: BasicTime.GMT] = { date _ DB.V2T[DB.GetP[wb, createDateProp]] }; SetCreateDate: PUBLIC PROC[wb: Whiteboard, date: BasicTime.GMT] = { [] _ DB.SetP[wb, createDateProp, DB.T2V[[date]]] }; 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]; <> FOR wbList: LIST OF Whiteboard _ Enumerate[NIL], 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[pattern: ROPE] RETURNS[wbList: LIST OF Whiteboard] = { wbSet: DB.EntitySet = DB.DomainSubset[WBEntity]; BEGIN ENABLE UNWIND => DB.ReleaseEntitySet[wbSet]; finder: TextFind.Finder = IF pattern = NIL THEN NIL ELSE TextFind.CreateFromRope[pattern: pattern, ignoreCase: TRUE, addBounds: TRUE]; FOR wb: DB.Entity _ DB.NextEntity[wbSet], DB.NextEntity[wbSet] UNTIL wb = NIL DO IF finder = NIL OR TextFind.SearchRope[finder, DB.NameOf[wb]].found THEN wbList _ CONS[wb, wbList] ENDLOOP; DB.ReleaseEntitySet[wbSet] END }; <> 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: BOOL _ FALSE] 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] }; <> 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]] }; <> 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; IF NOT readOnly THEN [] _ 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...