PieViewersImpl.mesa
Copyright © 1982, 1983, 1984 Xerox Corporation. All rights reserved.
Michael Plass, November 2, 1982 10:56 am
Last Edited by: Beach, May 24, 1983 9:13 am
Doug Wyatt, September 5, 1984 3:45:51 pm PDT
DIRECTORY
Imager USING [black, Context, MaskFill, SetColor, VEC, white],
ImagerOps USING [ImagerFromGraphics],
ImagerPath USING [PathProc],
PieViewers USING [PieViewer],
Real USING [RoundI, SqRt],
RealFns USING [Cos, Sin, Tan],
ViewerClasses USING [PaintProc, Viewer, ViewerClass, ViewerClassRec],
ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass];
PieViewersImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerOps, Real, RealFns, ViewerOps
EXPORTS PieViewers
= BEGIN
PieViewer: TYPE = PieViewers.PieViewer;
DataRec:
TYPE =
RECORD [
total: REAL, -- what the entire circle is worth
amount: REAL, -- what amount is currently on
granularity: REAL -- display will not change if the new amount is of the same grain
];
Create:
PUBLIC
PROC [parent: ViewerClasses.Viewer, x, y:
INTEGER ← 0, diameter:
INTEGER ← 16, total:
REAL ← 100, divisions:
NAT ← 25]
RETURNS [pieViewer: PieViewer] = TRUSTED {
data: REF DataRec ← NEW[DataRec];
data.total ← total;
data.granularity ← total/divisions;
pieViewer ← ViewerOps.CreateViewer[flavor: $PieViewer, info: [parent: parent, wx: x, wy: y, ww: diameter, wh: diameter, data: data, border: FALSE], paint: FALSE];
Set[pieViewer, 0];
};
Set:
PUBLIC
PROC [pieViewer: PieViewer, amount:
REAL] =
BEGIN ENABLE ANY => GOTO Quit;
d: REF DataRec ← NARROW[pieViewer.data];
IF amount=d.total
OR amount=0
OR Real.RoundI[d.amount/d.granularity] # Real.RoundI[amount/d.granularity]
THEN
BEGIN
d.amount ← amount;
TRUSTED{ViewerOps.PaintViewer[pieViewer, client, FALSE, $Update]};
END;
EXITS Quit => {}
END;
PieViewerPaint: ViewerClasses.PaintProc =
BEGIN
imager: Imager.Context ~ ImagerOps.ImagerFromGraphics[context];
d: REF DataRec ← NARROW[self.data];
diameter: REAL ← self.ww;
radius: REAL ← diameter/2;
center: VEC ~ [radius, radius];
blackPart: ImagerPath.PathProc ~ {
p: VEC ~ [radius, diameter-0.51];
moveTo[center];
lineTo[p];
ArcAround[curveTo, p, center, TwoPi*d.amount/d.total];
lineTo[center];
};
whitePart: ImagerPath.PathProc ~ {
p: VEC ~ [radius, diameter];
moveTo[center];
lineTo[p];
ArcAround[curveTo, p, center, TwoPi*(d.amount/d.total-1)];
lineTo[center];
};
Imager.SetColor[imager, Imager.black];
Imager.MaskFill[imager, blackPart];
Imager.SetColor[imager, Imager.white];
Imager.MaskFill[imager, whitePart];
END;
TwoPi: REAL = 2*3.14159265;
VEC: TYPE = Imager.VEC;
Abs:
PROCEDURE [a:
VEC]
RETURNS [
REAL] =
INLINE
{RETURN[Real.SqRt[a.x*a.x+a.y*a.y]]};
Mul:
PROCEDURE [a:
VEC, b:
VEC]
RETURNS [
VEC] =
INLINE
{RETURN[[(a.x*b.x - a.y*b.y), (a.x*b.y + a.y*b.x)]]}; -- complex product
Add:
PROCEDURE [a:
VEC, b:
VEC]
RETURNS [
VEC] =
INLINE
{RETURN[[a.x+b.x,a.y+b.y]]}; -- same as vector sum
Sub:
PROCEDURE [a:
VEC, b:
VEC]
RETURNS [
VEC] =
INLINE
{RETURN[[a.x-b.x,a.y-b.y]]}; -- same as vector difference
ShortArcAround:
PROC [curveTo:
PROC[p1, p2, p3:
VEC], p0:
VEC, center:
VEC, angle:
REAL]
RETURNS[VEC] =
BEGIN -- good for angles of less than about a quarter circle
init: VEC ← Sub[p0, center];
IF angle#0
THEN
BEGIN
final: VEC ← Mul[init, [RealFns.Cos[angle], RealFns.Sin[angle]]];
velocityRatio: REAL ← (4.0/3.0)*RealFns.Tan[angle/4];
b1: VEC ← Add[center, Add[init, Mul[init, [0,velocityRatio]]]];
b2: VEC ← Add[center, Add[final, Mul[final, [0,-velocityRatio]]]];
final ← Add[center, final];
curveTo[b1, b2, final];
RETURN[final];
END
ELSE RETURN[p0];
END;
MaxSmallArc: REAL = 3.14159265/2.0;
ArcAround:
PROC [curveTo:
PROC[p1, p2, p3:
VEC], p0:
VEC, center:
VEC, angle:
REAL] =
BEGIN
delta: REAL ← IF angle>0 THEN MaxSmallArc ELSE - MaxSmallArc;
WHILE
ABS[angle]>MaxSmallArc
DO
p0 ← ShortArcAround[curveTo, p0, center, delta];
angle ← angle - delta;
ENDLOOP;
[] ← ShortArcAround[curveTo, p0, center, angle];
END;
pieViewer: ViewerClasses.ViewerClass ←
NEW[ViewerClasses.ViewerClassRec ← [
paint: PieViewerPaint,
tipTable: NIL
]];
ViewerOps.RegisterViewerClass[$PieViewer, pieViewer]; -- plug in to Viewers
END.
Michael Plass, November 2, 1982 10:57 am. CEDARized.