DIRECTORY BasicTime, BiScrollers, Cursors, Geom2D, Imager, ImagerTransformation, InputFocus, IO, Menus, Pipal, PipalEditor, PipalMutate, PipalPaint, PipalReal, Process, Real, RefTab, TerminalIO, TIPUser, ViewerClasses, ViewerOps; PipalEditorImpl: CEDAR PROGRAM IMPORTS BasicTime, BiScrollers, Cursors, Geom2D, Imager, ImagerTransformation, InputFocus, IO, Menus, Pipal, PipalPaint, PipalReal, Process, TerminalIO, TIPUser, ViewerOps EXPORTS PipalEditor = BEGIN OPEN PipalEditor; lastViewerPaintTime: BasicTime.Pulses; CreateViewer: PUBLIC PROC [object: Pipal.Object] RETURNS [viewer: ViewerClasses.Viewer] ~ { viewer _ ViewerOps.CreateViewer[$Pipal, [name: "PipalViewer", data: object]]; }; ViewerPaint: ViewerClasses.PaintProc = { object: Pipal.Object = self.data; lastViewerPaintTime _ BasicTime.GetClockPulses[]; PipalPaint.Paint[object, context]; lastViewerPaintTime _ BasicTime.GetClockPulses[]-lastViewerPaintTime; }; viewerClass: ViewerClasses.ViewerClass _ NEW [ViewerClasses.ViewerClassRec _ [paint: ViewerPaint]]; ViewerData : TYPE = REF ViewerDataRec; -- what gets hung unto the viewer ViewerDataRec: TYPE = RECORD [ mutant: Pipal.Object, view: View, notify: NotifyProc]; lastBiscrollerPaintTime: BasicTime.Pulses; MakeMenu: PROC [viewerData: ViewerData] RETURNS [menu: Menus.Menu] = { menu _ Menus.CreateMenu[2]; Menus.AppendMenuEntry[menu, Menus.CreateEntry[name: "Reset", proc: ResetClick, clientData: viewerData, fork: FALSE, guarded: TRUE]]; Menus.AppendMenuEntry[menu, Menus.CreateEntry[name: "Undo", proc: UndoClick, clientData: viewerData, fork: FALSE]]; Menus.AppendMenuEntry[menu, Menus.CreateEntry[name: "Redo", proc: RedoClick, clientData: viewerData, fork: FALSE]]; Menus.AppendMenuEntry[menu, Menus.CreateEntry[name: "Flush", proc: FlushClick, clientData: viewerData, fork: FALSE]]; Menus.AppendMenuEntry[menu, Menus.CreateEntry[name: "Debug", proc: DebugClick, clientData: viewerData, fork: TRUE], 1]; }; CreateBiscroller: PUBLIC PROC [mutant: Pipal.Object, tipTable: Pipal.ROPE, notify: NotifyProc, state: REF _ NIL, buttons: BOOL _ FALSE] RETURNS [view: View] = { viewerData: ViewerData _ NEW [ViewerDataRec _ [mutant: mutant, view: NIL, notify: notify]]; style: BiScrollers.BiScrollerStyle _ BiScrollers.GetStyle["Buttonned"]; -- Buttonless class: BiScrollers.BiScrollerClass _ style.NewBiScrollerClass[[ flavor: $PipalBiscroller, -- Note: it has better not be the same as for creating a simple viewer ... [BS] extrema: Extrema, paint: Paint, notify: Notify, bsUserAction: ForkAndDo, finish: LIST [$Exit], menu: IF buttons THEN BiScrollers.CatenateMenus[BiScrollers.bsMenu, MakeMenu[viewerData]] ELSE BiScrollers.bsMenu, icon: fileCabinet, tipTable: TIPUser.InstantiateNewTIPTable[tipTable], cursor: textPointer, -- was bullseye mayStretch: FALSE, offsetsMustBeIntegers: TRUE, preferIntegerCoefficients: FALSE ]]; view _ NEW [ViewRec _ [state: state]]; viewerData.view _ view; [] _ class.style.CreateBiScroller[class: class, info: [ name: Pipal.ClassName[Pipal.ObjectClass[mutant]], iconic: TRUE, data: viewerData ]]; }; Extrema: BiScrollers.ExtremaProc = { viewerData: ViewerData _ NARROW[clientData]; size: PipalReal.Size _ PipalReal.ObjectSize[viewerData.mutant]; [min, max] _ Geom2D.ExtremaOfRect[[0, 0, size.x, size.y], direction]; }; WhatChanged: TYPE = REF WhatChangedRec; WhatChangedRec: TYPE = RECORD [ clipArea: Pipal.Object, -- redisplay the data structure inside these areas outlines: Pipal.Object -- then paint these outlines ]; Paint: ViewerClasses.PaintProc = { bs: BiScrollers.BiScroller _ BiScrollers.QuaBiScroller[self]; viewerData: ViewerData _ NARROW [BiScrollers.ClientDataOfViewer[self]]; mutant: Pipal.Object = viewerData.mutant; lastBiscrollerPaintTime _ BasicTime.GetClockPulses[]; Imager.SetColor[context, Imager.black]; Imager.MaskVector[context, [-1000, 0], [1000, 0]]; Imager.MaskVector[context, [0, -1000], [0, 1000]]; IF whatChanged=NIL THEN PipalPaint.Paint[mutant, context] ELSE { request: OutputRequest = NARROW [whatChanged, REF OutputRequest]^; SELECT request.type FROM clearAndRepaintArea => PipalPaint.ClipAndPaint[mutant, context, request.data]; paintOutline => PipalPaint.PaintAreaOutline[context, request.data]; ENDCASE => TRUSTED {Process.Detach[FORK TerminalIO.PutF["*** PipalEditorImpl: Unknown request: %g!\n", IO.int[ORD [request.type]]]]}; }; lastBiscrollerPaintTime _ BasicTime.GetClockPulses[]-lastBiscrollerPaintTime; }; ForkAndDo: BiScrollers.BSUserActionProc ~ TRUSTED {Process.Detach[FORK BiScrollers.DoBSUserAction[bs, input]]}; Notify: ViewerClasses.NotifyProc = { bs: BiScrollers.BiScroller _ BiScrollers.QuaBiScroller[self]; viewerData: ViewerData _ NARROW [BiScrollers.ClientDataOfViewer[self]]; viewerData.view.transformation _ bs.style.GetTransforms[bs].clientToViewer; viewerData.view.cursor _ bs.class.common.cursor; IF input.first#$Exit THEN { rs: LIST OF OutputRequest; new: Pipal.Object; [rs, new] _ viewerData.notify[viewerData.mutant, viewerData.view, input]; viewerData.mutant _ new; IF new=NIL THEN ERROR; -- trivial test avoiding many wedged viewers! FOR requests: LIST OF OutputRequest _ rs, requests.rest WHILE requests#NIL DO request: OutputRequest = requests.first; SELECT request.type FROM clearAndRepaintArea => ViewerOps.PaintViewer[self, client, FALSE, NEW [OutputRequest _ request]]; repaintAll => ViewerOps.PaintViewer[self, client]; -- until the day we have commands which change menus paintOutline => ViewerOps.PaintViewer[self, client, FALSE, NEW [OutputRequest _ request]]; changeCursor => Cursors.SetCursor[NARROW [request.data, REF Cursors.CursorType]^]; grabInputFocus => InputFocus.SetInputFocus[self]; translate, scale => { bitransf: BiScrollers.Transform _ bs.style.GetTransforms[bs].clientToViewer; bitransf _ ImagerTransformation.Concat[NARROW [request.data], bitransf]; bs.style.ChangeTransform[bs, bitransf, ignore]; Cursors.SetCursor[textPointer]; }; ENDCASE => ERROR; ENDLOOP; }; }; Debug: SIGNAL = CODE; ResetClick: Menus.ClickProc ~ { }; UndoClick: Menus.ClickProc ~ { }; RedoClick: Menus.ClickProc ~ { }; FlushClick: Menus.ClickProc ~ { }; DebugClick: Menus.ClickProc ~ { }; ViewerOps.RegisterViewerClass[$Pipal, viewerClass]; TerminalIO.PutRope["Pipal welcomes you\n"]; END. PipalEditorImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Louis Monier February 3, 1988 11:33:05 am PST Bertrand Serlet February 15, 1988 11:40:18 pm PST Readonly Viewers Creation Debugging only! BiScroller Creation Hack for stats ... whatChanged contains is either NIL (then the whole mutant should be repainted) or a REF to a request. This will have to change when there is a queue, and the cut between Notify and Paint will be different. Coordinate axis extra things to paint Undelicate duplication of code here, but that's probably due to BiScrollers. is that FALSE a TRUE??? Quick and Dirty Buttons mutant: Pipal.Object _ NARROW [clientData, ViewerData].mutant]; -- Reset !! mutant: Pipal.Object _ NARROW [clientData]; IF mutant.undoEvents=NIL THEN TerminalIO.PutF["*** Cannot Undo.\n"] ELSE PipalMutate.Undo[mutant]; ViewerOps.PaintViewer[parent, all]; mutant: Pipal.Object _ NARROW [clientData]; IF mutant.redoEvents=NIL THEN TerminalIO.PutF["*** Cannot Redo.\n"] ELSE PipalMutate.Redo[mutant]; ViewerOps.PaintViewer[parent, all]; mutant: Pipal.Object _ NARROW [clientData]; PipalMutate.Flush[mutant]; ViewerOps.PaintViewer[parent, all]; mutant: Pipal.Object _ NARROW [clientData]; SIGNAL Debug[]; ViewerOps.PaintViewer[parent, all]; Initialization Κ– "cedar" style˜codešœ™Kšœ<™