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