DIRECTORY Imager USING [Context, SetColor, ColorOperator, MaskRectangle, SetFont, SetStrokeWidth, MaskStroke, MaskVector, RotateT, TranslateT, Color, Font, SetXY, ShowRope, PathProc], ImagerBackdoor USING [GetBounds], ImagerColor USING [ColorFromRGB], ImagerColorOperator USING [RGBLinearColorModel], ImagerFont USING [Scale, Find], ImagerInterpress USING [Ref, Create, DeclareColorOperator, DeclareFont, DoPage, Close], Draw2d, Containers USING [Container, Create, ChildXBound, ChildYBound], Menus USING [Menu, CreateMenu, AppendMenuEntry, CreateEntry, MouseButton], ViewerClasses USING [Viewer, ViewerRec, ViewerClass, ViewerClassRec, NotifyProc, PaintProc, DestroyProc, ScrollProc, HScrollProc], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass], TIPUser USING [InstantiateNewTIPTable ,TIPScreenCoords], Icons USING [NewIconFromFile], IO USING [PutFR, real], Convert USING [RopeFromInt], Vector2 USING [VEC], Rope USING [ROPE, Cat, Equal], Real USING [FixI, Fix], MessageWindow USING [Append], MintDisplay; MintDisplayImpl: CEDAR MONITOR IMPORTS Imager, ImagerColor, ImagerColorOperator, ImagerInterpress, ImagerFont, ImagerBackdoor, Draw2d, IO, Convert, Containers, Menus, MessageWindow, ViewerOps, TIPUser, Rope, Real, Icons EXPORTS MintDisplay ~ BEGIN OPEN MintDisplay; defaultScalex: REAL _ 0.01; currentFont: Imager.Font _ ImagerFont.Find["Xerox/TiogaFonts/Helvetica12B"]; pressFont: Imager.Font _ ImagerFont.Scale[ImagerFont.Find["Xerox/PressFonts/Helvetica-brr"], 12.0]; pressScale: REAL _ 0.0002; fineStroke: REAL _ 1.0; coarseStroke: REAL _ 3.0; timeScale: REAL _ 1000.0; valueForTrue: REAL _ 2500.10; -- instead of 2500.0 to avoid 5000.0 -> "logical 2" Init: PROC ~ { mintQPictureClass: ViewerClasses.ViewerClass; -- Declare type mintQPictureClass _ NEW [-- Get record and fill it with procedure names ViewerClasses.ViewerClassRec _ [ notify: NotifyProc, -- procedure to respond to input events (from TIP table) paint: PaintProc, -- procedure called when viewer contents must be repainted destroy: DestroyProc, -- procedure to clean up when done scroll: VScrollProc, -- procedure to respond to vertical scroll bar hits hscroll: HScrollProc, -- procedure to respond to horizontal scroll bar hits tipTable: TIPUser.InstantiateNewTIPTable["QuickViewer.TIP"], cursor: crossHairsCircle -- cursor when mouse is in viewer ] ]; ViewerOps.RegisterViewerClass[$MintQViewer, mintQPictureClass];-- Register with viewers }; BuildViewer: PUBLIC PROC[viewerTitle: Rope.ROPE] RETURNS[viewer: Viewer] ~ { menu: Menus.Menu; container: Containers.Container; graphData: ViewerData _ NEW[ViewerDataRec]; menu _ Menus.CreateMenu[]; Menus.AppendMenuEntry[ menu: menu, -- enter "Reset" button entry: Menus.CreateEntry[ name: "Reset", proc: SetDefaults, clientData: graphData, documentation: "Reset graphViewer" ] ]; Menus.AppendMenuEntry[ menu: menu, -- enter "Mag" button entry: Menus.CreateEntry[ name: "Mag", proc: MagOnOff, clientData: graphData, documentation: "Mag switch" ] ]; Menus.AppendMenuEntry[ menu: menu, -- enter "Axis" button entry: Menus.CreateEntry[ name: "Axis", proc: TimeAxisBut, clientData: graphData, documentation: "Mag switch" ] ]; Menus.AppendMenuEntry[ menu: menu, -- enter "sizeX" button entry: Menus.CreateEntry[ name: "sizeX", proc: ScaleX, clientData: graphData, documentation: "Zoom x2" ] ]; Menus.AppendMenuEntry[ menu: menu, -- enter "MagSizeX" button entry: Menus.CreateEntry[ name: "MagSizeX", proc: MagScaleX, clientData: graphData, documentation: "Zoom x2mag" ] ]; Menus.AppendMenuEntry[ menu: menu, -- enter "sizeY" button entry: Menus.CreateEntry[ name: "sizeY", proc: ScaleY, clientData: graphData, documentation: "Zoom :2mag" ] ]; container _ Containers.Create[ info: [ name: viewerTitle, -- define outer viewer menu: menu, iconic: TRUE, icon: Icons.NewIconFromFile["Mint.icons", 3], column: left, scrollable: FALSE ] ]; viewer _ ViewerOps.CreateViewer[ -- define graphics area flavor: $MintQViewer, info: [ parent: container, wx: 0, wy: 0, -- position WRT parent ww: container.ww, -- CHildXBound below wh: container.wh, -- CHildXBound below name: "Oscilloscope", caption: FALSE, scrollable: TRUE, hscrollable: TRUE, data: graphData ], paint: FALSE ]; Containers.ChildXBound[container, viewer]; Containers.ChildYBound[container, viewer]; graphData.xMax _ MAX[viewer.cw,10.0]; -- this dirty hack because graphData.yMax _ MAX[viewer.ch,10.0]; -- cw and ch seems to be zero at that point ??? ViewerOps.PaintViewer[container, all]; -- load up the viewer (paint it) }; PaintProc: ViewerClasses.PaintProc ~ { -- repaint screen for updates dc: Imager.Context ~ context; viewerData: ViewerData ~ NARROW[self.data]; SELECT whatChanged FROM NIL => { -- window resized, redraw ReDraw[self]; }; ENDCASE => { -- call path for DrawInViewer NARROW[whatChanged, REF PROC[Imager.Context]]^[context]; }; }; DrawInViewer: PROCEDURE [viewer: Viewer, proc: PROC [Imager.Context]] ~ { drawProc: REF PROC[Imager.Context] _ NIL; TRUSTED { drawProc _ NEW[PROC[Imager.Context] _ proc]; }; ViewerOps.PaintViewer[ viewer: viewer,-- pass record to viewer painter hint: client, whatChanged: drawProc, clearClient: FALSE ]; }; SetDefaults: PROCEDURE [parent: REF ANY, clientData: REF ANY, mouseButton: Menus.MouseButton, shift, control: BOOL] ~ { viewerData: ViewerData ~ NARROW[clientData]; container: Viewer ~ NARROW[parent]; viewer: Viewer ~ container.child; viewerData.xTranslation _ 0.0; XScaleDisplayValues[viewerData.displayList, defaultScalex/viewerData.scalex, viewerData]; viewerData.scalex _ defaultScalex; viewerData.magOn _ FALSE; ReDraw[viewer]; }; TimeAxisBut: PROCEDURE [parent: REF ANY, clientData: REF ANY, mouseButton: Menus.MouseButton, shift, control: BOOL] ~ { viewerData: ViewerData ~ NARROW[clientData]; container: Viewer ~ NARROW[parent]; viewer: Viewer ~ container.child; TimeAxis[timeScale, viewer, red]; }; ScaleX: PROCEDURE [parent: REF ANY, clientData: REF ANY, mouseButton: Menus.MouseButton, shift, control: BOOL] ~ { viewerData: ViewerData ~ NARROW[clientData]; container: Viewer ~ NARROW[parent]; viewer: Viewer ~ container.child; alpha: REAL _ 2.0; IF mouseButton=yellow THEN RETURN; IF mouseButton=blue THEN alpha _ 0.5; viewerData.scalex _ alpha*viewerData.scalex; -- Zoom alpha XScaleDisplayValues[viewerData.displayList, alpha, viewerData]; ReDraw[viewer]; }; MagScaleX: PROCEDURE [parent: REF ANY, clientData: REF ANY, mouseButton: Menus.MouseButton, shift, control: BOOL] ~ { viewerData: ViewerData ~ NARROW[clientData]; container: Viewer ~ NARROW[parent]; viewer: Viewer ~ container.child; alpha: REAL _ 2.0; IF mouseButton=yellow THEN RETURN; IF mouseButton=blue THEN alpha _ 0.5; viewerData.magScale _ alpha*viewerData.magScale; XScaleDisplayValues[viewerData.magDisplayList, alpha, viewerData]; ReDraw[viewer]; }; ScaleY: PROCEDURE [parent: REF ANY, clientData: REF ANY, mouseButton: Menus.MouseButton, shift, control: BOOL] ~ { viewerData: ViewerData ~ NARROW[clientData]; container: Viewer ~ NARROW[parent]; viewer: Viewer ~ container.child; alpha: REAL _ 2.0; IF mouseButton=yellow THEN RETURN; IF mouseButton=blue THEN alpha _ 0.5; viewerData.scaley _ alpha*viewerData.scaley; viewerData.inter _ alpha*viewerData.inter; YScaleDisplayValues[viewerData.displayList, alpha, viewerData]; YScaleDisplayValues[viewerData.magDisplayList, alpha, viewerData]; ReDraw[viewer]; }; MagOnOff: PROCEDURE [parent: REF ANY, clientData: REF ANY, mouseButton: Menus.MouseButton, shift, control: BOOL] ~ { viewerData: ViewerData ~ NARROW[clientData]; container: Viewer ~ NARROW[parent]; viewer: Viewer ~ container.child; viewerData.magOn _ ~viewerData.magOn; ReDraw[viewer]; }; XScaleDisplayValues: PROCEDURE [displayList: DisplayList, alpha: REAL, viewerData: ViewerData] ~ { viewerData.xMin _ displayList.first.list.first.x; viewerData.xMax _ displayList.first.list.first.x; FOR dList: DisplayList _ displayList, dList.rest UNTIL dList=NIL DO FOR ilist: VecList _ dList.first.list, ilist.rest UNTIL ilist=NIL DO ilist.first.x _ alpha*ilist.first.x; viewerData.xMin _ MIN[viewerData.xMin, ilist.first.x]; viewerData.xMax _ MAX[viewerData.xMax, ilist.first.x]; ENDLOOP; ENDLOOP; }; YScaleDisplayValues: PROCEDURE [displayList: DisplayList, alpha: REAL, viewerData: ViewerData] ~ { n: INT _ 0; viewerData.yMin _ displayList.first.list.first.y; viewerData.yMax _ displayList.first.list.first.y; FOR dList: DisplayList _ displayList, dList.rest UNTIL dList=NIL DO n _ n+1; FOR ilist: VecList _ dList.first.list, ilist.rest UNTIL ilist=NIL DO ilist.first.y _ alpha*ilist.first.y; viewerData.yMin _ MIN[viewerData.yMin, ilist.first.y]; viewerData.yMax _ MAX[viewerData.yMax, ilist.first.y]; ENDLOOP; ENDLOOP; viewerData.yMax _ viewerData.yMax+n*viewerData.inter; }; NotifyProc: ViewerClasses.NotifyProc ~ { viewerData: ViewerData ~ NARROW[self.data]; x, y, t: REAL; IF ISTYPE[input.first, TIPUser.TIPScreenCoords] -- If input is coords from mouse THEN { mousePlace: TIPUser.TIPScreenCoords _ NARROW[input.first]; x _ mousePlace.mouseX; y _ mousePlace.mouseY; IF ISTYPE[input.rest.first, ATOM] THEN { buttonName: ATOM _ NARROW[input.rest.first]; shft, ctrl: BOOLEAN _ FALSE; restOfInput: LIST OF REF ANY _ input.rest.rest; WHILE restOfInput # NIL DO SELECT NARROW[restOfInput.first, ATOM] FROM $Shift => shft _ TRUE; $Ctrl => ctrl _ TRUE; ENDCASE; -- ignore anything else restOfInput _ restOfInput.rest; ENDLOOP; SELECT buttonName FROM $LeftButton => { IF viewerData.magOn THEN t _ (x-viewerData.magOr)/viewerData.magScale ELSE t _ (x-viewerData.xTranslation)/viewerData.scalex; DrawRope[[x, y], IO.PutFR["t:%d", IO.real[t]], self, red]; }; $MiddleButton => {}; $RightButton => { IF ~viewerData.magOn THEN { viewerData.magOr _ (x-viewerData.xTranslation)/viewerData.scalex; ReDraw[self]; }; }; $LeftHeld => {}; $MiddleHeld => {}; $RightHeld => {}; ENDCASE; }; }; }; DestroyProc: ViewerClasses.DestroyProc ~ { MessageWindow.Append["MintDisplay Exited",TRUE]; -- say goodbye }; VScrollProc: ViewerClasses.ScrollProc ~ { selfData: ViewerData ~ NARROW[self.data]; SELECT op FROM up => { selfData.yTranslation _ MIN[selfData.yTranslation + amount, selfData.yMin+self.ch]; }; down => { selfData.yTranslation _ MAX[selfData.yTranslation - amount, -selfData.yMax]; }; thumb => { selfData.yTranslation _ amount * (selfData.yMax - selfData.yMin)/100.0; }; query => { top _ MAX[0, Real.FixI[100.0*(selfData.yMax + selfData.yTranslation - self.ch) /(selfData.yMax - selfData.yMin)]]; bottom _ MIN[100, Real.FixI[100.0*(selfData.yMax + selfData.yTranslation) /(selfData.yMax - selfData.yMin)]]; RETURN; }; ENDCASE; ReDraw[self]; }; HScrollProc: ViewerClasses.HScrollProc ~ { selfData: ViewerData ~ NARROW[self.data]; IF selfData.magOn THEN { SELECT op FROM right => { selfData.magOr _ MIN[selfData.magOr + amount, selfData.xMin*selfData.magScale/selfData.scalex + self.cw]; }; left => { selfData.magOr _ MAX[selfData.magOr - amount, -selfData.xMax*selfData.magScale/selfData.scalex]; }; thumb => { selfData.magOr _ - amount * (selfData.xMax-selfData.xMin)*0.01 - selfData.xMin; }; query => { left _ MAX[0, Real.FixI[100.0*(-selfData.magOr - selfData.xMin) / (selfData.xMax-selfData.xMin)]]; right _ MIN[100, Real.FixI[100.0*(-selfData.magOr - selfData.xMin + self.cw*selfData.scalex/selfData.magScale) /(selfData.xMax - selfData.xMin)]]; RETURN; }; ENDCASE; } ELSE { SELECT op FROM right => { selfData.xTranslation _ MIN[selfData.xTranslation + amount, selfData.xMin + self.cw]; }; left => { selfData.xTranslation _ MAX[selfData.xTranslation - amount, -selfData.xMax]; }; thumb => { selfData.xTranslation _ - amount * (selfData.xMax-selfData.xMin)*0.01 - selfData.xMin; }; query => { left _ MAX[0, Real.FixI[100.0*(-selfData.xTranslation - selfData.xMin) / (selfData.xMax-selfData.xMin)]]; right _ MIN[100, Real.FixI[100.0*(-selfData.xTranslation - selfData.xMin + self.cw) /(selfData.xMax - selfData.xMin)]]; RETURN; }; ENDCASE; }; ReDraw[self]; }; DrawVect: PUBLIC PROC [or: VEC, ex: VEC, viewer: Viewer, color: Imager.Color] ~ { DoDrawVect: PROC [context: Imager.Context] ~ { Imager.SetColor[context, color]; Imager.MaskVector[context, [or.x+viewerData.xTranslation, or.y+viewerData.yTranslation], [ex.x+viewerData.xTranslation, ex.y+viewerData.yTranslation]]; }; viewerData: ViewerData ~ NARROW[viewer.data]; DrawInViewer[viewer, DoDrawVect];-- ask the viewer procs to call you back }; DrawRope: PUBLIC PROC[pos: VEC, rope: Rope.ROPE, viewer: Viewer, color: Imager.Color] ~ { DoDrawRope: PROC [context: Imager.Context] ~ { ShowRope[pos.x, pos.y, rope, context, color]; }; DrawInViewer[viewer, DoDrawRope];-- ask the viewer procs to call you back }; DrawVectAbs: PROC [or: VEC, ex: VEC, viewer: Viewer, color: Imager.Color] ~ { DoDrawVectAbs: PROC [context: Imager.Context] ~ { Imager.SetColor[context, color]; Imager.MaskVector[context, or, ex]; }; viewerData: ViewerData ~ NARROW[viewer.data]; DrawInViewer[viewer, DoDrawVectAbs];-- ask the viewer procs to call you back }; TimeAxis: PUBLIC PROC [unit: REAL, viewer: Viewer, color: Imager.Color] ~ { DoTimeAxis: PROC [context: Imager.Context] ~ { Path: Imager.PathProc ~ { FOR n:INT IN [n1..n2] DO moveTo[[x+orx+n*50.0, y]]; lineTo[[x+orx+n*50.0, y+10]]; ENDLOOP; }; Imager.SetColor[context, color]; Imager.MaskStroke[context, Path]; Imager.SetFont[context, currentFont]; tscale _ 1/(tscale*unit); FOR n:INT IN [n1..n2] DO Imager.SetXY[context, [x+orx+n*50.0, y-10.0]]; Imager.ShowRope[context, IO.PutFR["%d", IO.real[x+n*50.0*tscale]]]; ENDLOOP; }; viewerData: ViewerData ~ NARROW[viewer.data]; tscale, orx, x, y: REAL; n1, n2: INT; x _ 0.0; y _ viewer.ch*0.5; IF viewerData.magOn THEN { orx _ -viewerData.magOr*viewerData.magScale - viewerData.xTranslation; tscale _ viewerData.magScale } ELSE { orx _ viewerData.xTranslation; tscale _ viewerData.scalex }; n1 _ Real.Fix[-orx/50.0]; n2 _ Real.Fix[(viewer.cw-orx)/50.0]; DrawInViewer[viewer, DoTimeAxis]; }; WriteList: PROC [orx, ory: REAL, vecList: VecList, context: Imager.Context, color: Imager.Color, radix: REAL _ 1.0, firstx, lastx: REAL] ~ { x1, y1: REAL; y2: REAL; n: INT; IF vecList=NIL THEN RETURN; Imager.SetColor[context, color]; y1 _ ory; y2 _ y1+10.0; FOR ilist: VecList _ vecList, ilist.rest UNTIL ilist=NIL DO x1 _ orx+ilist.first.x; IF x1>lastx THEN LOOP; IF x1-viewerData.inter THEN { --simplified clipping Imager.SetColor[context, green]; Draw2d.Solid[context, [0.0, or.y], [1000.0, or.y]]; ShowRope[0.0, or.y + viewerData.inter*0.5, dList.first.name, context, blue]; IF dList.first.analog THEN DrawList[or.x, or.y, dList.first.list, context, black, 0.0, viewer.cw] ELSE WriteList[or.x, or.y, dList.first.list, context, black, radix, 0.0, viewer.cw]; }; or.y _ viewerData.inter + or.y; IF or.y>viewer.ch THEN RETURN; ENDLOOP; }; viewerData: ViewerData ~ NARROW[viewer.data]; displayList: DisplayList; radix: REAL _ valueForTrue*viewerData.scaley; IF viewerData.displayList=NIL THEN RETURN; DrawInViewer[viewer, DrawToScreen]; }; ProduceIPMaster: PUBLIC PROC [viewer: Viewer] ~ { DrawToIP: PROC [context: Imager.Context] ~ { Path: Imager.PathProc ~ { x, y: REAL; x _ dRec.or.x+dRec.list.first.x; y _ yGraph+dRec.or.y+dRec.list.first.y; moveTo[[x+viewerData.xTranslation, y+viewerData.yTranslation]]; FOR ilist: VecList _ dRec.list.rest, ilist.rest UNTIL ilist=NIL DO x _ dRec.or.x+ilist.first.x; y _ yGraph+dRec.or.y+ilist.first.y; lineTo[[x+viewerData.xTranslation, y+viewerData.yTranslation]]; ENDLOOP; }; yGraph: REAL _ 0.0; dRec: DisplayListRec; Imager.TranslateT[context, [viewer.cw, -10.0]]; Imager.RotateT[context, 90.0]; FOR dList: DisplayList _ viewerData.displayList, dList.rest UNTIL dList=NIL DO dRec _ dList.first; Imager.SetStrokeWidth[context, fineStroke]; Imager.SetColor[context, green]; Imager.MaskVector[context, [0.0, yGraph+viewerData.yTranslation+dRec.or.y], [750.0, yGraph+viewerData.yTranslation+dRec.or.y]]; Imager.SetStrokeWidth[context, coarseStroke]; Imager.SetColor[context, black]; Imager.MaskStroke[context, Path]; Imager.SetColor[context, blue]; Imager.SetFont[context, pressFont]; Imager.SetXY[context, [0.0, yGraph+dRec.or.y + 0.5*viewerData.inter]]; Imager.ShowRope[context, dRec.name]; yGraph _ yGraph+viewerData.inter; ENDLOOP; }; -- DrawToIP viewerData: ViewerData ~ NARROW[viewer.data]; fileName: Rope.ROPE _ Rope.Cat["///Temp/Mint/", "Dummy", ".interpress"]; ip: ImagerInterpress.Ref _ ImagerInterpress.Create[fileName]; rgbLinear: Imager.ColorOperator ~ ImagerColorOperator.RGBLinearColorModel[255]; ImagerInterpress.DeclareColorOperator[ip, rgbLinear]; ImagerInterpress.DeclareFont[ip, pressFont]; ImagerInterpress.DoPage[ip, DrawToIP, pressScale]; ImagerInterpress.Close[ip]; MessageWindow.Append[Rope.Cat[fileName, " created"],TRUE]; }; UpdateDisplay: PUBLIC PROC [displayList: DisplayList, viewer: Viewer] ~ { x, xMag, y :REAL; vl1, vl2: VecList; viewerData: ViewerData ~ NARROW[viewer.data]; FOR idisplayList: DisplayList _ displayList, idisplayList.rest UNTIL idisplayList=NIL DO vDisplayList: DisplayList _ viewerData.displayList; mDisplayList: DisplayList _ viewerData.magDisplayList; UNTIL vDisplayList=NIL DO IF Rope.Equal[vDisplayList.first.name, idisplayList.first.name] THEN { IF ~Rope.Equal[mDisplayList.first.name, idisplayList.first.name] THEN ERROR; -- both orders are no longer = vDisplayList.first.list _ CONS[[0.0, 0.0], vDisplayList.first.list]; vl1 _ vDisplayList.first.list; mDisplayList.first.list _ CONS[[0.0, 0.0], mDisplayList.first.list]; vl2 _ mDisplayList.first.list; FOR iVecList: VecList _ idisplayList.first.list, iVecList.rest UNTIL iVecList=NIL DO x _ viewerData.scalex*iVecList.first.x; xMag _ viewerData.magScale*iVecList.first.x; y _ viewerData.scaley*iVecList.first.y; vl1.rest _ CONS[[x: x, y: y], vl1.rest]; -- add before the old 1st el of the list vl1 _ vl1.rest; vl2.rest _ CONS[[x: xMag, y: y], vl2.rest]; -- add before the old 1st el of the list vl2 _ vl2.rest; ENDLOOP; vDisplayList.first.list _ vDisplayList.first.list.rest; mDisplayList.first.list _ mDisplayList.first.list.rest; EXIT; }; vDisplayList _ vDisplayList.rest; mDisplayList _ mDisplayList.rest; ENDLOOP; ENDLOOP; }; LoadDisplay: PUBLIC PROC [displayList: DisplayList, viewer: Viewer] ~ { x, xMag, y :REAL; vl1, vl2: VecList; viewerData: ViewerData ~ NARROW[viewer.data]; displayListRec: DisplayListRec; magDisplayListRec: DisplayListRec; displayListRec.or _ [0.0, 0.0]; magDisplayListRec.or _ [0.0, 0.0]; viewerData.displayList _ NIL; viewerData.magDisplayList _ NIL; FOR idisplayList: DisplayList _ displayList, idisplayList.rest UNTIL idisplayList=NIL DO displayListRec.name _ idisplayList.first.name; displayListRec.analog _ idisplayList.first.analog; magDisplayListRec.name _ idisplayList.first.name; magDisplayListRec.analog _ idisplayList.first.analog; displayListRec.list _ LIST[[0.0, 0.0]]; --dummy first el vl1 _ displayListRec.list; -- pointer to the last el of list magDisplayListRec.list _ LIST[[0.0, 0.0]]; -- same things vl2 _ magDisplayListRec.list; FOR iVecList: VecList _ idisplayList.first.list, iVecList.rest UNTIL iVecList=NIL DO x _ viewerData.scalex*iVecList.first.x; xMag _ viewerData.magScale*iVecList.first.x; y _ viewerData.scaley*iVecList.first.y; vl1.rest _ LIST[[x: x, y: y]]; -- add to the end of the list vl1 _ vl1.rest; vl2.rest _ LIST[[x: xMag, y: y]]; vl2 _ vl2.rest; ENDLOOP; displayListRec.list _ displayListRec.list.rest; --remove the dummy 1st el magDisplayListRec.list _ magDisplayListRec.list.rest; viewerData.displayList _ CONS[displayListRec, viewerData.displayList]; viewerData.magDisplayList _ CONS[magDisplayListRec, viewerData.magDisplayList]; ENDLOOP; ReDraw[viewer]; }; black: PUBLIC Imager.Color _ ImagerColor.ColorFromRGB[ [ R: 0.0, G: 0.0, B: 0.0 ] ]; white: PUBLIC Imager.Color _ ImagerColor.ColorFromRGB[ [ R: 1.0, G: 1.0, B: 1.0 ] ]; red: PUBLIC Imager.Color _ ImagerColor.ColorFromRGB[ [ R: 1.0, G: 0.0, B: 0.0 ] ]; green: PUBLIC Imager.Color _ ImagerColor.ColorFromRGB[ [ R: 0.0, G: 1.0, B: 0.0 ] ]; blue: PUBLIC Imager.Color _ ImagerColor.ColorFromRGB[ [ R: 0.0, G: 0.0, B: 1.0 ] ]; puce: PUBLIC Imager.Color _ ImagerColor.ColorFromRGB[ [ R: 0.5, G: 0.2, B: 0.4 ] ]; Init[]; END. lMintDisplayImpl.mesa Copyright (C) 1986 by Xerox Corporation. All rights reserved. Christian LeCocq August 1, 1986 3:33:31 pm PDT Imager Viewers others Process USING [Detach], -- Tip table (translates mouse events to commands) TRUSTED { Process.Detach[FORK ButtonPasser]; }; -- Start up button event monitor graphState: State _ NEW[StateRep _ []]; PROC [self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL] Pass procedure to PaintProc NotifyProc ~ PROC[self: Viewer, input: LIST OF REF ANY] IF ISTYPE[input.rest.first, ATOM] AND (gotaNewOne = FALSE ) THEN { ButtonMonitor[self, buttonName, ctrl, shft]; Clean up on exit (viewer destroyed) This will be called when the viewer is destroyed Acts on scrollbar mouse hits ScrollProc ~ PROC[self: Viewer, op: ScrollOp, amount: INTEGER] RETURNS[top, bottom: INTEGER _ LAST[INTEGER]]; ScrollOp: TYPE = {query, up, down, thumb} Acts on hscrollbar mouse hits HScrollProc ~ PROC[self: Viewer, op: HScrollOp, amount: INTEGER] RETURNS[left, right: INTEGER _ LAST[INTEGER]]; HScrollOp: TYPE = {query, left, right, thumb} DrawList: PROC [orx, ory: REAL, vecList: VecList, context: Imager.Context, color: Imager.Color, firstx, lastx: REAL] ~ { Path: Imager.PathProc ~ { x, y: REAL; x _ orx+vecList.first.x; y _ ory+vecList.first.y; moveTo[[x, y]]; FOR ilist: VecList _ vecList.rest, ilist.rest UNTIL ilist=NIL DO x _ orx+ilist.first.x; y _ ory+ilist.first.y; lineTo[[x, y]]; IF xœ˜FKšœ?œœŸ˜kKšœœ&˜DKšœ˜Kšœœ&˜DKšœ˜šœ<œ œ˜TKšœ(˜(Kšœ,˜,Kšœ'˜'Kšœ œŸ(˜QKšœ˜Kšœ œŸ(˜TKšœ˜Kšœ˜—Kšœ7˜7Kšœ7˜7Kšœ˜K˜—Kšœ!˜!Kšœ!˜!Kšœ˜—Kšœ˜—K˜K˜—š  œ œ"œ ˜GJ™SJšœ œ˜Jšœ˜Jšœœ˜-Jšœ˜Jšœ"˜"Jšœ˜Jšœ"˜"Jšœœ˜Jšœœ˜ šœ;œœ˜XKšœ.˜.Kšœ2˜2Kšœ1˜1Kšœ5˜5KšœœŸ˜8KšœŸ!˜