PaintFunction:
PUBLIC ViewerClasses.PaintProc ~ {
control: Control ← NARROW[self.data];
Action:
PROC ~ {
IF whatChanged =
NIL
THEN PaintInit[context, control, self.ww, self.wh]
ELSE PaintUpdate[context, control];
};
ImagerOps.DoWithBuffer[context, Action, 0, 0, self.ww, self.wh];
};
PaintInit:
PROC [context: Context, control: Control, w, h:
INTEGER] ~ {
function: Function ← NARROW[control.functionRef];
IF function = NIL THEN RETURN;
Imager.SetColor[context, Imager.white];
Imager.MaskRectangleI[context, 0, 0, w, h];
Imager.SetColor[context, Imager.black];
function.vMul ← IF h = 0 THEN 1.0 ELSE (control.max-control.min)/Real.Float[h-3];
FOR x:
NAT
IN[0..control.values.length)
DO
y:
INTEGER ← function.screenValues[x] ←
Real.RoundI[(control.values[x]-control.min)/function.vMul];
Imager.MaskRectangleI[context, x, y, 1, 1];
ENDLOOP;
};
PaintUpdate:
PROC [context: Context, control: Control] ~ {
UpdateOne:
PROC [x:
INTEGER, y, value:
REAL, report:
BOOL] ~ {
control.values[x] ← value;
Imager.MaskRectangleI[context, x, function.screenValues[x] ← Real.Round[y], 1, 1];
IF report
AND control.status #
NIL
THEN {
ViewerTools.SetContents[control.status, Rope.Concat[Convert.FtoRope[value, 3], " "]];
ViewerOps.PaintViewer[control.status, client];
};
};
y: REAL;
x0, x1: INTEGER;
function: Function ← NARROW[control.functionRef];
IF function = NIL THEN RETURN;
IF function.p1.x > function.p0.x
THEN {x0 ← function.p0.x; x1 ← function.p1.x; y ← function.p0.y}
ELSE {x0 ← function.p1.x; x1 ← function.p0.x; y ← function.p1.y};
Imager.SetColor[context, Imager.white];
FOR x:
NAT
IN[x0..x1]
DO
Imager.MaskRectangleI[context, x, function.screenValues[x], 1, 1];
ENDLOOP;
Imager.SetColor[context, Imager.black];
IF x0 = x1
THEN UpdateOne[x0, y, control.min+function.vMul*y, TRUE]
ELSE {
value: REAL ← control.min+function.vMul*y;
dy: REAL ← Real.Float[function.p1.y-function.p0.y]/(function.p1.x-function.p0.x);
dValue: REAL ← function.vMul*dy;
FOR x:
NAT
IN[x0..x1]
DO
UpdateOne[x, y, value, x = x1];
value ← value+dValue;
y ← y+dy;
ENDLOOP;
};
};