DIRECTORY Atom USING [GetPName], Containers USING [Container, Create, ChildXBound, ChildYBound], Graphics USING [Context, Mark, Save, white, GetBounds, SetColor, DrawBox, Restore, Translate], InputFocus USING [ReleaseButtons], Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc], PEViewer, Process USING [Detach], Real USING [FixI], Rope USING [ROPE], TIPUser USING [InstantiateNewTIPTable,TIPScreenCoords], ViewerClasses USING [Viewer, ViewerClass, ViewerClassRec, NotifyProc, PaintProc, DestroyProc, ScrollProc], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass], WindowManager USING [RestoreCursor]; PEViewerImpl: CEDAR MONITOR IMPORTS Atom, Containers, Graphics, InputFocus, Menus, Process, Real, TIPUser, ViewerOps, WindowManager EXPORTS PEViewer = BEGIN OPEN PEViewer; entryHeight: CARDINAL = 12; -- height of a line of items in a menu entryVSpace: CARDINAL = 3; -- vertical leading between lines entryHSpace: CARDINAL = 8; -- horizontal space between items on a line PathViewerData: TYPE = REF PathViewerDataRec; PathViewerDataRec: TYPE = RECORD [ outer: Containers.Container _ NIL, viewer: ViewerClasses.Viewer, xTranslation, yTranslation: REAL _ 0., xLeft, xRight, yBottom, yTop: REAL _ 0., buttonPasserState: ButtonPasserState _ alive, inputEvent: ATOM, newEventArrival: CONDITION, gotANewHit: BOOLEAN _ FALSE, controlPointX, controlPointY: REAL _ 0., redrawProc: RedrawProc, -- name of procedure for redrawing on window resizing, etc. buttonProc: ButtonProc, -- name of procedure for acting on button pushes quitProc: QuitProc, -- name of procedure for cleaning up on exit clientData: REF ANY ]; ButtonPasserState: TYPE = {alive, dying, dead}; MenuData: TYPE = REF MenuDataRec; MenuDataRec: TYPE = RECORD [ menuButton: ATOM, pathViewerData: PathViewerData ]; BuildViewer: PUBLIC PROCEDURE [name: Rope.ROPE, menuLabels: LIST OF MenuLabelRec, clientData: REF ANY, redrawProc: RedrawProc, quitProc: QuitProc, buttonProc: ButtonProc] RETURNS [pathViewer: ViewerClasses.Viewer] = { menu: Menus.Menu _ Menus.CreateMenu[]; pathViewerData: PathViewerData _ NEW[PathViewerDataRec _ [redrawProc: redrawProc, buttonProc: buttonProc, quitProc: quitProc, clientData: clientData]]; Menus.AppendMenuEntry[ -- enter "erase" button menu: menu, entry: Menus.CreateEntry[ name: "Erase", proc: Erase, clientData: pathViewerData, documentation: "Erase the viewer" ] ]; Menus.AppendMenuEntry[ -- enter "<" button menu: menu, entry: Menus.CreateEntry[ name: "<", proc: RollLeft, clientData: pathViewerData, documentation: "Roll image to left" ] ]; Menus.AppendMenuEntry[ -- enter ">" button menu: menu, entry: Menus.CreateEntry[ name: ">", proc: RollRight, clientData: pathViewerData, documentation: "Roll image to right" ] ]; FOR menuLabels _ menuLabels, menuLabels.rest UNTIL menuLabels = NIL DO Menus.AppendMenuEntry[ -- enter menu buttons menu: menu, entry: Menus.CreateEntry[ name: Atom.GetPName[menuLabels.first.label], proc: MenuHit, clientData: NEW[MenuDataRec _ [ menuButton: menuLabels.first.label, pathViewerData: pathViewerData ] ], documentation: "", guarded: menuLabels.first.guarded ] ]; ENDLOOP; pathViewerData.outer _ Containers.Create[ [ name: name, menu: menu, iconic: TRUE, column: left, scrollable: FALSE ] ]; pathViewerData.viewer _ ViewerOps.CreateViewer[ flavor: $PEViewer, info: [ parent: pathViewerData.outer, wx: 0, wy: 0, -- position WRT parent ww: pathViewerData.outer.ww, -- CHildXBound below wh: pathViewerData.outer.wh, -- CHildXBound below data: pathViewerData, -- describes the current scene scrollable: TRUE ] ]; Containers.ChildXBound[pathViewerData.outer, pathViewerData.viewer]; Containers.ChildYBound[pathViewerData.outer, pathViewerData.viewer]; ViewerOps.PaintViewer[pathViewerData.outer, all]; pathViewerData.xTranslation _ pathViewerData.yTranslation _ 0.; pathViewerData.xLeft _ pathViewerData.yBottom _ 0.; pathViewerData.xRight _ pathViewerData.viewer.ww; pathViewerData.yTop _ pathViewerData.viewer.wh; TRUSTED {Process.Detach[FORK ButtonPasser[pathViewerData]];}; RETURN [pathViewerData.viewer]; }; DrawInViewer: PUBLIC PROCEDURE [pathViewer: ViewerClasses.Viewer, drawProc: DrawProc] = { doDrawProc: REF DrawProc _ NIL; IF pathViewer # NIL THEN { TRUSTED {doDrawProc _ NEW[DrawProc _ drawProc];}; ViewerOps.PaintViewer[ viewer: pathViewer, hint: client, whatChanged: doDrawProc, clearClient: FALSE ]; }; }; PaintProc: ViewerClasses.PaintProc = { pathViewerData: PathViewerData _ NARROW[self.data]; x,y: REAL; x _ pathViewerData.xTranslation; y _ pathViewerData.yTranslation; IF whatChanged = NIL THEN { Graphics.Translate[context, x, y]; pathViewerData.redrawProc[pathViewerData.clientData]; } ELSE { Graphics.Translate[context, x, y]; NARROW[whatChanged, REF DrawProc]^[context]; }; }; Erase: Menus.MenuProc = { DoErase: PROC [context: Graphics.Context] = { mark: Graphics.Mark _ Graphics.Save[context]; Graphics.SetColor[context, Graphics.white]; Graphics.DrawBox[context, Graphics.GetBounds[context]]; Graphics.Restore[context,mark]; }; pathViewerData: PathViewerData _ NARROW[clientData]; DrawInViewer[pathViewerData.viewer, DoErase]; }; RollLeft: Menus.MenuProc = { pathViewerData: PathViewerData _ NARROW[clientData]; pathViewerData.xTranslation _ pathViewerData.xTranslation - 64; pathViewerData.redrawProc[clientData: pathViewerData.clientData]; }; RollRight: Menus.MenuProc = { pathViewerData: PathViewerData _ NARROW[clientData]; pathViewerData.xTranslation _ pathViewerData.xTranslation + 64; pathViewerData.redrawProc[clientData: pathViewerData.clientData]; }; MenuHit: Menus.MenuProc = { menuData: MenuData _ NARROW[clientData]; ButtonMonitor[menuData.pathViewerData, menuData.menuButton]; }; ButtonMonitor: ENTRY PROCEDURE [pathViewerData: PathViewerData, event: ATOM] = { pathViewerData.inputEvent _ event; pathViewerData.gotANewHit _ TRUE; NOTIFY pathViewerData.newEventArrival; }; ButtonPasser: PROCEDURE [pathViewerData: PathViewerData] = { WHILE pathViewerData.buttonPasserState = alive DO IF GotAButtonHit[pathViewerData] THEN pathViewerData.buttonProc[pathViewerData.clientData, pathViewerData.inputEvent, pathViewerData.controlPointX, pathViewerData.controlPointY]; ENDLOOP; pathViewerData.buttonPasserState _ dead; }; GotAButtonHit: ENTRY PROCEDURE [pathViewerData: PathViewerData] RETURNS [gotAHit: BOOLEAN] = { IF ~pathViewerData.gotANewHit THEN WAIT pathViewerData.newEventArrival; gotAHit _ pathViewerData.gotANewHit; pathViewerData.gotANewHit _ FALSE; }; NotifyProc: ViewerClasses.NotifyProc = { ENABLE UNWIND => { InputFocus.ReleaseButtons[]; WindowManager.RestoreCursor[]; }; pathViewerData: PathViewerData _ NARROW[self.data]; FOR list: LIST OF REF ANY _ input, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM x: ATOM => ButtonMonitor[pathViewerData, x]; z: TIPUser.TIPScreenCoords => { OPEN pathViewerData; controlPointX _ z.mouseX - xTranslation; controlPointY _ z.mouseY - yTranslation; IF controlPointX > xRight THEN xRight _ controlPointX ELSE IF controlPointX < xLeft THEN xLeft _ controlPointX; IF controlPointY > yTop THEN yTop _ controlPointY ELSE IF controlPointY < yBottom THEN yBottom _ controlPointY; }; ENDCASE => ERROR; ENDLOOP; }; DestroyProc: ViewerClasses.DestroyProc = { pathViewerData: PathViewerData _ NARROW[self.data]; DestroyButtonPasser[pathViewerData]; IF pathViewerData.quitProc # NIL THEN pathViewerData.quitProc[pathViewerData.clientData]; pathViewerData.viewer _ NIL; pathViewerData.outer _ NIL; }; DestroyButtonPasser: ENTRY PROCEDURE [pathViewerData: PathViewerData] = { pathViewerData.buttonPasserState _ dying; NOTIFY pathViewerData.newEventArrival; }; ScrollProc: ViewerClasses.ScrollProc = { pathViewerData: PathViewerData _ NARROW[self.data]; SELECT op FROM up => { pathViewerData.yTranslation _ pathViewerData.yTranslation + amount; pathViewerData.redrawProc[clientData: pathViewerData.clientData]; }; down => { pathViewerData.yTranslation _ pathViewerData.yTranslation - amount; pathViewerData.redrawProc[clientData: pathViewerData.clientData]; }; thumb => { pathViewerData.yTranslation _ - (pathViewerData.yBottom + (1. - amount/100.) * (pathViewerData.yTop - pathViewerData.yBottom)); pathViewerData.redrawProc[clientData: pathViewerData.clientData]; }; query => { OPEN pathViewerData; RETURN [Real.FixI[100. - (-yTranslation + self.ch - yBottom) * 100. / (yTop - yBottom)], Real.FixI[100. - (-yTranslation - yBottom) * 100. / (yTop - yBottom)]]; }; ENDCASE; }; Init: PROCEDURE [] = { pathViewerClass: ViewerClasses.ViewerClass; pathViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: PaintProc, notify: NotifyProc, destroy: DestroyProc, scroll: ScrollProc, tipTable: TIPUser.InstantiateNewTIPTable["PEViewer.TIP"], icon: document ] ]; ViewerOps.RegisterViewerClass[$PEViewer, pathViewerClass]; }; Init[]; END. ˜PEViewerImpl.mesa Last Edited by Plebon, August 23, 1983 4:17 pm Routines to manage the Path Editor viewer. These routines are essentially Frank Crow's Quick Viewer with a few improvements. This routine makes a viewer with the supplied name and menu labels. The supplied redrawProc is called when the screen must be redrawn (because the viewer changes size, etc.). The supplied quitProc is called to clean up on program termination (which occurs when the viewer is destroyed. Constrain the graphics area to lie in viewer space left over after menu, etc. are drawn. This routine calls the PaintProc to draw in the viewer. This routine repaints the screen with updates. This routine erases the contents the the graphics viewer. This routine moves the image to the left in the graphics viewer. This routine moves the image to the right in the graphics viewer. This routine handles client menu item hits. This routine stores a button event and notifies the button passing process. This process monitors button events. This routine waits for notification of an event, and determines if the event is a button hit. This routine responds to input events (from the TIP table). Expand work area if clicked outside existing bounds. This routine cleans up when the viewer is destroyed. This routine causes the button passer process to kill itself. This routine handles scrollbar mouse hits. This routine starts up the viewer. Ê ^˜Jšœ™J™.J™J™}J˜šÏk ˜ Jšœœ ˜Jšœ œ/˜?Jšœ œP˜^Jšœ œ˜"Jšœœ<˜GJšœ ˜ Jšœœ ˜Jšœœ˜Jšœœœ˜Jšœœ*˜7JšœœW˜jJšœ œ2˜AJšœœ˜$J˜J˜—šœ ˜Jšœ`˜gJšœ ˜J˜—Jšœœ ˜J˜Jšœ œ Ïc&˜DJšœ œž!˜>Jšœ œ ž+˜JJ˜Jšœœœ˜-šœœœ˜%Jšœœ˜"Jšœ˜Jšœœ˜&Jšœœ˜(Jšœ-˜-Jšœ œ˜Jšœ œ˜Jšœ œœ˜Jšœœ˜(Jšœž<˜UJšœž0˜JJšœž,˜CJšœ œ˜Jšœ˜—J˜Jšœœ˜/J˜Jšœ œœ ˜!šœ œœ˜Jšœ œ˜Jšœ˜Jšœ˜—J˜šÏn œœ œ œœœœœFœ'˜ÙJšœ ™ Jšœ&˜&Jšœ!œs˜—šœž˜2Jšœ ˜ šœ˜J˜J˜ Jšœ˜J˜!J˜—J˜—šœž˜.Jšœ ˜ šœ˜J˜ J˜Jšœ˜J˜#J˜—J˜—šœž˜.Jšœ ˜ šœ˜J˜ J˜Jšœ˜J˜$J˜—J˜—šœ*œœ˜Fšœžœ˜1Jšœ ˜ šœ˜Jšœ,˜,Jšœ˜šœ œ˜Jšœ$˜$Jšœ˜Jšœ˜—Jšœ˜Jšœ!˜!Jšœ˜—J˜—Jš˜—šœ+˜+Jšœ ˜ J˜ Jšœœ˜ J˜ Jšœ ˜Jšœ˜—šœ/˜/Jšœ˜šœ˜Jšœ˜Jšœž˜+Jšœž˜2Jšœž˜3Jšœž#˜8Jšœ ˜J˜—Jšœ˜—Jšœ\™\JšœE˜EJšœD˜DJšœ1˜1Jšœ?˜?Jšœ3˜3Jšœ1˜1Jšœ0˜0Jšœœ!˜=Jšœ˜J˜—J˜šŸ œœ œ;˜YJ™7Jšœ œ œ˜šœœœ˜Jšœœ˜1šœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜Jšœ˜—J˜—J˜—J˜šÏb œ˜&Jšœ.™.Jšœ!œ ˜3Jšœœ˜ Jšœ ˜ Jšœ ˜ šœœœ˜Jšœ"˜"Jšœ5˜5Jšœ˜—šœ˜Jšœ"˜"Jšœœ˜,Jšœ˜—J˜—J˜šŸœ˜J™9šŸœœ ˜-Jšœ-˜-Jšœ+˜+Jšœ7˜7Jšœ˜J˜—Jšœ!œ ˜4Jšœ-˜-J˜—J˜šŸœ˜JšœA™AJšœ!œ ˜4Jšœ?˜?JšœA˜AJ˜—J˜šŸ œ˜JšœB™BJšœ!œ ˜4Jšœ?˜?JšœA˜AJ˜J˜—šŸœ˜J™+Jšœœ ˜(Jšœ<˜