DIRECTORY Controls, ControlsPrivate, Convert, Draw2d, Imager, ImagerOps, Real, RealFns, ViewerClasses, ViewerOps, ViewerTools; ControlsSliderDialImpl: CEDAR MONITOR IMPORTS ControlsPrivate, Convert, Draw2d, Imager, ImagerOps, Real, RealFns, ViewerOps, ViewerTools EXPORTS Controls, ControlsPrivate ~ BEGIN OPEN Controls; SliderDial: TYPE ~ REF SliderDialRec; SliderDialRec: TYPE ~ RECORD [ t: REAL _ 0.0, -- parametric pos'n (0~min, 1~max) tPrev: REAL _ 0.0, -- (private) previous t detents: DetentList _ NIL, -- list of detents detented: BOOL _ FALSE, -- (private) true if control detented detentedPrev: BOOL _ FALSE, -- (private) true if was detented taper: SliderTaper _ lin, -- lin, log, or exponential slider cx, cy, rad: REAL _ 0.0 -- center and radius of dial ]; NewSliderDial: PUBLIC PROC [control: Control] ~ { sliderDial: SliderDial _ NEW[SliderDialRec _ [detents: control.detents, taper: control.taper]]; control.sliderDialRef _ sliderDial; FOR d: DetentList _ sliderDial.detents, d.rest WHILE d # NIL DO d.first.t _ (d.first.value-control.min)/(control.max-control.min); ENDLOOP; IF control.max # control.min THEN { sliderDial.t _(control.init-control.min)/(control.max-control.min); IF control.taper = log THEN sliderDial.t _ sliderDial.t*sliderDial.t; IF control.taper = exp THEN sliderDial.t _ Real.SqRt[sliderDial.t]; }; control.value _ control.init; sliderDial.rad _ MIN[control.w, control.h]/2-1; sliderDial.cx _ control.w/2; sliderDial.cy _ sliderDial.cx-1; }; NotifySliderDial: PUBLIC PROC [control: Control] ~ { IF ControlsPrivate.ControlProcBusy[control] THEN RETURN; ComputeControlTandValue[control, control.mouse.x, control.mouse.y]; ViewerOps.PaintViewer[control.viewer, client, FALSE, control]; ControlsPrivate.ForkControlProc[control]; }; SetSliderDialValue: PUBLIC PROC [control: Control, value: REAL, repaint: BOOL _ TRUE] ~ { sliderDial: SliderDial _ NARROW[control.sliderDialRef]; sliderDial.detentedPrev _ sliderDial.detented; sliderDial.detented _ FALSE; control.valuePrev _ control.value; control.value _ value; sliderDial.tPrev _ sliderDial.t; sliderDial.t _ (control.value-control.min)/(control.max-control.min); SELECT sliderDial.taper FROM log => sliderDial.t _ sliderDial.t*sliderDial.t; exp => sliderDial.t _ Real.SqRt[sliderDial.t]; ENDCASE; IF repaint THEN ViewerOps.PaintViewer[control.viewer, client, FALSE, control]; }; GetSliderDialValue: PUBLIC PROC [control: Control] RETURNS [REAL] ~ { RETURN[control.value]; }; PaintSliderDial: PUBLIC ViewerClasses.PaintProc ~ { control: Control _ NARROW[self.data]; sliderDial: SliderDial _ NARROW[control.sliderDialRef]; Action: PROC ~ { IF control.w = 0 THEN control.w _ control.viewer.cw; IF control.h = 0 THEN control.h _ control.viewer.ch; IF whatChanged = NIL AND control.type = dial THEN Draw2d.Circle[context, [sliderDial.cx, sliderDial.cy], sliderDial.rad, FALSE]; UnTick[context, control]; FOR detents: DetentList _ sliderDial.detents, detents.rest WHILE detents # NIL DO Tick[context, control, detents.first.t, FALSE, 1]; ENDLOOP; Tick[context, control, sliderDial.t, sliderDial.detented, 2]; sliderDial.detentedPrev _ sliderDial.detented; IF control.status # NIL THEN { ViewerTools.SetContents[control.status, Convert.FtoRope[control.value, IF control.truncate THEN 0 ELSE 3]]; ViewerOps.PaintViewer[control.status, client]; }; }; IF sliderDial # NIL THEN ImagerOps.DoWithBuffer[context, Action, 0, 0, self.ww, self.wh]; }; UnTick: PUBLIC PROC[context: Context, control: Control] ~ { sliderDial: SliderDial _ NARROW[control.sliderDialRef]; Imager.SetColor[context, Imager.white]; Tick[context, control, sliderDial.tPrev, sliderDial.detentedPrev, 2]; Imager.SetColor[context, Imager.black]; }; Tick: PUBLIC PROC [ context: Context, control: Control, t: REAL, detent: BOOL _ FALSE, width: NAT _ 1] ~ { SELECT control.type FROM vSlider => { y: REAL _ control.h*t; Imager.MaskRectangle[context, [0, y-width/2, control.w, width]]; IF detent THEN Draw2d.Square[context, [control.w/2, y], 3.0]; }; hSlider => { x: REAL _ control.w*t; Imager.MaskRectangle[context, [x-width/2, 0, width, control.h]]; IF detent THEN Draw2d.Square[context, [x+1, control.h/2-1], 3.0]; }; dial => { sliderDial: SliderDial _ NARROW[control.sliderDialRef]; rad: REAL _ sliderDial.rad-3; deg: REAL _ 360.0*t; Imager.SetStrokeWidth[context, width]; Imager.MaskVector[context, [sliderDial.cx+rad*RealFns.CosDeg[deg], sliderDial.cy+rad*RealFns.SinDeg[deg]], [sliderDial.cx, sliderDial.cy]]; IF detent THEN Draw2d.Circle[context, [sliderDial.cx, sliderDial.cy], 3.0, TRUE]; }; ENDCASE => NULL; }; ComputeControlTandValue: PROC [control: Control, x, y: INTEGER] ~ { ComputeControlT[control, x, y]; ComputeControlValue[control]; }; ComputeControlT: PROC [control: Control, x, y: INTEGER] ~ { sliderDial: SliderDial _ NARROW[control.sliderDialRef]; sliderDial.tPrev _ sliderDial.t; SELECT control.type FROM vSlider => sliderDial.t _ REAL[y]/REAL[control.h-3]; hSlider => sliderDial.t _ REAL[x]/REAL[control.w-3]; dial => { sliderDial.t _ RealFns.ArcTan[y-sliderDial.cy, x-sliderDial.cx]/(2.0*3.1415926535); IF y-sliderDial.cy < 0.0 THEN sliderDial.t _ sliderDial.t+1.0; }; ENDCASE => NULL; sliderDial.t _ MIN[1.0, MAX[0.0, sliderDial.t]]; }; ComputeControlValue: PROC [control: Control] ~ { sliderDial: SliderDial _ NARROW[control.sliderDialRef]; control.valuePrev _ control.value; sliderDial.detented _ FALSE; IF sliderDial.detents = NIL THEN { tt: REAL _ SELECT sliderDial.taper FROM log => Real.SqRt[sliderDial.t], exp => sliderDial.t*sliderDial.t, ENDCASE => sliderDial.t; control.value _ (1.0-tt)*control.min+tt*control.max; } ELSE { grain: REAL ~ 0.02; t0, t1, value0, value1: REAL _ 0.0; FOR d: DetentList _ sliderDial.detents, d.rest WHILE d # NIL DO t: REAL _ d.first.t; IF ABS[sliderDial.t-t] < grain THEN { sliderDial.t _ t; control.value _ d.first.value; sliderDial.detented _ TRUE; EXIT; }; IF t > sliderDial.t THEN EXIT; ENDLOOP; IF NOT sliderDial.detented THEN control.value _ (1.0-sliderDial.t)*control.min+sliderDial.t*control.max; }; IF control.truncate THEN control.value _ Real.Round[control.value]; }; END. ΰControlsSliderDialImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, February 24, 1987 4:42:40 pm PST Slider/Dial Type Definitions Initialization Notification Reading/Writing Painting Κβ˜šœ™Jšœ Οmœ1™Jšœ)˜)J˜——š ™š Οnœžœžœžœ žœžœ˜YJšœžœ˜7J˜Jšœ.˜.Jšœžœ˜Jšœ"˜"J˜Jšœ ˜ IcodešœE˜Ešžœž˜Lšœ0˜0Lšœ.˜.Lšžœ˜—Jšžœ žœ.žœ ˜OJšœ˜J˜—š£œž œžœžœ˜ELšžœ˜L˜——š ™š£œžœ˜3Jšœžœ ˜%Jšœžœ˜7š£œžœ˜Jšžœžœ˜4Jšžœžœ˜4šžœžœ˜,JšžœHžœ˜S—Lšœ˜šžœ8žœ žœž˜QLšœ(žœ˜2Lšžœ˜—Jšœ=˜=Jšœ.˜.cedaršžœžœžœž˜šœ'˜'Mšœžœžœžœ˜C—Jšœ.˜.J˜—J˜—JšžœžœžœA˜YJ˜J˜—š£œž œ(˜;Jšœžœ˜7J˜Jšœ'˜'JšœE˜EJšœ'˜'J˜—J˜šΠbnœžœžœ˜Jš œ'žœ žœžœ žœ ˜VJ˜šžœž˜˜ Jšœžœ˜Jšœ@˜@Jšžœžœ/˜=L˜—˜ Jšœžœ˜Jšœ@˜@Jšžœžœ3˜AL˜—šœ ˜ Jšœžœ˜8Jšœžœ˜Jšœžœ ˜Jšœ&˜&Jšœ‹˜‹Jšžœžœ=žœ˜QL˜—Lšžœžœ˜—J˜J˜—š€œžœžœ˜CL˜L˜L˜L˜—š€œžœžœ˜;Lšœžœ˜7L˜Jšœ ˜ šžœž˜Lšœžœžœ˜4Lšœžœžœ˜4šœ ˜ LšœS˜SLšžœžœ!˜>Lšœ˜—Lšžœžœ˜—Lšœžœžœ˜0L˜L˜—š€œžœ˜0Lšœžœ˜7J˜Jšœ"˜"Lšœžœ˜šžœžœžœ˜"šœžœžœž˜'Lšœ˜Lšœ!˜!Lšžœ˜—Lšœ4˜4Jšœ˜—šžœ˜Lšœžœ˜Lšœžœ˜#L˜šžœ,žœžœž˜?Lšœžœ ˜šžœžœžœ˜%LšœGžœ˜LLšžœ˜Lšœ˜—Lšžœžœžœ˜Lšžœ˜—L˜šžœžœ˜LšžœI˜M—L˜—Lšžœžœ+˜CLšœ˜L˜——Jšžœ˜J˜J˜—…— β