File NoteEditorImpl.mesa
Created by Donahue, October 27, 1982 11:37 am
Last edited by:
Donahue March 14, 1983 3:35 pm
Cattell December 22, 1983 12:57 pm
Last Edited by: Butler, August 13, 1984 2:12:10 pm PDT
DIRECTORY
Buttons: TYPE USING[ ButtonProc ],
DB,
DBEnvironment,
NoteEditor,
Menus,
NutButtons USING [NutButton],
NutViewer USING [MakeButton, Error, Initialize, MakeBigTextBox, MakeRuler],
Rope,
VFonts,
ViewerClasses: TYPE USING[ Viewer ],
ViewerOps: TYPE USING[ AddProp, FetchProp, PaintHint, PaintViewer, CreateViewer, DestroyViewer, EstablishViewerPosition, SetNewVersion ],
ViewerTools;
NoteEditorImpl: PROGRAM
IMPORTS DB, ViewerOps, Rope, VFonts, ViewerTools, NutViewer, Menus
EXPORTS NoteEditor =
BEGIN OPEN DB, Rope, ViewerClasses;
xFudge: INT = 4;
BoolPtr: TYPE = REF BOOL;
DisplayNote: PUBLIC PROC[
entity: Entity,
sibling: Viewer,
segment: DB.Segment ← NIL,
openHeight: NAT ← 0,
openWidth: NAT ← 0,
noEdits: BOOL ← FALSE ]
RETURNS[ noteViewer: Viewer] = {
Display note subwindow. Note that if noEdits=TRUE and the required schema is underfined
or no note exists, then we return immediately.
NoteRel: Relation =
DeclareRelation["note", IF entity = NIL THEN segment ELSE SegmentOf[entity], OldOnly];
NoteOfAttr: Attribute = DB.DeclareAttribute[
r: NoteRel, name: "of", type: AnyDomainType, version: OldOnly ];
NoteIsAttr: Attribute = DB.DeclareAttribute[
r: NoteRel, name: "is", type: RopeType, version: OldOnly];
noteRelship: Relship← IF NoteRel=NIL OR entity = NIL THEN NIL ELSE
NextRelship[RelationSubset[NoteRel, LIST[AttributeValue[NoteOfAttr, entity]]]];
text: ROPEIF noteRelship = NIL THEN NIL ELSE GetFS[ noteRelship, NoteIsAttr ];
tiogaText: ViewerTools.TiogaContents← RopeToTioga[text];
noteButton: NutButtons.NutButton;
textViewer: Viewer;
IF noEdits AND Rope.Equal[text, ""] THEN RETURN[NIL];
noteButton ← NutViewer.MakeButton[
q: NIL, proc: NoteProc, sib: sibling, name: "Notes",
newLine: TRUE, visible: TRUE];
IF openHeight = 0 THEN openHeight ← VFonts.FontHeight[]*(Rope.Length[text]/70+2);
IF openWidth = 0 THEN openWidth ← 40*VFonts.CharWidth['A];
noteViewer ← ViewerOps.CreateViewer[flavor: $Container,
info: [parent: sibling.parent,
wx: noteButton.wx + noteButton.ww + xFudge,
wy: noteButton.wy, ww: openWidth, wh: openHeight,
border: TRUE, scrollable: FALSE] ];
textViewer ← NutViewer.Initialize[noteViewer];
textViewer ← NutViewer.MakeBigTextBox[sib: textViewer, contents: ""];
ViewerTools.SetTiogaContents[
viewer: textViewer, contents: tiogaText, paint: TRUE ];
ViewerTools.InhibitUserEdits[textViewer]; -- shouldn't edit text directly
ViewerOps.AddProp[ noteButton, $edits, NEW[ BOOL ← (NOT noEdits)] ];
ViewerOps.AddProp[ noteButton, $note, noteRelship ] ;
ViewerOps.AddProp[ noteButton, $Next, noteViewer];
ViewerOps.AddProp[ noteViewer, $Value, text ] ;
ViewerOps.AddProp[ noteViewer, $TextViewer, textViewer];
ViewerOps.AddProp[ sibling.parent, $Notes, noteButton] };
NoteProc: Buttons.ButtonProc =
TRUSTED BEGIN
noteButton: NutButtons.NutButton = NARROW[parent];
noteViewer: Viewer = NARROW[ ViewerOps.FetchProp[ noteButton, $Next]];
edits: BoolPtr = NARROW[ ViewerOps.FetchProp[ noteButton, $edits ]];
SELECT mouseButton FROM
Menus.MouseButton[red] =>
IF edits^ = TRUE THEN MakeNoteEditor[noteViewer]
ELSE NutViewer.Error[noteButton.parent, "Cannot edit note"];
Menus.MouseButton[blue] => --grow box??
{};
ENDCASE;
ViewerOps.PaintViewer[ noteButton.parent, client ];
END;
MakeNoteEditor: PROC[noteViewer: Viewer] =
BEGIN
textViewer: Viewer = NARROW[ ViewerOps.FetchProp[ noteViewer, $TextViewer]];
text: ROPE = ViewerTools.GetContents[ textViewer ];
tiogaText: ViewerTools.TiogaContents← RopeToTioga[text];
width: INT ← noteViewer.ww;
height: INT ← noteViewer.wh;
lastV: Viewer;
ViewerOps.DestroyViewer[textViewer];
ViewerOps.EstablishViewerPosition[viewer: noteViewer, x: noteViewer.wx,
y: noteViewer.wy, w: noteViewer.ww, h: 2*noteViewer.wh];
lastV ← NutViewer.Initialize[noteViewer];
lastV ← NutViewer.MakeButton[q: NIL, sib: lastV, proc: ValueGrow, name: "Grow"];
lastV ← NutViewer.MakeButton[q: NIL, sib: lastV, proc: ValueDone, name: "Done"];
lastV ← NutViewer.MakeButton[q: NIL, sib: lastV, proc: ValueReset, name: "Reset"];
lastV ← NutViewer.MakeRuler[lastV];
lastV ← NutViewer.MakeBigTextBox[sib: lastV,
contents: "" ];
ViewerTools.SetTiogaContents[
viewer: lastV, contents: tiogaText, paint: TRUE ];
ViewerOps.AddProp[ noteViewer, $TextViewer, lastV];
ViewerTools.SetSelection[ lastV, NIL ];
END;
SaveNote: PUBLIC PROC[newEntity: Entity, viewer: Viewer, update: BOOLEANFALSE] =
BEGIN
noteViewer: Viewer = NARROW[ ViewerOps.FetchProp[viewer, $Next]];
text: ROPE = NARROW[ ViewerOps.FetchProp[noteViewer, $Value]];
NoteRel: Relation = DeclareRelation["note", SegmentOf[newEntity], NewOrOld];
NoteOfAttr: Attribute = DeclareAttribute[NoteRel, "of", AnyDomainType];
NoteIsAttr: Attribute = DeclareAttribute[NoteRel, "is", RopeType];
IF update THEN BEGIN
noteRelship: Relship = V2E[ ViewerOps.FetchProp[ viewer, $note ] ];
IF noteRelship # NIL THEN
{ SetF[ noteRelship, NoteIsAttr, S2V[text] ]; RETURN };
END;
ViewerOps.AddProp[ viewer, $note, CreateRelship[ r: NoteRel, init: LIST[
AttributeValue[attribute: NoteOfAttr, lo: newEntity ],
AttributeValue[attribute: NoteIsAttr, lo: S2V[text]]]]];
END;
TiogaToRope: PROC[tioga: ViewerTools.TiogaContents] RETURNS [rope: ROPE] = {
Converts a tioga node into a single rope that can be stored in a database or file.
IF tioga.formatting.Length[]=0 THEN -- No formatting
RETURN[tioga.contents]
ELSE -- Concatenate text and formatting with a null as separator
RETURN[Rope.Cat[tioga.contents, "\000", tioga.formatting]];
};
RopeToTioga: PROC[rope: ROPE] RETURNS [tioga: ViewerTools.TiogaContents] = {
Converts a rope into the two parts previously concatenated by TiogaToRope.
pos: INT← rope.Find["\000"];
IF pos=-1 THEN -- No formatting: fake a Tioga node
tioga← NEW[ViewerTools.TiogaContentsRec← [rope, NIL]]
ELSE -- Break into parts before and after null separator
tioga← NEW[ViewerTools.TiogaContentsRec← [rope.Substr[0, pos], rope.Substr[pos+1]]];
};
ValueGrow: Buttons.ButtonProc =
TRUSTED BEGIN
noteViewer: ViewerClasses.Viewer ← (NARROW[parent, Viewer]).parent;
shiftHeight: INT ← 2*noteViewer.wh;
ViewerOps.EstablishViewerPosition[viewer: noteViewer, x: noteViewer.wx,
y: noteViewer.wy, h: 2*noteViewer.wh, w: noteViewer.ww];
ViewerOps.PaintViewer[noteViewer, all];
END;
ValueDone: Buttons.ButtonProc =
TRUSTED BEGIN
noteViewer: ViewerClasses.Viewer ← (NARROW[parent, Viewer]).parent;
textViewer: ViewerClasses.Viewer ← NARROW[
ViewerOps.FetchProp[noteViewer, $TextViewer] ];
newValue: Rope.ROPE = ViewerTools.GetContents[textViewer];
topOfViewer: INT = textViewer.sibling.sibling.wy;
newHeight: INT = VFonts.FontHeight[]*(Rope.Length[newValue]/70+2);
newWidth: INT = 40*VFonts.CharWidth['A];
-- destroy buttons and move text up
ViewerOps.EstablishViewerPosition[viewer: noteViewer, x: noteViewer.wx,
y: noteViewer.wy, h: newHeight, w: newWidth];
ViewerOps.EstablishViewerPosition[viewer: textViewer, x: textViewer.wx,
y: topOfViewer, h: newHeight, w: newWidth];
ViewerOps.DestroyViewer[textViewer.sibling.sibling.sibling.sibling]; --("grow")
ViewerOps.DestroyViewer[textViewer.sibling.sibling.sibling]; --("done")
ViewerOps.DestroyViewer[textViewer.sibling.sibling]; --("reset")
ViewerOps.DestroyViewer[textViewer.sibling]; --(line)
-- if new value then reset properties and flag editor as changed
IF newValue # ViewerOps.FetchProp[noteViewer, $Value] THEN BEGIN
noteButton: NutButtons.NutButton = noteViewer.sibling;
ViewerOps.AddProp[noteButton, $Changes, noteViewer];
ViewerOps.AddProp[noteViewer, $Value, newValue];
ViewerOps.SetNewVersion[noteViewer.parent];
IF Menus.FindEntry[noteViewer.parent.menu, "Reset"] # NIL THEN --editor viewer
Menus.SetGuarded[ Menus.FindEntry[noteViewer.parent.menu, "Reset"], TRUE ];
END;
ViewerOps.PaintViewer[noteViewer.parent, client];
END;
ValueReset: Buttons.ButtonProc =
TRUSTED BEGIN
noteViewer: ViewerClasses.Viewer ← (NARROW[parent, Viewer]).parent;
textViewer: ViewerClasses.Viewer ← NARROW[
ViewerOps.FetchProp[noteViewer, $TextViewer]];
oldValue: Rope.ROPENARROW[ViewerOps.FetchProp[noteViewer, $Value]];
tiogaText: ViewerTools.TiogaContents← RopeToTioga[oldValue];
ViewerTools.SetTiogaContents[
viewer: textViewer, contents: tiogaText, paint: TRUE ];
END;
END.