ControlsFunctionImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, July 2, 1992 6:10 pm PDT
DIRECTORY Controls, ControlsPrivate, Convert, Imager, Real, Rope, ViewerClasses, ViewerOps, ViewerTools;
ControlsFunctionImpl:
CEDAR
MONITOR
IMPORTS ControlsPrivate, Convert, Imager, Real, Rope, ViewerOps, ViewerTools
EXPORTS Controls, ControlsPrivate
~ BEGIN
Types
Context: TYPE ~ Imager.Context;
Control: TYPE ~ Controls.Control;
IntegerPair: TYPE ~ Controls.IntegerPair;
IntegerSequence: TYPE ~ Controls.IntegerSequence;
IntegerSequenceRep: TYPE ~ Controls.IntegerSequenceRep;
Mouse: TYPE ~ Controls.Mouse;
RealSequence: TYPE ~ Controls.RealSequence;
RealSequenceRep: TYPE ~ Controls.RealSequenceRep;
Function Type Definitions
Function: TYPE ~ REF FunctionRep;
FunctionRep:
TYPE ~
RECORD [
vMul: REAL ¬ 0.0, -- (private) value multiplier
screenValues: IntegerSequence ¬ NIL, -- (private) screen function values
p0, p1: IntegerPair ¬ [] -- (private) mouse interpolates
];
Function Initialization/Reading/Setting
NewFunction:
PUBLIC PROC [control: Control] ~ {
function: Function ¬ NEW[FunctionRep];
IF control.type # function THEN RETURN;
control.functionRef ¬ function;
IF control.values =
NIL
THEN {
control.values ¬ NEW[RealSequenceRep[control.w]];
FOR i:
NAT
IN[0..control.values.length)
DO
control.values[i] ¬ control.min;
ENDLOOP;
};
IF control.values.length <
CARD16[control.w]
THEN {
temp: RealSequence ¬ NEW[RealSequenceRep[control.w]];
FOR i: NAT IN[0..control.values.length) DO temp[i] ¬ control.values[i]; ENDLOOP;
control.values ¬ temp;
control.values.length ¬ control.w;
};
function.screenValues ¬ NEW[IntegerSequenceRep[control.w]];
};
ResetFunction:
PUBLIC
PROC [control: Control, repaint:
BOOL ¬
TRUE] ~ {
IF control.type = function
THEN {
FOR i:
NAT
IN[0..control.values.length)
DO
control.values[i] ¬ control.min;
ENDLOOP;
IF repaint THEN RequestPaint[control, FALSE, NIL];
};
};
SetFunctionValues:
PUBLIC PROC [
control: Control, values: RealSequence, repaint: BOOL ¬ TRUE] ~ {
control.values ¬ values;
IF repaint THEN RequestPaint[control, FALSE, NIL];
};
GetFunctionValues:
PUBLIC PROC [control: Control]
RETURNS [RealSequence] ~ {
RETURN[control.values];
};
Function Notification
NotifyFunction:
PUBLIC
PROC [control: Control, mouse: Mouse] ~ {
control.mouse ¬ mouse;
SetInterpolates[control];
IF control.mouse.state # up
THEN RequestPaint[control, FALSE, control]
ELSE ControlsPrivate.MaybeForkControlProc[control];
};
SetInterpolates:
PROC [control: Control] ~ {
mouse: Mouse ¬ control.mouse;
function: Function ¬ NARROW[control.functionRef];
SELECT mouse.state
FROM
down =>
SELECT mouse.button
FROM
left, middle =>
function.p0 ¬ function.p1 ¬ mouse.pos;
right => {
-- straight lines
function.p0 ¬ function.p1;
function.p1 ¬ mouse.pos;
};
ENDCASE => NULL;
held =>
SELECT mouse.button
FROM
left, middle => {
-- freestyle
function.p0 ¬ function.p1;
function.p1 ¬ mouse.pos;
};
right =>
-- straight lines
function.p1 ¬ mouse.pos;
ENDCASE => NULL;
ENDCASE => NULL;
};
Function Painting
RequestPaint:
PROC [control: Control, clearClient:
BOOL, whatChanged:
REF
ANY] ~ {
ViewerOps.PaintViewer[control.viewer, client, clearClient, whatChanged];
IF control.status #
NIL
THEN {
value: REAL ~ control.values[NARROW[control.functionRef, Function].p1.x];
ViewerTools.SetContents[control.status, Rope.Concat[Convert.FtoRope[value, 3], " "]];
ViewerOps.PaintViewer[control.status, client];
};
};
PaintFunction:
PUBLIC ViewerClasses.PaintProc ~ {
PaintUpdate:
PROC ~ {
UpdateOne:
PROC [x:
INTEGER, y, value:
REAL] ~ {
control.values[x] ¬ value;
Imager.MaskRectangleI[context, x, function.screenValues[x] ¬ Real.Round[y], 1, 1];
};
y: REAL;
x0, x1: INTEGER;
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]
ELSE {
value: REAL ¬ control.min+function.vMul*y;
dy: REAL ¬ (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];
value ¬ value+dValue;
y ¬ y+dy;
ENDLOOP;
};
};
PaintInit:
PROC ~ {
Imager.SetColor[context, Imager.black];
function.vMul ¬ IF self.wh = 0 THEN 1.0 ELSE (control.max-control.min)/(self.wh-3.0);
FOR x:
NAT
IN[0..control.values.length)
DO
y:
INTEGER ¬ function.screenValues[x] ¬
Real.Round[(control.values[x]-control.min)/function.vMul];
Imager.MaskRectangleI[context, x, y, 1, 1];
ENDLOOP;
};
control: Control ¬ NARROW[self.data];
function: Function ¬ NARROW[control.functionRef];
IF function = NIL THEN RETURN;
IF whatChanged =
NIL
THEN Imager.DoWithBuffer[context, PaintInit, 0, 0, self.ww, self.wh, Imager.white]
ELSE PaintUpdate[];
};
END.