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 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 ~ 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 ]; 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]; }; 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; }; 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. ό ControlsFunctionImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, July 2, 1992 6:10 pm PDT Types Function Type Definitions Function Initialization/Reading/Setting Function Notification Function Painting Κτ•NewlineDelimiter –"cedarcode" style™šœ™Jšœ Οeœ6™BJ™%J˜JšΟk œ_˜hJ˜—šΠblœžœž˜#JšžœE˜Lšžœ˜!J˜——Jšœž˜headšΟl™Jšœ žœ˜#Jšœ žœ˜%Jšœ žœ˜,Jšœžœ˜3Jšœžœ˜7Jšœžœ˜!Jšœžœ˜-Jšœžœ˜2—š ™Jšœ žœžœ ˜%šœ žœžœ˜Jšœ žœ Οc˜9Jšœ$žœ‘#˜LJšœ"‘˜AJ˜——š '™'šΟn œž œ˜/Jšœžœ˜&Jšžœžœžœ˜'J˜šžœžœžœ˜Jšœžœ˜1šžœžœžœž˜*J˜ Jšžœ˜—J˜—šžœžœ žœ˜3Jšœžœ˜5Jš žœžœžœžœžœ˜PJ˜J˜"J˜—Jšœžœ ˜;J˜J˜—š ’ œžœžœžœžœ˜Gšžœžœ˜!šžœžœžœž˜*J˜ Jšžœ˜—Jšžœ žœžœžœ˜2J˜—J˜J˜—š’œž œ˜ Jšœ1žœžœ˜AJ˜Jšžœ žœžœžœ˜2J˜J™—š’œž œžœ˜LJšžœ˜J˜——š ™š’œžœžœ%˜@J˜J˜šžœ˜Jšžœžœ ˜*Jšžœ.˜3—J˜J˜—šΠbnœžœ˜,J˜Jšœžœ˜1šžœ ž˜šœžœž˜ ˜J˜&—šœ‘˜'J˜J˜J˜—Jšžœžœ˜—šœžœž˜ šœ‘ ˜(J˜J˜J˜—šœ‘˜&J˜—Jšžœžœ˜—Jšžœžœ˜—Jšœ˜——š ™š ’ œžœ!žœžœžœ˜RJ˜Hšžœžœžœ˜Jšœžœžœ&˜IJšœZ˜ZJšœ.˜.J˜—J˜J˜—š’ œžœ˜1š’ œžœ˜š’ œžœžœ žœ˜1J˜J˜RJšœ˜—Jšœžœ˜Jšœžœ˜šžœ˜ Jšžœ<˜@Jšžœ=˜A—Jšœ'˜'šžœžœžœ ž˜JšœB˜BJšžœ˜—Jšœ'˜'šžœ˜ Jšžœ.˜2šžœ˜Jšœžœ˜*Jšœžœ?˜GJšœžœ˜ šžœžœžœ ž˜J˜J˜J˜ Jšžœ˜—J˜——Jšœ˜—š’ œžœ˜Jšœ'˜'Jšœžœ žœžœ)˜Ušžœžœžœž˜*šœžœ˜'Jšœ:˜:—Jšœ+˜+Jšžœ˜—J˜—Jšœžœ ˜%Jšœžœ˜1Jšžœ žœžœžœ˜šžœž˜JšžœN˜RJšžœ˜—J˜J˜——Jšžœ˜J˜J˜—…—ΘΈ