<> <> <> <> <> DIRECTORY Imager USING [black, MaskFill, SetColor, TranslateT, white], ImagerPath USING [PathProc, VEC], PieViewers USING [PieViewer], Real USING [RoundI], RealFns USING [CosDeg, SinDeg], ViewerClasses USING [PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass]; PieViewersImpl: CEDAR PROGRAM IMPORTS Imager, Real, RealFns, ViewerOps EXPORTS PieViewers ~ BEGIN PieViewer: TYPE ~ PieViewers.PieViewer; Data: TYPE ~ REF DataRec; 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] ~ { 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] ~ { d: Data ~ NARROW[pieViewer.data]; IF d=NIL THEN RETURN; IF amount=d.total OR amount=0 OR Real.RoundI[d.amount/d.granularity] # Real.RoundI[amount/d.granularity] THEN { d.amount _ amount; ViewerOps.PaintViewer[pieViewer, client, FALSE, $Update]; }; }; VEC: TYPE ~ ImagerPath.VEC; PieViewerPaint: ViewerClasses.PaintProc ~ { d: Data ~ NARROW[self.data]; delta: REAL ~ 360*(d.amount/d.total); radius: REAL _ MIN[self.cw, self.ch]*0.5; Loc: PROC [a: REAL] RETURNS [VEC] ~ { RETURN[[radius*RealFns.CosDeg[a], radius*RealFns.SinDeg[a]]] }; MaskSector: PROC [a0, a2: REAL] ~ { path: ImagerPath.PathProc ~ { moveTo[[0, 0]]; lineTo[Loc[a0]]; arcTo[Loc[(a0+a2)/2], Loc[a2]] }; Imager.MaskFill[context, path]; }; Imager.TranslateT[context, [self.cw*0.5, self.ch*0.5]]; Imager.SetColor[context, Imager.black]; MaskSector[90, 90+delta]; Imager.SetColor[context, Imager.white]; radius _ radius+1; -- mask white with larger radius to avoid black garbage MaskSector[90, 90-(360-delta)]; }; pieViewer: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: PieViewerPaint, tipTable: NIL ]]; ViewerOps.RegisterViewerClass[$PieViewer, pieViewer]; -- plug in to Viewers END.