QuickViewerExampleImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Authored by Frank Crow
Last Edited by: Crow, September 25, 1986 5:56:20 pm PDT
Rick Beach, June 13, 1986 5:37:03 pm PDT
Rudimentary Imager exerciser
DIRECTORY
RealFns  USING [Cos, Sin],
QuickViewer USING [BuildViewer, DrawInViewer, QuickView],
Imager  USING [Context, Color, Font, DoSaveAll, SetColor, black, white, MaskVector,
 PathProc, MaskFill, MaskRectangle, SetFont, SetXY, ShowRope, Rectangle,
 SetStrokeWidth, SetStrokeEnd, SetStrokeJoint],
ImagerColor USING [ColorFromRGB],
ImagerFont USING [Find, Scale],
ImagerBackdoor USING [GetBounds],
Vector2 USING [VEC],
Rope USING [ROPE, Cat],
MessageWindow USING [Append];
QuickViewerExampleImpl: CEDAR PROGRAM
IMPORTS RealFns, QuickViewer, Imager, ImagerBackdoor, ImagerColor, ImagerFont, Rope, MessageWindow
~ BEGIN
drawMode: ATOM; -- type of object to draw
ShapeRec: TYPE ~ RECORD[ color: Imager.Color, drawMode: ATOM, place: Vector2.VEC ];
DisplayList: TYPE ~ RECORD[ SEQUENCE length: NAT OF ShapeRec ];
displayList: REF DisplayList ← NEW[ DisplayList[32] ]; -- display list of shapes
displayListPtr: NAT ← 0;
size: REAL ← 20.; -- size of objects (radius or side length)
stopMe: BOOLEANFALSE;
currentColor: Imager.Color ← Imager.black;
currentFont: Imager.Font ← NIL;
displayViewer: REF QuickViewer.QuickView ← NIL;
Sqr: PROCEDURE [number: REAL] RETURNS [REAL] ~ { RETURN[number * number]; };
Init: PROCEDURE [] ~ {
displayViewer ← QuickViewer.BuildViewer[
"QuickViewerExample",
LIST["Boxes", "Circles", "Octagons", "Xs", "Black", "White", "Red", "Green", "Blue", "Puce", "Spiral", "STOP!"],
ReDraw,
MenuHit,
ShutDown
];
};
This will be called whenever the mouse is moved or a button is pushed
MenuHit: PROCEDURE[bttn, choice: ATOM, x, y: REAL] ~ {
keys: Rope.ROPE;
SELECT choice FROM
$ControlShift => keys ← "ctrl-shift";
$Control => keys ← "ctrl";
$Shift => keys ← "shift";
ENDCASE => keys ← NIL;
SELECT bttn FROM
$Boxes, $Circles, $Xs, $Octagons => drawMode ← bttn;
$Black => currentColor ← ImagerColor.ColorFromRGB[ [ R: 0.0, G: 0.0, B: 0.0 ] ];
$White => currentColor ← ImagerColor.ColorFromRGB[ [ R: 1.0, G: 1.0, B: 1.0 ] ];
$Red => currentColor ← ImagerColor.ColorFromRGB[ [ R: 1.0, G: 0.0, B: 0.0 ] ];
$Green => currentColor ← ImagerColor.ColorFromRGB[ [ R: 0.0, G: 1.0, B: 0.0 ] ];
$Blue => currentColor ← ImagerColor.ColorFromRGB[ [ R: 0.0, G: 0.0, B: 1.0 ] ];
$Puce => currentColor ← ImagerColor.ColorFromRGB[ [ R: 0.5, G: 0.2, B: 0.4 ] ];
$Spiral => DrawSpiral[];
$STOP => { stopMe ← TRUE; ShowRope[ 100.0, 100.0, "STOP!" ]; };
$LeftButton, $LeftHeld => {
displayList[displayListPtr] ← [currentColor, drawMode, [x, y] ];
SELECT drawMode FROM
$Xs => DrawX[displayList[displayListPtr].place, size];
$Boxes => DrawBox[displayList[displayListPtr].place, size];
$Circles => DrawCircle[displayList[displayListPtr].place, size];
$Octagons => DrawOct[displayList[displayListPtr].place, size];
ENDCASE;
displayListPtr ← displayListPtr + 1;
IF displayListPtr = displayList.length THEN { -- get longer display list
newList: REF DisplayList ← NEW[ DisplayList[displayList.length + 32] ];
FOR i: NAT IN [0..displayListPtr) DO newList[i] ← displayList[i]; ENDLOOP;
displayList ← newList;
};
};
$MiddleButton => ShowRope[ x, y, Rope.Cat["MiddleButton ", keys] ];
$RightButton => ShowRope[ x, y, Rope.Cat["RightButton ", keys] ];
$MiddleHeld => ShowRope[ x, y, Rope.Cat["MiddleHeld ", keys] ];
$RightHeld => ShowRope[ x, y, Rope.Cat["RightHeld ", keys] ];
ENDCASE;
};
ReDraw: PROCEDURE [imagerCtx: Imager.Context, toDo: REF ANY] ~ { 
This will be called when the viewer is changed
savedColor: Imager.Color ← currentColor;
proc: PROC ~ { -- erase viewport first
Imager.SetColor[imagerCtx, Imager.white]; -- set color to white
Imager.MaskRectangle[imagerCtx, ImagerBackdoor.GetBounds[imagerCtx]]; -- fill screen
};
Imager.DoSaveAll[imagerCtx, proc];
FOR i: NAT IN [0..displayListPtr) DO
currentColor ← displayList[i].color;
SELECT displayList[i].drawMode FROM
$Xs => DrawX[displayList[i].place, size];
$Boxes => DrawBox[displayList[i].place, size];
$Circles => DrawCircle[displayList[i].place, size];
$Octagons => DrawOct[displayList[i].place, size];
ENDCASE;
ENDLOOP;
currentColor ← savedColor;
};
ShutDown: PROCEDURE [] ~ {
This will be called when the viewer is destroyed
MessageWindow.Append["QuickViewerExample Exited",TRUE]; -- say goodbye
};
DrawSpiral: PROC [] ~ {
oldPt, newPt: Vector2.VEC;
screen: Imager.Rectangle;
DoVector: PROC [context: Imager.Context] ~ {
Imager.SetStrokeWidth[context, 8.0];
Imager.SetStrokeEnd[context, round];
Imager.SetStrokeJoint[context, mitered];
Imager.SetColor[context, currentColor];
Imager.MaskVector[context, oldPt, newPt];
};
DoSetUp: PROC [context: Imager.Context] ~ {
screen ← ImagerBackdoor.GetBounds[context];
};
QuickViewer.DrawInViewer[displayViewer, DoSetUp];
oldPt ← [screen.w/2.0, screen.h/2.0];
FOR i: NAT IN [0..1000] DO
newPt ← [
i/10.0 * RealFns.Sin[i/40.0] + screen.w/2.0 ,
i/10.0 * RealFns.Cos[i/40.0] + screen.h/2.0
];
IF stopMe THEN { stopMe ← FALSE; EXIT; };
QuickViewer.DrawInViewer[displayViewer, DoVector];
oldPt ← newPt;
ENDLOOP;
};
The following are examples using callback from the Viewers package
DrawX: PROC [controlPoint: Vector2.VEC, leg: REAL] ~ {
DoDrawX: PROC [context: Imager.Context] ~ {
Imager.SetColor[context, currentColor];
Imager.MaskVector[
context,
[controlPoint.x - leg, controlPoint.y - leg],
[controlPoint.x + leg, controlPoint.y + leg]
];
Imager.MaskVector[
context,
[controlPoint.x - leg, controlPoint.y + leg],
[controlPoint.x + leg, controlPoint.y - leg]
];
};
QuickViewer.DrawInViewer[displayViewer, DoDrawX]; -- get viewer procs to call you back
};
DrawBox: PROC [controlPoint: Vector2.VEC, side: REAL] ~ {
DoDrawBox: PROC [context: Imager.Context] ~ {
Path: Imager.PathProc ~ {
moveTo[[controlPoint.x - side, controlPoint.y - side]];
lineTo[[controlPoint.x + side, controlPoint.y - side]];
lineTo[[controlPoint.x + side, controlPoint.y + side]];
lineTo[[controlPoint.x - side, controlPoint.y + side]];
lineTo[[controlPoint.x - side, controlPoint.y - side]];
};
Imager.SetColor[context, currentColor];
Imager.MaskFill[context, Path];
};
QuickViewer.DrawInViewer[displayViewer, DoDrawBox];
};
DrawCircle: PROC [controlPoint: Vector2.VEC, radius: REAL] ~ {
DoDrawCircle: PROC [context: Imager.Context] ~ {
Path: Imager.PathProc ~ {
x, y, theta: REAL ← 0.;
moveTo[[controlPoint.x + radius, controlPoint.y]];
UNTIL theta > 2*3.1416 DO
x ← radius * RealFns.Cos[theta] + controlPoint.x;
y ← radius * RealFns.Sin[theta] + controlPoint.y;
lineTo[[x, y]];
theta ← theta + 3.1416 / 12.;
ENDLOOP;
};
Imager.SetColor[context, currentColor];
Imager.MaskFill[context, Path];
};
QuickViewer.DrawInViewer[displayViewer, DoDrawCircle]; -- get viewer to call you back
};
DrawOct: PROC [controlPoint: Vector2.VEC, radius: REAL] ~ { -- draw an octagon
DoDrawOct: PROC [context: Imager.Context] ~ {
Path: Imager.PathProc ~ {
x, y, theta: REAL ← 0.;
moveTo[[controlPoint.x + radius , controlPoint.y - radius/3.]];
lineTo[[controlPoint.x + radius , controlPoint.y + radius/3.]];
lineTo[[controlPoint.x + radius/3., controlPoint.y + radius]];
lineTo[[controlPoint.x - radius/3., controlPoint.y + radius]];
lineTo[[controlPoint.x - radius, controlPoint.y + radius/3.]];
lineTo[[controlPoint.x - radius, controlPoint.y - radius/3.]];
lineTo[[controlPoint.x - radius/3., controlPoint.y - radius]];
lineTo[[controlPoint.x + radius/3., controlPoint.y - radius]];
lineTo[[controlPoint.x + radius, controlPoint.y - radius/3.]];
};
Imager.SetColor[context, currentColor];
Imager.MaskFill[context, Path];
};
QuickViewer.DrawInViewer[displayViewer, DoDrawOct];
};
ShowRope: PROC[x, y: REAL, rope: Rope.ROPE] ~ {
DoShowRope: PROC[context: Imager.Context] ~ {
IF currentFont = NIL THEN {
currentFont ← ImagerFont.Find["Xerox/Pressfonts/TimesRoman-MRR"];
currentFont ← ImagerFont.Scale[currentFont, 12.0];
};
Imager.SetColor[context, currentColor];
Imager.SetFont[context, currentFont];
Imager.SetXY[context, [x, y]];
Imager.ShowRope[context, rope];
};
QuickViewer.DrawInViewer[displayViewer, DoShowRope];
};
Init[];
END.