DIRECTORY Cursors USING [CursorType, NewCursor], Graphics USING [Box, DrawBox, GetBounds, SetColor], GraphicsBasic USING [Color, white], InputFocus USING [CaptureButtons, ReleaseButtons], Process USING [Detach, Milliseconds, MsecToTicks, SetTimeout], MySliders, TIPUser USING [InstantiateNewTIPTable, TIPScreenCoords, TIPScreenCoordsRec], ViewerClasses USING [GetProc, NotifyProc, PaintProc, SetProc, Viewer, ViewerRec, ViewerClass, ViewerClassRec], ViewerOps USING [CreateViewer, GetViewer, MouseInViewer, PaintViewer, RegisterViewerClass, SetViewer, UserToScreenCoords], WindowManager USING [RestoreCursor]; MySlidersImpl: CEDAR MONITOR IMPORTS Cursors, Graphics, InputFocus, Process, TIPUser, ViewerOps, WindowManager EXPORTS MySliders = BEGIN OPEN MySliders; Create: PUBLIC PROCEDURE [info: ViewerClasses.ViewerRec _ [], sliderProc: SliderProc _ NIL, filterProc: FilterProc _ NIL, orientation: SliderOrientation _ vertical, foreground: GraphicsBasic.Color _ [r:50, g:100, b:150], background: GraphicsBasic.Color _ GraphicsBasic.white, value: NormalizedSliderValue _ 0.0, clientData: REF ANY _ NIL, paint: BOOL _ TRUE] RETURNS [slider: Slider] = { sliderData: SliderData _ NEW[SliderDataRec _ [sliderProc: sliderProc, filterProc: filterProc, orientation: orientation, foreground: foreground, background: background, normalizedSliderValue: value, clientData: clientData]]; info.data _ sliderData; info.scrollable _ FALSE; RETURN[ViewerOps.CreateViewer[flavor: $Slider, info: info, paint: paint]]; }; GetContents: PUBLIC PROCEDURE [slider: Slider] RETURNS [contents: NormalizedSliderValue] = { RETURN[NARROW[ViewerOps.GetViewer[viewer: slider], REF NormalizedSliderValue]^]; }; SetContents: PUBLIC PROCEDURE [slider: Slider, contents: NormalizedSliderValue] = { value: REF NormalizedSliderValue _ NEW[NormalizedSliderValue _ contents]; ViewerOps.SetViewer[viewer: slider, data: value]; }; SlidersPaint: PRIVATE ViewerClasses.PaintProc = { min, max: REAL; sliderData: SliderData _ NARROW[self.data]; box: Graphics.Box _ Graphics.GetBounds[context]; SELECT whatChanged FROM NIL => { Graphics.SetColor[context, sliderData.background]; Graphics.DrawBox[context, box]; SetMaxSliderValue[self]; SetSliderValue[sliderData, sliderData.normalizedSliderValue]; min _ 0.0; max _ sliderData.sliderValue; Graphics.SetColor[context, sliderData.foreground]; }; $sliderValue => { IF sliderData.oldSliderValue <= sliderData.sliderValue THEN { min _ 0.0; -- sliderData.oldSliderValue; max _ sliderData.sliderValue; Graphics.SetColor[context, sliderData.foreground]; } ELSE { min _ sliderData.sliderValue; max _ IF sliderData.orientation = horizontal THEN box.xmax ELSE box.ymax; -- sliderData.oldSliderValue; Graphics.SetColor[context, sliderData.background]; }; }; ENDCASE => ERROR; IF sliderData.orientation = horizontal THEN { box.xmin _ min; box.xmax _ max; } ELSE { box.ymin _ min; box.ymax _ max; }; Graphics.DrawBox[context, box]; sliderData.oldSliderValue _ sliderData.sliderValue; }; SetMaxSliderValue: PROCEDURE [slider: Slider] = { sliderData: SliderData _ NARROW[slider.data]; sliderData.maxSliderValue _ IF sliderData.orientation = horizontal THEN slider.cw ELSE slider.ch; IF sliderData.maxSliderValue < 1.0 THEN sliderData.maxSliderValue _ 1.0; }; SlidersGet: PRIVATE ViewerClasses.GetProc = { sliderData: SliderData _ NARROW[self.data]; RETURN[NEW[NormalizedSliderValue _ sliderData.normalizedSliderValue]]; }; SlidersSet: PRIVATE ENTRY ViewerClasses.SetProc = { dataValue: REF NormalizedSliderValue _ NARROW[data]; sliderData: SliderData _ NARROW[self.data]; SetSliderValue[sliderData, dataValue^]; ViewerOps.PaintViewer[viewer: self, hint: client, clearClient: FALSE, whatChanged: $sliderValue]; }; SetSliderValue: PRIVATE PROCEDURE [sliderData: SliderData, normalizedValue: NormalizedSliderValue] = { SELECT normalizedValue FROM < 0.0 => normalizedValue _ 0.0; > 1.0 => normalizedValue _ 1.0; ENDCASE; sliderData.normalizedSliderValue _ normalizedValue; sliderData.sliderValue _ sliderData.normalizedSliderValue * sliderData.maxSliderValue; }; SlidersNotify: PRIVATE ViewerClasses.NotifyProc = TRUSTED { ENABLE UNWIND => { InputFocus.ReleaseButtons[]; WindowManager.RestoreCursor[] }; v: ViewerClasses.Viewer; c: BOOLEAN; mouse: TIPUser.TIPScreenCoords; mouseValue: SliderValue; mouseScreenCoords: TIPUser.TIPScreenCoords _ NEW[TIPUser.TIPScreenCoordsRec]; sliderData: SliderData _ NARROW[self.data]; FOR list: LIST OF REF ANY _ input, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM x: ATOM => SELECT x FROM $Enable => { InputFocus.CaptureButtons[proc: SlidersNotify, tip: slidersClass.tipTable, viewer: self]; sliderData.state _ inputEnabled; sliderData.savedSliderValue _ sliderData.sliderValue; mouseValue _ IF sliderData.orientation = horizontal THEN mouse.mouseX ELSE mouse.mouseY; SetNewSliderValue[sliderData: sliderData, value: mouseValue, reason: move]; CreateSliderProcess[self]; }; $Abort => { InputFocus.ReleaseButtons[]; sliderData.state _ inputDisabled; SetNewSliderValue[sliderData: sliderData, value: sliderData.savedSliderValue, reason: abort]; sliderProcessData.state _ dying; }; $Move => IF sliderData.state = inputEnabled THEN { mouseScreenCoords^ _ mouse^; [v, c] _ ViewerOps.MouseInViewer[mouse]; IF v = self AND c THEN mouseValue _ IF sliderData.orientation = horizontal THEN mouse.mouseX ELSE mouse.mouseY ELSE IF MouseAboveSlider[self: self, coords: mouseScreenCoords] THEN mouseValue _ sliderData.maxSliderValue ELSE IF MouseBelowSlider[self: self, coords: mouseScreenCoords] THEN mouseValue _ 0.0 ELSE mouseValue _ sliderData.mouseValue; SetNewSliderValue[sliderData: sliderData, value: mouseValue, reason: move]; }; $Set => IF sliderData.state = inputEnabled THEN { reason: Reason _ set; InputFocus.ReleaseButtons[]; sliderData.state _ inputDisabled; mouseScreenCoords^ _ mouse^; [v, c] _ ViewerOps.MouseInViewer[mouse]; IF v = self AND c THEN mouseValue _ IF sliderData.orientation = horizontal THEN mouse.mouseX ELSE mouse.mouseY ELSE IF MouseAboveSlider[self: self, coords: mouseScreenCoords] THEN mouseValue _ sliderData.maxSliderValue ELSE IF MouseBelowSlider[self: self, coords: mouseScreenCoords] THEN mouseValue _ 0.0 ELSE { mouseValue _ sliderData.savedSliderValue; reason _ abort; }; SetNewSliderValue[sliderData: sliderData, value: mouseValue, reason: reason]; sliderProcessData.state _ dying; }; ENDCASE => NULL; z: TIPUser.TIPScreenCoords => mouse _ z; ENDCASE => ERROR; ENDLOOP; }; SetNewSliderValue: PRIVATE ENTRY PROCEDURE [sliderData: SliderData, value: SliderValue, reason: Reason] = { sliderData.mouseValue _ value; sliderData.reason _ reason; }; MouseAboveSlider: PRIVATE PROCEDURE [self: Slider, coords: TIPUser.TIPScreenCoords] RETURNS [above: BOOLEAN] = { cornerX, cornerY: INTEGER; sliderData: SliderData _ NARROW[self.data]; IF sliderData.orientation = horizontal THEN { [cornerX, cornerY] _ ViewerOps.UserToScreenCoords[self: self, vx: self.ww-2, vy: 0]; IF coords.mouseX > cornerX AND coords.mouseY >= cornerY AND coords.mouseY < cornerY + self.wh THEN RETURN[TRUE]; } ELSE { [cornerX, cornerY] _ ViewerOps.UserToScreenCoords[self: self, vx: 0, vy: self.wh-2]; IF coords.mouseY > cornerY AND coords.mouseX >= cornerX AND coords.mouseX < cornerX + self.ww THEN RETURN[TRUE]; }; RETURN[FALSE]; }; MouseBelowSlider: PRIVATE PROCEDURE [self: Slider, coords: TIPUser.TIPScreenCoords] RETURNS [below: BOOLEAN] = { cornerX, cornerY: INTEGER; sliderData: SliderData _ NARROW[self.data]; [cornerX, cornerY] _ ViewerOps.UserToScreenCoords[self: self, vx: 0, vy: 0]; IF sliderData.orientation = horizontal THEN { IF coords.mouseX < cornerX AND coords.mouseY >= cornerY AND coords.mouseY < cornerY + self.wh THEN RETURN[TRUE]; } ELSE { IF coords.mouseY < cornerY AND coords.mouseX >= cornerX AND coords.mouseX < cornerX + self.ww THEN RETURN[TRUE]; }; RETURN[FALSE]; }; SliderProcessData: TYPE = REF SliderProcessDataRec; SliderProcessDataRec: TYPE = RECORD [ slider: Slider _ NIL, timerCondition: CONDITION, state: SliderProcessState _ alive ]; SliderProcessState: TYPE = {alive, dying}; sliderProcessData: SliderProcessData _ NIL; CreateSliderProcess: PRIVATE PROCEDURE [slider: Slider] = { sliderProcessData _ NEW[SliderProcessDataRec]; sliderProcessData.slider _ slider; TRUSTED {Process.Detach[FORK SliderProcess[sliderProcessData]]}; }; SliderProcess: PRIVATE PROCEDURE [myData: SliderProcessData] = { UpdateSliderValue: PROCEDURE [self: Slider] = { sliderData: SliderData _ NARROW[self.data]; notifyClient: BOOLEAN; reason: Reason; normalizedValue: NormalizedSliderValue; [notifyClient, reason, normalizedValue] _ UpdateSlider[self]; IF sliderData.sliderProc # NIL AND notifyClient THEN sliderData.sliderProc[slider: self, reason: reason, value: normalizedValue, clientData: sliderData.clientData]; }; timerPeriod: Process.Milliseconds = 40; WHILE myData.state = alive DO UpdateSliderValue[myData.slider]; Wait[myData, timerPeriod]; ENDLOOP; UpdateSliderValue[myData.slider]; }; UpdateSlider: PRIVATE ENTRY PROCEDURE [self: Slider] RETURNS [notifyClient: BOOLEAN, reason: Reason, normalizedValue: NormalizedSliderValue] = { sliderData: SliderData _ NARROW[self.data]; value: NormalizedSliderValue; notifyClient _ FALSE; IF sliderData.mouseValue # sliderData.oldSliderValue THEN { notifyClient _ TRUE; value _ sliderData.mouseValue / sliderData.maxSliderValue; IF sliderData.filterProc # NIL THEN value _ sliderData.filterProc[value, sliderData.clientData]; SetSliderValue[sliderData, value]; IF sliderData.sliderValue # sliderData.oldSliderValue THEN { notifyClient _ TRUE; ViewerOps.PaintViewer[viewer: self, hint: client, clearClient: FALSE, whatChanged: $sliderValue]; }; }; IF sliderData.reason # sliderData.oldReason THEN notifyClient _ TRUE; sliderData.oldReason _ sliderData.reason; RETURN[notifyClient, sliderData.reason, sliderData.normalizedSliderValue]; }; Wait: PRIVATE ENTRY PROCEDURE [data: SliderProcessData, milliseconds: Process.Milliseconds] = { TRUSTED {Process.SetTimeout[@data.timerCondition, Process.MsecToTicks[milliseconds]]}; WAIT data.timerCondition; }; slidersClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: SlidersPaint, get: SlidersGet, set: SlidersSet, notify: SlidersNotify, tipTable: TIPUser.InstantiateNewTIPTable["Slider.tip"], cursor: Cursors.NewCursor[[0,0, 000600B, 000600B, 000600B, 000600B, 000600B, 037774B, 037774B, 000600B, 000600B, 000600B, 000600B, 000600B, 0,0], -8, -8] -- now cross, before : crossHairsCircle ]]; ViewerOps.RegisterViewerClass[$Slider, slidersClass]; END. t///cd18/MySlidersImpl.mesa Written by Darlene Plebon on June 22, 1983 1:16 pm Last Edited by: Beach, June 22, 1983 6:15 pm Last Edited by: Monier, September 24, 1984 8:36:24 pm PDT slidersClass is a record containing the procedures and data common to all slidersClass viewer instances (class record). Register the Sliders class of viewer with the Window Manager Κ Š– "Cedar" style˜Iproc– "Cedar" stylešœ™K– "Cedar" stylešœ2™2J™,J™9unitšΟk ˜ Jšœœ˜&Jšœ œ%˜3Jšœœ˜#Jšœ œ"˜2Jšœœ1˜>Jšœ ˜ Jšœœ?˜LJšœœ[˜nJšœ œk˜zJšœœ˜$—šΟb œœ˜JšœJ˜QJšœ ˜—Lšœœ ˜J˜J˜šΟnœœ œ?œœΜœœœ œœœ˜ƒJšœœΓ˜ίJšœ˜Jšœœ˜JšœD˜JJšœ˜—J˜šŸ œœ œœ&˜\Jšœœ&œ˜PJ˜—J˜šŸ œœ œ6˜SJšœœœ#˜IJšœ1˜1J˜—J˜šŸ œœ˜1Kšœ œ˜Kšœœ ˜+J˜0šœ ˜šœ˜Kšœ2˜2Kšœ ˜ J˜Jšœ=˜=J˜ Jšœ˜Kšœ2˜2Jšœ˜—šœ˜šœ5œ˜=Jšœ(˜(Jšœ˜Kšœ2˜2Jšœ˜—šœ˜Jšœ˜Jšœœ%œ7˜hKšœ2˜2Jšœ˜—J˜—Jšœœ˜—šœ%œ˜-J˜J˜Jšœ˜—šœ˜J˜J˜Jšœ˜—Kšœ ˜ Jšœ3˜3Jšœ˜—J˜šŸœ œ˜1Jšœœ˜-Jšœœ%œ œ ˜aJšœ œ!˜HJ˜—J˜šŸ œœ˜-Kšœœ ˜+Jšœœ<˜FJšœ˜J˜—šŸ œ œ˜3Jšœ œœ˜4Jšœœ ˜+Jšœ'˜'Jšœ?œ˜aJšœ˜J˜—šŸœœ œE˜fšœ˜J˜J˜Jšœ˜—Jšœ3˜3JšœV˜VJ˜—J˜šŸ œœœ˜;JšœœC˜PJ˜Jšœœ˜ Kšœ˜K˜Kšœ-œ˜MKšœœ ˜+šœœœœœœœ˜@šœ œ˜šœœœ˜šœ ˜ J•StartOfExpansionc[proc: ViewerClasses.NotifyProc, tip: TIPTables.TIPTable, viewer: ViewerClasses.Viewer _ NIL]šœY˜YJšœ ˜ Jšœ5˜5Jšœ œ%œœ˜XJšœK˜KJšœ˜Jšœ˜—šœ ˜ J˜Jšœ!˜!Jšœ]˜]Jšœ ˜ Jšœ˜—šœ œ!œ˜2Jšœ˜J˜(Jš œ œœœ%œœ ˜qJšœœ9œ(˜lJšœœ9œ˜VJšœ$˜(JšœK˜KJšœ˜—šœœ!œ˜1J˜Jšœ˜Jšœ!˜!Jšœ˜J˜(Jš œ œœœ%œœ ˜qJšœœ9œ(˜lJšœœ9œ˜Všœ˜Jšœ)˜)J˜J˜—JšœM˜MJšœ ˜ Jšœ˜—Jšœœ˜—Jšœ(˜(Jšœœ˜—Jšœ˜—Jšœ˜—Iemphasis™šŸœœA˜kJšœ˜Jšœ˜J˜—J˜š Ÿœœ œ1œ œ˜pJšœœ˜Kšœœ ˜+šœ%œ˜-JšœT˜TJš œœœ#œœœ˜pJšœ˜—šœ˜JšœT˜TJš œœœ#œœœ˜pJšœ˜—Jšœœ˜J˜—J˜š Ÿœœ œ1œ œ˜pJšœœ˜Kšœœ ˜+JšœL˜Lšœ%œ˜-Jš œœœ#œœœ˜pJšœ˜—šœ˜Jš œœœ#œœœ˜pJšœ˜—Jšœœ˜J˜—J˜Jšœœœ˜3šœœœ˜%Jšœœ˜Jšœ œ˜J˜!J˜—Jšœœ˜*J˜Jšœ'œ˜+J˜šŸœœ˜;Jšœœ˜.Jšœ"˜"Jšœœ$˜@J˜—J˜šŸ œœ ˜@šŸœ œ˜/Kšœœ ˜+Jšœœ˜Jšœ˜Jšœ'˜'Jšœ=˜=Jšœœœ œp˜€J˜—Jšœ'˜'šœ˜Jšœ!˜!J˜—Jšœ˜Jšœ!˜!J˜—J˜š Ÿ œœœ œœœ=˜Kšœœ ˜+Jšœ˜Jšœœ˜šœ3œ˜;Jšœœ˜Jšœ:˜:Jšœœœ=˜`Jšœ"˜"šœ3œ˜