-- DisplayerImpl.mesa -- last edit February 19, 1986 3:27:55 pm PST Sturgis -- Swinehart, August 11, 1985 10:15:19 pm PDT DIRECTORY Buttons USING[Button, ButtonProc, Create], Containers USING[Create, ChildXBound, ChildYBound], Displayer USING[ButtonDefiningProc], Labels USING[Create], NewCalcGlobal USING[Document, DocumentProcs], Rope USING[ROPE], StructureNodes USING[Action, PrePaintPass, StructureNode], VFonts USING [ StringWidth, FontHeight ], ViewerClasses USING[Viewer], ViewerEvents USING[EventProc, RegisterEventProc], ViewerOps USING[AddProp, FetchProp, MoveViewer, PaintViewer], ViewerTools USING[MakeNewTextViewer]; DisplayerImpl: PROGRAM IMPORTS Buttons, Containers, Labels, VFonts, ViewerEvents, ViewerOps, ViewerTools EXPORTS Displayer, NewCalcGlobal = BEGIN OPEN Displayer, NewCalcGlobal, ViewerClasses; -- control stuff VersionForSave: CARDINAL = 2; Displayer: TYPE = REF DisplayerBody; DisplayerBody: PUBLIC TYPE = RECORD[ owner: REF ANY, document: NewCalcGlobal.Document, container: Viewer, buttonsPart: Viewer, dataPartContainer: Viewer ← NIL, -- for scrolling dataPart: Viewer ← NIL, rootsn: StructureNodes.StructureNode ← NIL, structureY: INTEGER ← 0, open: BOOLEAN ← FALSE, selectedSn: StructureNodes.StructureNode ← NIL, selectedI, selectedJ: CARDINAL ← 0 ]; ProcButtonInfo: TYPE = REF ProcButtonInfoBody; ProcButtonInfoBody: TYPE = RECORD[ displayer: Displayer, ownerProc: PROC[REF ANY], arg: REF ANY ]; StructureOpButtonInfo: TYPE = REF StructureOpButtonInfoBody; StructureOpButtonInfoBody: TYPE = RECORD[ displayer: Displayer, act: StructureNodes.Action ]; BuildDisplayer: PUBLIC PROCEDURE[document: NewCalcGlobal.Document, owner: REF ANY, name: Rope.ROPE, defineButtons: ButtonDefiningProc] RETURNS[Displayer, --container--Viewer, --structure--Viewer] = BEGIN whole: ViewerClasses.Viewer ← Containers.Create[[name: name, border: FALSE, scrollable: FALSE]]; buttonsPart: Viewer ← Containers.Create[[parent: whole]]; displayer: Displayer ← NEW[DisplayerBody ← [owner: owner, document: document, container: whole, buttonsPart: buttonsPart]]; ViewerOps.AddProp[whole, $DisplayerData, displayer]; [] ← ViewerEvents.RegisterEventProc[DisplayerOpening, open, whole, TRUE]; [] ← ViewerEvents.RegisterEventProc[DisplayerGrown, grow, whole, FALSE]; [displayer.structureY] ← CreateButtons[owner, buttonsPart, displayer, defineButtons]; ViewerOps.MoveViewer[viewer: buttonsPart, x: 0, y: 0, w: 0, h: displayer.structureY, paint: FALSE]; Containers.ChildXBound[displayer.container, buttonsPart]; displayer.dataPartContainer ← Containers.Create[[parent: displayer.container, border: FALSE, wy: displayer.structureY]]; -- until scrolling is more reasonable Containers.ChildXBound[displayer.container, displayer.dataPartContainer]; Containers.ChildYBound[displayer.container, displayer.dataPartContainer]; displayer.dataPart ← Containers.Create[[parent: displayer.dataPartContainer, border: FALSE, scrollable: FALSE]]; Containers.ChildXBound[displayer.dataPartContainer, displayer.dataPart]; --Containers.ChildYBound[displayer.dataPartContainer, displayer.dataPart]; RETURN[displayer, displayer.container, displayer.dataPart]; END; SetDisplayerContents: PUBLIC PROCEDURE[displayer: Displayer, name: Rope.ROPE, sn: StructureNodes.StructureNode] = -- It is up to the client to have previously called abandon on the previous contents. BEGIN displayer.rootsn ← sn; ResetDisplayerName[displayer, name]; END; ResetDisplayerName: PUBLIC PROCEDURE[displayer: Displayer, name: Rope.ROPE] = BEGIN displayer.container.name ← name; ViewerOps.PaintViewer[displayer.container, caption]; END; CreateButtons: PROCEDURE[owner: REF ANY, container: Viewer, displayer: Displayer, defineButtons: ButtonDefiningProc] RETURNS[newY: INTEGER] = BEGIN x, y: INTEGER; h: INTEGER; defineProcButton: PROCEDURE[name: Rope.ROPE, proc: PROC[REF ANY], arg: REF ANY] = BEGIN procButtonInfo: ProcButtonInfo ← NEW[ProcButtonInfoBody ← [displayer, proc, IF arg = NIL THEN owner ELSE arg]]; Step[Buttons.Create[info: [name: name, wx: x, wy: y+1, parent: container, border: FALSE], proc: StandardButtonProc, clientData: procButtonInfo, fork: TRUE]]; END; defineStructureOpButton: PROCEDURE[act: StructureNodes.Action] = {Step[Buttons.Create[info: [name: TextForAction[act], wx: x, wy: y, parent: container, border: FALSE], proc: StructureActionButtonProc, clientData: NEW[StructureOpButtonInfoBody ← [displayer, act]], fork: TRUE]]}; defineLabel: PROCEDURE[initialContents, forSize: Rope.ROPE] RETURNS[Viewer] = BEGIN w: INTEGER ← VFonts.StringWidth[IF forSize = NIL THEN initialContents ELSE forSize] + 10; h: INTEGER ← VFonts.FontHeight[] + 5; v: Viewer ← Labels.Create[[parent: container, wx: x, wy: y, ww: w, wh: h, name: initialContents, border: FALSE]]; Step[v]; RETURN[v]; END; defineText: PROCEDURE[initialContents, forSize: Rope.ROPE] RETURNS[Viewer] = BEGIN w: INTEGER ← VFonts.StringWidth[IF forSize = NIL THEN initialContents ELSE forSize] + 10; h: INTEGER ← VFonts.FontHeight[] + 5; v: Viewer ← ViewerTools.MakeNewTextViewer[[parent: container, wx: x, wy: y+3, ww: w, wh: h, data: initialContents, scrollable: FALSE, border: FALSE]]; Step[v]; RETURN[v]; END; newLine: PROCEDURE = BEGIN y ← y + h; x ← 0; h ← 0; END; Step: PROCEDURE[v: Viewer] = BEGIN deltaY: INTEGER ← (v.wy-y) + v.wh; x ← x + v.ww; IF deltaY > h THEN h ← deltaY; END; x ← y ← h ← 0; defineButtons[owner, defineProcButton, defineStructureOpButton, defineLabel, defineText, newLine]; newLine[]; newLine[]; RETURN[y]; END; TextForAction: PROCEDURE[act: StructureNodes.Action] RETURNS[Rope.ROPE] = BEGIN RETURN[SELECT act FROM MarkCellInteresting => "MarkCellInteresting", InsertColumn => "InsertColumn", AppendColumn => "AppendColumn", DeleteColumn => "DeleteColumn", InsertRow => "InsertRow", AppendRow => "AppendRow", DeleteRow => "DeleteRow", InsertSlot => "InsertSlot", AppendSlot => "AppendSlot", DeleteSlot => "DeleteSlot", InsertPage => "InsertPage", AppendPage => "AppendPage", DeletePage => "DeletePage", CreateGCellArray => "CreateGCellArray", CreateHCellArray => "CreateTable", SetRowControlToControl => "con", SetRowControlToText => "text", SetRowControlToAddItem => "+exp", SetRowControlToSum => "sum", SetColControlToControl => "con", SetColControlToText => "text", SetColControlToAddZero => "+0", SetColControlToAddItem => "+exp", SetColControlToSubItem => "-exp", SetColControlToLeftValTimesExp => "lv*exp", SetColControlToLeftVal => "lv", SetColControlToSum => "sum", SetColControlToTotal => "total", SetColControlToIdGetsTotal => "id←t", SetColControlToIdGetsSum => "id←s", SetColControlToIdGetsLv => "id←lv", ToggleControlVisibility => "ToggleControlVisibility", SetPageId => "SetPageId", MakeSummaryPage => "MakeSummaryPage", CreateSummaryHCellArray => "CreateTableGroup", ENDCASE => ERROR]; END; StandardButtonProc: Buttons.ButtonProc = TRUSTED BEGIN buttonInfo: ProcButtonInfo ← NARROW[clientData]; buttonInfo.ownerProc[buttonInfo.arg]; END; StructureActionButtonProc: Buttons.ButtonProc = TRUSTED BEGIN buttonInfo: StructureOpButtonInfo ← NARROW[clientData]; SABPInternal: PROCEDURE = BEGIN procs: REF NewCalcGlobal.DocumentProcs ← buttonInfo.displayer.document.procs; procs.doOperatorOrStructureAct[buttonInfo.displayer.document, buttonInfo.act, NIL, NIL]; procs.adjust[buttonInfo.displayer.document]; END; buttonInfo.displayer.document.procs.executeInMonitor[buttonInfo.displayer.document, SABPInternal]; END; -- support code --DoOperatorOrStructureAct: PUBLIC PROCEDURE[displayer: Displayer, act: StructureNodes.Action, p1, p2: REF ANY] RETURNS[triedIt: BOOLEAN] = --BEGIN --disp: Displayer; --sn: StructureNodes.StructureNode; --I, J: CARDINAL; --[disp, sn, J] ← GCell.GetItemSelection[]; --IF disp # displayer AND displayer # NIL THEN RETURN[FALSE]; --IF sn = NIL THEN RETURN[FALSE]; --I ← 0; -- --for first call --WHILE sn # NIL DO --[sn, I, J] ← sn.procs.Act[sn, I, J, act, p1, p2]; --ENDLOOP; --RETURN[TRUE]; --END; DisplayerOpening: ViewerEvents.EventProc = TRUSTED BEGIN property: REF ANY ← ViewerOps.FetchProp[viewer, $DisplayerData]; displayer: Displayer ← NARROW[property]; DisplayerOpeningInternal: PROCEDURE = BEGIN IF displayer.open THEN RETURN; displayer.open ← TRUE; PaintDisplayerContents[displayer]; END; displayer.document.procs.executeInMonitor[displayer.document, DisplayerOpeningInternal]; END; -- this code is required to get rid of the funny lines that show up after one of my viewers is grown. -- they are "really" (Willi Sue) a bug in viewers. DisplayerGrown: ViewerEvents.EventProc = TRUSTED BEGIN property: REF ANY ← ViewerOps.FetchProp[viewer, $DisplayerData]; displayer: Displayer ← NARROW[property]; ViewerOps.PaintViewer[displayer.container, client]; END; --AfterStructureOp: PUBLIC PROCEDURE[displayer: Displayer] = --BEGIN --displayer.document.procs.computeTotals[displayer.document]; --displayer.document.procs.adjust[displayer.document]; --END; PaintDisplayerContents: PUBLIC PROCEDURE[displayer: Displayer] = BEGIN lead, height: CARDINAL; L, R, W: CARDINAL; IF displayer.rootsn # NIL AND displayer.open THEN BEGIN [lead, height, , L, , , R, W] ← displayer.rootsn.procs.PrePrePaint[displayer.rootsn]; -- February 19, 1986 3:19:20 pm PST: following is a crock installed because ChildYBound of viewers mechanism has stopped working -- ChildYBound should be setting the height of the data container as the container is scrolled. It no longer does so, so this next line sets it as large as is needed to hold all the sub viewers -- note: the 20 occurring in the next line matches the first 20 appearing in the calls below to PrePaint (i.e., the y offset). ViewerOps.MoveViewer[viewer: displayer.dataPart, x: displayer.dataPart.wx, y: displayer.dataPart.wy, w: displayer.dataPart.ww, h: lead+height+20, paint: FALSE]; -- end of crock displayer.rootsn.procs.PrePaint[displayer.rootsn, 20, 20, L, R, W, first]; displayer.rootsn.procs.PrePaint[displayer.rootsn, 20, 20, L, R, W, second]; displayer.rootsn.procs.Paint[displayer.rootsn, TRUE]; END; --IF displayer.open THEN ViewerOps.PaintViewer[displayer.container, all]; END; -- main code END.. -- 17-Feb-82 11:16:14: Sturgis, started SimpleMatrixImpl.mesa -- RTE: 19-Feb-82 12:37:35: a run time type error using NARROW, would have been caught with parameterized types. i.e. pulled a REF ANY out of a matrix and then supplied it to the wrong procedure. The matrix could have been declared as a paramaterized type. -- RTE: 19-Feb-82 12:51:19: row and column creation did so at 1, rather than intended index. -- RTE: 19-Feb-82 12:58:12: the matrices that hold column and row info needed 1 row (or column) to contain the actual elements (as well as the n columns (or rows)). -- REMARK: 19-Feb-82 13:03:26: screen now comes up, next step is to get the arithmetic to work. -- RTE: 19-Feb-82 13:05:11: forgot to install the menu into the container. -- RTE: 19-Feb-82 13:57:51: ComputeRowSum called GetElement with row number before column number, should have been the other way around. Needed painted cardinals here. -- REMARK: 19-Feb-82 14:05:53: basic arithmetic works. Assorted issues remain: block edit f dependent values, or reset them to correct values; correct handling of badly edited values, etc. -- REMARK: 22-Feb-82 17:24:37: Print (onto a.listing), Save (onto a.logical), and load (from a.logical) seem to work!! Have yet to remove some debugging output. -- change: 26-Feb-82 16:28:07: remove data cell code. -- REMARK: 26-Feb-82 16:45:10: works with DataCell moved out. -- REMARK: 28-Feb-82 16:46:44: renamed: NewCalc.mesa, removed all except world control info. begin edit -- REMARK: 1-Mar-82 18:47:40: compiles -- change: 4-Mar-82 13:11:03: change module name to NewCalc (forgot to change it while editing before), change zero point for structure to 20,20, to see if this makes things visible. (currently 0,0). -- change: 4-Mar-82 17:57:05: add verify -- change: 5-Mar-82 11:58:16: verify now calls dependencies.verify -- RTE?: 5-Mar-82 14:08:23: add a call to perform dirty actions during structure actions. RTE: 6-Mar-82 14:51:04:change action name from print to Show, add a CR between lines. -- 6-Mar-82 17:50:30: top level becomes column of rows. -- 6-Mar-82 18:14:31: add slot menu items, and createsimplematrixA -- 7-Mar-82 17:06:53: modify to use buttons, since menu was too full -- RTE: 7-Mar-82 17:37:26: all buttons overlapped, buttons comments were wrong, so add code to compute appropritae positions. -- RTE: 7-Mar-82 17:48:30: taking several steps to get things unoverlapped. change: 8-Mar-82 15:28:07: convert to new load and save conventions -- RTE: 8-Mar-82 17:21:17: load should have tested for the leading "(" inside the loop. -- change: 9-Mar-82 14:18:05: change the names of the save and print files -- change: 11-Mar-82 14:07:13: add the operator actions of set+, set- and set=. add GeneralOperator action, add the actoin of creating an AdditiveMatrix. -- change: 13-Mar-82 12:04:18: install editable text box to hold svae file name. started at 11:00, lost :15 when Wasp died. Also restructured button creation code, and added button for requesting encryption key, but have yed to add the code. -- RTE: 13-Mar-82 12:29:54: while attempt code to input encryption key, found that MessageWIndow.ReadFrom hung. SO converted to a text box to hold the key, and set key will replace contents of box wieh *s. -- remark: 13-Mar-82 12:35:11: simple mode of getting encryption key is fundamentally working. -- remark: 13-Mar-82 12:40:20: decided to add a test to be sure key had been edited before using it. -- remark: 14-Mar-82 12:30:46: add version numbers and encrytion to save files. about 1/2 hour of initial editing. -- remark: 14-Mar-82 13:05:54: In load, move KeyToken out a level of nesting or so so that I can see it with bugbane. Cant se it with COPilot because it is a variant record. -- RTE: 14-Mar-82 13:47:35: did not have the start of reading decrypted exactly synchronized with the encrypted chars in the file (having to do with skipping over blanks etc). insert a synchronizing char. -- remark: 18-Mar-82 16:26:11: add Adjust, check for dirty data more often, add sub viewers to hold data, so it can be scrolled independently of the buttons. RTE: 18-Mar-82 16:57:25: had "move" the buttons viewer in order to set its height to structureY (rather than 0). RTE: 18-Mar-82 17:04:57: did not step a line at end of CreateButtons, so data viewer ended up overlapping last row of buttons. added 2 StepLines. (note: these chagnes today have taken about 2 hours). -- remark: 25-Mar-82 16:17:35: add another level of container nesting to keep scrolling from changing the wy values of the individual screeen elements. Thus "adjust" won't undo the effect of previous scrolling. (required due to a somewhat unreasonable scrolling implementation by viewers.) -- RTE: March 25, 1982 4:29 pm: had to change the Child?BOund calls to name correct parent. -- July 31, 1982 2:19 pm: convert to cedar 3.2 -- change: August 1, 1982 5:46 pm: add assignmentcells -- change: August 2, 1982 11:14 am: convert to a monitor, fork all button procs, put entry on all button procs. -- RTE: August 4, 1982 10:35 am: add unwind catches to entry procedures. -- change: August 4, 1982 10:35 am: add version to subsequent load calls., remove assignmentcell from top level -- RTE: August 4, 1982 11:09 am: forgot to output new version number during save. -- change: August 7, 1982 4:00 pm: register build world procedure as a command "NewCalc". -- August 7, 1982 6:02 pm: convert to using NCGlobal. -- August 8, 1982 3:25 pm: add code to catch loop in dependency graph error. -- August 8, 1982 3:49 pm: various changes, remove excess calls on performdirtyactions, remove redundant call on sort dependency graph, etc. Thus the dependency error catches need be in only one place. -- August 8, 1982 5:27 pm: catch multiple assignment to one data itme. -- October 1, 1982 2:37 pm: add create GCell array operation and button -- October 2, 1982 2:54 pm: Rename NewCalcImpl -- October 2, 1982 5:24 pm: add logic to try old style selection, then new style selection. -- October 2, 1982 6:28 pm: note selection needs to be an entry procedure as it will be called by a forked process. eventually the caller should use a monitor lock procedure to be supplied by NeCalcImpl. -- October 3, 1982 1:57 pm: add ExecuteInMonitor, a procedure to be called with a proc param, so that proc executes inside the monitor. -- RTE: October 3, 1982 2:21 pm: NoteSelection remained an ENTRY procedure, leading to instant monitor lock. -- change: October 5, 1982 5:07 pm: modify load to set button to black on grey while in execution. -- change: October 5, 1982 5:15 pm: and all the rest of the action buttons. -- change: October 6, 1982 5:47 pm: export get and note selection to GCell, call MakeAGCellToolInstance. -- October 8, 1982 1:31 pm: convert entirely to new node structure. -- change: October 10, 1982 11:58 am: convert to 3.4. 1) IO.CreateFileStream => FileIO.Open. 2) viewer in a button prc becomes NARROW[parent, Viewer]. -- October 10, 1982 2:21 pm: get Action and BadFormatLoadFile from StructureNodes rather than StructureNode. Also remove the recently de implemented actions (e.g. set operator +, createAdditiveMatrix.). -- October 10, 1982 3:51 pm: add code to copy from an encrypted file to a decrypted one. -- October 12, 1982 2:37 pm: rename as "DisplayerImpl". This will be used to display Pages and Arrays. There will be several instances per displayed document. -- October 12, 1982 6:10 pm: lots of bugs trying to get demo working. Outstanding bug is that code in GCellImpl calls ExecuteInMonitor in the NewCalcGlobal interface. Need to get things in a more indirect way. As want to arrive at the appropriate Monitor execute procedure with the appropriate parameter. -- convert to restructured NCGlobal, which includes the ExecuteInMonitor procedure. -- October 14, 1982 5:10 pm: change: GetSelection changed, noew returns displayer, which should be compared with displayer holding the action button. No action if current selection not in displayer holding button. Also, remove demo code. Remove NoteSelection. -- October 18, 1982 3:29 pm: allow proc button to have a private argument. -- October 18, 1982 3:57 pm: add code to reset the name of the viewer, i.e. the caption line. -- October 20, 1982 3:58 pm: add page actions to procedure that generates ropes for action buttons. -- October 21, 1982 1:15 pm: call owner.procs.ComputeTotals, to get totals computed. -- RTE: October 21, 1982 5:08 pm: was returning datapartcontainer, rather than datapart. Result was that viewers landed in the wrong place when ever the outer viewer was scrolled. -- October 26, 1982 4:48 pm: export DoOperatorOrStructure, and allow it to work on any displayer if displayer=NIL. -- RTE: October 31, 1982 4:03 pm: StructureActionButtonProc needed to execute in monitor. For other button procs, the called procedure enters the monitor. -- RTE: November 2, 1982 3:31 pm: DoOperatorOrStructureAct should also return FALSE IF ln is NIL. -- November 2, 1982 4:29 pm: add 2 ref any params to DoOperatorOrStructureAct. -- November 14, 1982 1:56 pm: convert to new selection procedures. CTE: February 11, 1983 11:08 am: convert to 4.0 -- February 27, 1983 3:48 pm: replace logicalnode and displayNode etc with structurenode. February 27, 1983 3:55 pm: took about 5 minutes. -- March 7, 1983 12:13 pm: add code to avoid construcing internal viewers until icon first opened. -- June 25, 1984 11:05:03 am PDT: add code to catch viewer growth, and repaint afterwards, so as to get rid of nasty lines. These catches did not take, as probably only on explicit grow command. The fix that worked, suggested by John Maxwell, is to not have borders around the assorted internal containers. These borders were the ones that were remaining around. However, for appearences, I had to replace the borders around the button area. -- June 25, 1984 11:48:18 am PDT: remove the nasty borders around labels in the button area. -- June 25, 1984 11:58:10 am PDT: now try to get all the various pieces of text to line up. First fix: in making a text box, set wy to y+2, rather than y. Next, text gets wy=y+3, buttons get wy = y+1. Now, the computation of line width is wrong, as ignores the y offsets, and only looks at the viewer heights. So add code to keep track of this in Step. -- June 28, 1984 3:47:20 pm PDT: add HCell Arrays -- July 2, 1984 10:07:12 am PDT: add the new row and column control commands -- February 19, 1986 3:18:43 pm PST: install a work around to PaintDisplayerContents because ChildYBound has stopped working.