<> <> <> <> <> <<>> <<>> DIRECTORY DB, DefaultNutUtilities, IO, InputFocus, Menus USING [MouseButton], Nut, NutOps, NutViewer, Rope USING [Find, Substr], VFonts USING [StringWidth, Font, EstablishFont], ViewerOps, Buttons; DefaultNutUtilitiesImpl: CEDAR PROGRAM IMPORTS DB, Nut, NutOps, NutViewer, InputFocus, ViewerOps, VFonts, Rope EXPORTS DefaultNutUtilities = BEGIN OPEN DB, NutViewer, DefaultNutUtilities; buttonSize: INT = 125; xFudge: INT = 4; attributeFont: PUBLIC VFonts.Font _ VFonts.EstablishFont[family: "Tioga", size: 10]; relationFont: PUBLIC VFonts.Font _ VFonts.EstablishFont[family: "Helvetica", size: 8, bold: TRUE]; valueFont: PUBLIC VFonts.Font _ VFonts.EstablishFont[family: "Cream", size: 12]; SpawnParent: PROC[v: Viewer] RETURNS [parent: Viewer] = { parent _ v; WHILE parent.parent # NIL DO parent _ parent.parent ENDLOOP }; ProcessSelection: PUBLIC Buttons.ButtonProc = -- A standard ButtonProc that assumes the button's REF ANY data is the FieldHandle above. -- Insures attribute of tuple is entity-valued and non-NIL, then calls Nut.Display on it. BEGIN OPEN DB; otherEntity: Entity; fd: DefaultNutUtilities.FieldHandle_ NARROW[clientData]; viewer: Viewer_ NARROW[parent]; IF fd.attribute=NIL THEN -- it was the relation itself { otherEntity _ RelationOf[fd.tuple]; IF NOT DB.Null[otherEntity] THEN [] _ Nut.Display[eName: DB.NameOf[otherEntity], domain: "RelationDomain", parent: SpawnParent[viewer], segment: DB.SegmentOf[otherEntity]] } ELSE IF NutOps.EntityValued[fd.attribute] THEN -- attribute refs another entity IF Null[fd.tuple] THEN Message[viewer, "That relationship has been deleted!"] ELSE IF Null[otherEntity_V2E[GetF[fd.tuple, fd.attribute]]] THEN Message[viewer, "That entity has been deleted!"] ELSE { otherEntity _ V2E[GetF[fd.tuple, fd.attribute]]; [] _ Nut.Display[eName: DB.NameOf[otherEntity], domain: DB.NameOf[DB.DomainOf[otherEntity]], parent: SpawnParent[viewer], segment: DB.SegmentOf[otherEntity]] } ELSE -- attribute is a string or number Message[viewer, "Not an entity-valued field"]; END; Reset: PUBLIC PROC[eName, domain: ROPE, seg: DB.Segment, viewer: Viewer] = BEGIN -- Resets contents of editor to its statebefore edits started. InputFocus.SetInputFocus[]; -- kill the caret viewer.child _ NIL; ViewerOps.PaintViewer[viewer, client]; [] _ Nut.Edit[eName: eName, domain: domain, segment: seg, parent: viewer] ; END; Edit: PUBLIC PROC[eName, domain: ROPE, seg: DB.Segment, parent: Viewer] = BEGIN -- Invoked when hit the "Edit" button on the default displayer. -- Should replace the displayer viewer with an editor viewer. InputFocus.SetInputFocus[]; IF NutOps.IsSystemEntity[eName] THEN BEGIN [] _ NutViewer.Message[NIL, eName, " is a system entity. You may not edit it."]; RETURN; END; [] _ Nut.Edit[ eName: eName, domain: domain, segment: seg, parent: parent]; END; GetTopLevel: PUBLIC PROCEDURE [v: Viewer] RETURNS [ancestor: Viewer] = { FOR ancestor _ v, ancestor.parent UNTIL ancestor.parent=NIL DO ENDLOOP; }; AttrButtonLength: PUBLIC PROC[ attrString, attrValue: ROPE, button: Menus.MouseButton _ Menus.MouseButton[red] ] RETURNS[INT] = BEGIN width: INT = VFonts.StringWidth[PreColon[attrString], attributeFont] + 2*xFudge; vWidth: INT = VFonts.StringWidth[attrValue, valueFont]; IF button=Menus.MouseButton[red] AND vWidth>buttonSize+10 THEN RETURN[width+buttonSize] ELSE RETURN[width+vWidth]; END; PreColon: PROC[label: ROPE] RETURNS[ROPE] = BEGIN colonPos: INT _ Rope.Find[s1: label, s2: ":"]; IF colonPos = -1 THEN --Not a label RETURN[label] ELSE RETURN[ Rope.Substr[base: label, len: colonPos+1] ]; END; END. . .