blob: ca67f7930181e619285c6c7b864c47cc5b419826 [file] [log] [blame]
Guido van Rossum336f2811990-10-24 16:39:18 +00001# Module 'Sliders'
2#
Guido van Rossum4de12871990-10-25 18:50:59 +00003# XXX Should split caller interface, appearance and reactivity better
4
Guido van Rossum336f2811990-10-24 16:39:18 +00005
6import stdwin
7from stdwinevents import *
8import rect
9from minmax import min, max
Guido van Rossum4de12871990-10-25 18:50:59 +000010from Buttons import *
Guido van Rossum336f2811990-10-24 16:39:18 +000011
12
13# Field indices in event detail
14#
15_HV = 0
16_CLICKS = 1
17_BUTTON = 2
18_MASK = 3
19
20
21# A dragslider is the simplest possible slider.
22# It looks like a button but dragging the mouse left or right
23# changes the controlled value.
24#
Guido van Rossum4de12871990-10-25 18:50:59 +000025class DragSliderReactivity() = NoReactivity():
Guido van Rossum336f2811990-10-24 16:39:18 +000026 #
27 def mouse_down(self, detail):
28 h, v = hv = detail[_HV]
29 if self.enabled and self.mousetest(hv):
30 self.anchor = h
31 self.oldval = self.val
32 self.active = 1
33 #
34 def mouse_move(self, detail):
35 if self.active:
36 h, v = detail[_HV]
37 self.setval(self.oldval + (h - self.anchor))
38 #
39 def mouse_up(self, detail):
40 if self.active:
41 h, v = detail[_HV]
42 self.setval(self.oldval + (h - self.anchor))
43 self.active = 0
44 #
Guido van Rossum4de12871990-10-25 18:50:59 +000045
46class DragSliderAppearance() = ButtonAppearance():
47 #
48 def define(self, (win, bounds)):
49 self.min = 0
50 self.val = -1 # Changed by next setval call
51 self.max = 100
52 self.setval_hook = 0
53 self.pretext = self.postext = ''
54 self = ClassicButton.define(self, (win, bounds, ''))
55 self.setval(50)
56 return self
57 #
58 # INVARIANTS maintained by the setval method:
59 #
60 # self.min <= self.val <= self.max
61 # self.text = self.pretext + `self.val` + self.postext
62 #
63 # (Notice that unlike in Python ranges, the end point belongs
64 # to the range.)
65 #
66 def setval(self, val):
67 val = min(self.max, max(self.min, val))
68 if val <> self.val:
69 self.val = val
70 self.setval_trigger()
71 # (The trigger may change val, pretext and postext)
72 self.settext(self.pretext + `self.val` + self.postext)
73 #
74 def setval_trigger(self):
75 if self.setval_hook:
76 self.setval_hook(self)
77 #
78
79class DragSlider() = DragSliderReactivity(), DragSliderAppearance(): pass
80
81
82# Auxiliary class for DragSlider incorporated in ComplexSlider
83#
84class _SubDragSlider() = DragSlider():
85 def define(self, (win, bounds, parent)):
86 self.parent = parent
87 return DragSlider.define(self, (win, bounds))
88 def setval_trigger(self):
89 self.parent.val = self.val
90 self.parent.setval_trigger()
91
92# Auxiliary class for ClassicButton incorporated in ComplexSlider
93#
94class _SubClassicButton() = ClassicButton():
95 def define(self, (win, bounds, text, step, parent)):
96 self.parent = parent
97 self.step = step
98 return ClassicButton.define(self, (win, bounds, text))
99 def down_trigger(self):
100 self.parent.setval(self.parent.val + self.step)
101 self.delay = 5
102 self.win.settimer(self.delay)
103 def move_trigger(self):
104 self.win.settimer(self.delay)
105 def timer_trigger(self):
106 self.delay = 1
107 self.parent.setval(self.parent.val + self.step)
108 self.win.settimer(self.delay)
109
110# A complex slider is a wrapper around three buttons:
111# One to step down, a dragslider, and one to step up.
112#
113class ComplexSlider() = LabelAppearance(), NoReactivity():
114 #
115 def define(self, (win, bounds)):
116 #
117 self.win = win
118 self.bounds = bounds
119 self.setval_hook = 0
120 #
121 (left, top), (right, bottom) = bounds
122 size = bottom - top
123 #
124 downbox = (left, top), (left+size, bottom)
125 sliderbox = (left+size, top), (right-size, bottom)
126 upbox = (right-size, top), (right, bottom)
127 #
128 self.downbutton = \
129 _SubClassicButton().define(win, downbox, '-', -1, self)
130 #
131 self.sliderbutton = \
132 _SubDragSlider().define(win, sliderbox, self)
133 #
134 self.upbutton = \
135 _SubClassicButton().define(win, upbox, '+', 1, self)
136 #
137 self.min = self.sliderbutton.min
138 self.val = self.sliderbutton.val
139 self.max = self.sliderbutton.max
140 self.pretext = self.sliderbutton.pretext
141 self.postext = self.sliderbutton.postext
142 #
143 self.children = \
144 [self.downbutton, self.sliderbutton, self.upbutton]
145 #
146 return self
147 #
148 def mouse_down(self, detail):
149 for b in self.children:
150 b.mouse_down(detail)
151 #
152 def mouse_move(self, detail):
153 for b in self.children:
154 b.mouse_move(detail)
155 #
156 def mouse_up(self, detail):
157 for b in self.children:
158 b.mouse_up(detail)
159 #
160 def timer(self):
161 for b in self.children:
162 b.timer()
163 #
164 def draw(self, area):
165 for b in self.children:
166 b.draw(area)
167 #
168 def setval(self, val):
169 self.sliderbutton.min = self.min
170 self.sliderbutton.max = self.max
171 self.sliderbutton.pretext = self.pretext
172 self.sliderbutton.postext = self.postext
173 self.sliderbutton.setval(val)
174 #
175 def setval_trigger(self):
176 if self.setval_hook:
177 self.setval_hook(self)
178 #