Sliders.py 4.38 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1
# Module 'Sliders'
Guido van Rossum's avatar
Guido van Rossum committed
2

Guido van Rossum's avatar
Guido van Rossum committed
3 4 5 6

import stdwin
from stdwinevents import *
import rect
Guido van Rossum's avatar
Guido van Rossum committed
7
from Buttons import *
8
from HVSplit import HSplit
Guido van Rossum's avatar
Guido van Rossum committed
9 10 11 12 13 14 15 16 17 18


# Field indices in event detail
#
_HV = 0
_CLICKS = 1
_BUTTON = 2
_MASK = 3


19
# DragSlider is the simplest possible slider.
Guido van Rossum's avatar
Guido van Rossum committed
20 21
# It looks like a button but dragging the mouse left or right
# changes the controlled value.
22 23
# It does not support any of the triggers or hooks defined by Buttons,
# but defines its own setval_trigger and setval_hook.
Guido van Rossum's avatar
Guido van Rossum committed
24
#
Guido van Rossum's avatar
Guido van Rossum committed
25
class DragSliderReactivity(BaseReactivity):
Guido van Rossum's avatar
Guido van Rossum committed
26
	#
Guido van Rossum's avatar
Guido van Rossum committed
27 28 29 30 31 32
	def mouse_down(self, detail):
		h, v = hv = detail[_HV]
		if self.enabled and self.mousetest(hv):
			self.anchor = h
			self.oldval = self.val
			self.active = 1
Guido van Rossum's avatar
Guido van Rossum committed
33
	#
Guido van Rossum's avatar
Guido van Rossum committed
34 35 36 37
	def mouse_move(self, detail):
		if self.active:
			h, v = detail[_HV]
			self.setval(self.oldval + (h - self.anchor))
Guido van Rossum's avatar
Guido van Rossum committed
38
	#
Guido van Rossum's avatar
Guido van Rossum committed
39 40 41 42 43 44 45
	def mouse_up(self, detail):
		if self.active:
			h, v = detail[_HV]
			self.setval(self.oldval + (h - self.anchor))
			self.active = 0
	#

Guido van Rossum's avatar
Guido van Rossum committed
46
class DragSliderAppearance(ButtonAppearance):
Guido van Rossum's avatar
Guido van Rossum committed
47
	#
Guido van Rossum's avatar
Guido van Rossum committed
48 49 50 51 52
	# INVARIANTS maintained by the setval method:
	#
	#	self.min <= self.val <= self.max
	#	self.text = self.pretext + `self.val` + self.postext
	#
53
	# (Notice that unlike Python ranges, the end point belongs
Guido van Rossum's avatar
Guido van Rossum committed
54 55
	# to the range.)
	#
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
	def init_appearance(self):
		ButtonAppearance.init_appearance(self)
		self.min = 0
		self.val = 0
		self.max = 100
		self.hook = 0
		self.pretext = self.postext = ''
		self.recalctext()
	#
	# The 'get*' and 'set*' methods belong to the generic slider interface
	#
	def getval(self): return self.val
	#
	def sethook(self, hook):
		self.hook = hook
	#
72
	def setminvalmax(self, min, val, max):
73 74 75 76
		self.min = min
		self.max = max
		self.setval(val)
	#
77
	def settexts(self, pretext, postext):
78 79 80 81
		self.pretext = pretext
		self.postext = postext
		self.recalctext()
	#
Guido van Rossum's avatar
Guido van Rossum committed
82 83 84 85
	def setval(self, val):
		val = min(self.max, max(self.min, val))
		if val <> self.val:
			self.val = val
86 87 88 89 90 91
			self.recalctext()
			self.trigger()
	#
	def trigger(self):
		if self.hook:
			self.hook(self)
Guido van Rossum's avatar
Guido van Rossum committed
92
	#
93 94
	def recalctext(self):
		self.settext(self.pretext + `self.val` + self.postext)
Guido van Rossum's avatar
Guido van Rossum committed
95 96
	#

Guido van Rossum's avatar
Guido van Rossum committed
97
class DragSlider(DragSliderReactivity, DragSliderAppearance, Define):
98
	def definetext(self, parent, text):
99
		raise RuntimeError, 'DragSlider.definetext() not supported'
Guido van Rossum's avatar
Guido van Rossum committed
100 101


102
# Auxiliary class for PushButton incorporated in ComplexSlider
Guido van Rossum's avatar
Guido van Rossum committed
103
#
Guido van Rossum's avatar
Guido van Rossum committed
104
class _StepButton(PushButton):
105 106 107 108 109
	def define(self, parent):
		self = PushButton.define(self, parent)
		self.step = 0
		return self
	def setstep(self, step):
Guido van Rossum's avatar
Guido van Rossum committed
110
		self.step = step
111
	def definetextstep(self, parent, text, step):
112 113 114 115 116 117 118 119
		self = self.definetext(parent, text)
		self.setstep(step)
		return self
	def init_reactivity(self):
		PushButton.init_reactivity(self)
		self.parent.need_timer(self)
	def step_trigger(self):
		self.parent.setval(self.parent.getval() + self.step)
Guido van Rossum's avatar
Guido van Rossum committed
120
	def down_trigger(self):
121 122 123 124 125 126 127
		self.step_trigger()
		self.parent.settimer(5)
	def timer(self):
		if self.hilited:
			self.step_trigger()
		if self.active:
			self.parent.settimer(1)
Guido van Rossum's avatar
Guido van Rossum committed
128

129 130 131

# A complex slider is an HSplit initialized to three buttons:
# one to step down, a dragslider, and one to step up.
Guido van Rossum's avatar
Guido van Rossum committed
132
#
Guido van Rossum's avatar
Guido van Rossum committed
133
class ComplexSlider(HSplit):
Guido van Rossum's avatar
Guido van Rossum committed
134
	#
135 136 137 138
	# Override Slider define() method
	#
	def define(self, parent):
		self = self.create(parent) # HSplit
Guido van Rossum's avatar
Guido van Rossum committed
139
		#
140 141 142
		self.downbutton = _StepButton().definetextstep(self, '-', -1)
		self.dragbutton = DragSlider().define(self)
		self.upbutton = _StepButton().definetextstep(self, '+', 1)
Guido van Rossum's avatar
Guido van Rossum committed
143 144
		#
		return self
Guido van Rossum's avatar
Guido van Rossum committed
145
	#
146
	# Override HSplit methods
Guido van Rossum's avatar
Guido van Rossum committed
147
	#
148
	def getminsize(self, m, (width, height)):
149 150 151 152 153 154
		w1, h1 = self.downbutton.getminsize(m, (0, height))
		w3, h3 = self.upbutton.getminsize(m, (0, height))
		w1 = max(w1, h1)
		w3 = max(w3, h3)
		w2, h2 = self.dragbutton.getminsize(m, (width-w1-w3, height))
		return w1+w2+w3, max(h1, h2, h3)
Guido van Rossum's avatar
Guido van Rossum committed
155
	#
156 157 158
	def setbounds(self, bounds):
		(left, top), (right, bottom) = self.bounds = bounds
		size = bottom - top
159 160 161 162
		self.downbutton.setbounds(((left, top), (left+size, bottom)))
		self.dragbutton.setbounds(((left+size, top), \
						(right-size, bottom)))
		self.upbutton.setbounds(((right-size, top), (right, bottom)))
163 164 165 166 167 168 169 170 171 172 173 174
	#
	# Pass other Slider methods on to dragbutton
	#
	def getval(self): return self.dragbutton.getval()
	def sethook(self, hook): self.dragbutton.sethook(hook)
	def setminvalmax(self, args): self.dragbutton.setminvalmax(args)
	def settexts(self, args): self.dragbutton.settexts(args)
	def setval(self, val): self.dragbutton.setval(val)
	def enable(self, flag):
		self.downbutton.enable(flag)
		self.dragbutton.enable(flag)
		self.upbutton.enable(flag)