2 from pygame.locals import *
8 from . import pguglobals
9 from .errors import PguError
11 _SLIDER_HORIZONTAL = 0
14 class _slider(widget.Widget):
17 def __init__(self,value,orient,min,max,size,step=1,**params):
18 params.setdefault('cls','slider')
19 widget.Widget.__init__(self,**params)
20 self.min,self.max,self.value,self.orient,self.size,self.step = min,max,value,orient,size,step
21 self.style.check("bar")
25 self.value = self.value
26 r = pygame.rect.Rect(0,0,self.style.width,self.style.height)
27 if self.orient == _SLIDER_HORIZONTAL:
28 r.x = (self.value-self.min) * (r.w-self.size) / max(1,self.max-self.min);
31 r.y = (self.value-self.min) * (r.h-self.size) / max(1,self.max-self.min);
36 pguglobals.app.theme.render(s,self.style.bar,r)
40 r = pygame.rect.Rect(0,0,self.style.width,self.style.height)
42 if e.type == ENTER: self.repaint()
43 elif e.type == EXIT: self.repaint()
44 elif e.type == MOUSEBUTTONDOWN:
45 if self.bar.collidepoint(e.pos):
46 self.grab = e.pos[0],e.pos[1]
47 self.grab_value = self.value
49 x,y,adj = e.pos[0],e.pos[1],1
52 elif e.type == MOUSEBUTTONUP:
53 #x,y,adj = e.pos[0],e.pos[1],1
55 elif e.type == MOUSEMOTION:
56 if 1 in e.buttons and self.container.myfocus is self:
58 rel = e.pos[0]-self.grab[0],e.pos[1]-self.grab[1]
59 if self.orient == _SLIDER_HORIZONTAL:
61 if d != 0: self.value = self.grab_value + ((self.max-self.min) * rel[0] / d)
64 if d != 0: self.value = self.grab_value + ((self.max-self.min) * rel[1] / d)
66 x,y,adj = e.pos[0],e.pos[1],1
68 elif e.type is KEYDOWN:
69 if self.orient == _SLIDER_HORIZONTAL and e.key == K_LEFT:
70 self.value -= self.step
72 elif self.orient == _SLIDER_HORIZONTAL and e.key == K_RIGHT:
73 self.value += self.step
75 elif self.orient == _SLIDER_VERTICAL and e.key == K_UP:
76 self.value -= self.step
78 elif self.orient == _SLIDER_VERTICAL and e.key == K_DOWN:
79 self.value += self.step
83 if self.orient == _SLIDER_HORIZONTAL:
84 d = self.size/2 - (r.w/(self.max-self.min+1))/2
85 self.value = (x-d) * (self.max-self.min) / (r.w-self.size+1) + self.min
87 d = self.size/2 - (r.h/(self.max-self.min+1))/2
88 self.value = (y-d) * (self.max-self.min) / (r.h-self.size+1) + self.min
91 if self.container.myhover is self: self.pcls = "hover"
92 if (self.container.myfocus is self and 1 in pygame.mouse.get_pressed()): self.pcls = "down"
96 # TODO - replace this with property functions and setters
97 def __setattr__(self,k,v):
102 _v = self.__dict__.get(k,NOATTR)
104 if k == 'value' and _v != NOATTR and _v != v:
107 if hasattr(self,'size'):
108 sz = min(self.size,max(self.style.width,self.style.height))
109 sz = max(sz,min(self.style.width,self.style.height))
110 self.__dict__['size'] = sz
112 if hasattr(self,'max') and hasattr(self,'min'):
113 if self.max < self.min: self.max = self.min
120 # def value(self, val):
122 # val = max(val, self.min)
123 # val = min(val, self.max)
125 # oldval = self._value
127 # if (oldval != val):
131 # if hasattr(self,'size'):
132 # sz = min(self.size,max(self.style.width,self.style.height))
133 # sz = max(sz,min(self.style.width,self.style.height))
136 # if hasattr(self,'max') and hasattr(self,'min'):
137 # if self.max < self.min: self.max = self.min
140 class VSlider(_slider):
141 """A verticle slider."""
143 def __init__(self,value,min,max,size,step=1,**params):
144 """Construct a veritcal slider widget.
147 value -- the default position of the slider, between min and max
148 min -- the minimum value for the slider
149 max -- the maximum value
150 size -- the length of the slider bar in pixels
151 step -- how much to jump when using the keyboard
154 params.setdefault('cls','vslider')
155 _slider.__init__(self,value,_SLIDER_VERTICAL,min,max,size,step,**params)
157 class HSlider(_slider):
158 """A horizontal slider."""
160 def __init__(self,value,min,max,size,step=1,**params):
161 params.setdefault('cls','hslider')
162 _slider.__init__(self,value,_SLIDER_HORIZONTAL,min,max,size,step,**params)
164 class HScrollBar(table.Table):
165 """A horizontal scroll bar."""
167 def __init__(self,value,min,max,size,step=1,**params):
168 params.setdefault('cls','hscrollbar')
170 table.Table.__init__(self,**params)
172 # Check that these styles are defined
173 self.style.check("minus")
174 self.style.check("plus")
176 self.slider = _slider(value,_SLIDER_HORIZONTAL,min,max,size,step=step,cls=self.cls+'.slider')
177 self.minus = basic.Image(self.style.minus)
178 self.minus.connect(MOUSEBUTTONDOWN,self._click,-1)
179 self.slider.connect(CHANGE,self.send,CHANGE)
181 self.minus2 = basic.Image(self.style.minus)
182 self.minus2.connect(MOUSEBUTTONDOWN,self._click,-1)
184 self.plus = basic.Image(self.style.plus)
185 self.plus.connect(MOUSEBUTTONDOWN,self._click,1)
189 def _click(self,value):
190 self.slider.value += self.slider.step*value
192 def resize(self,width=None,height=None):
197 h = self.slider.style.height
200 if w > (h*2 + self.minus.style.width+self.plus.style.width):
202 ww += self.minus.style.width
206 if w > (h*2 + self.minus.style.width+self.minus2.style.width+self.plus.style.width):
208 ww += self.minus2.style.width
210 if w > (h*2 + self.minus.style.width+self.plus.style.width):
212 ww += self.plus.style.width
215 #HACK: handle theme sizing properly
216 xt,xr,xb,xl = pguglobals.app.theme.getspacing(self.slider)
219 self.slider.style.width = self.style.width - ww
220 setattr(self.slider,'size',self.size * self.slider.style.width / max(1,self.style.width))
221 #self.slider.size = self.size * self.slider.style.width / max(1,self.style.width)
222 return table.Table.resize(self,width,height)
226 return self.slider.min
229 def min(self, value):
230 self.slider.min = value
234 return self.slider.max
237 def max(self, value):
238 self.slider.max = value
242 return self.slider.value
245 def value(self, value):
246 self.slider.value = value
250 return self.slider.step
253 def step(self, value):
254 self.slider.step = value
256 # def __setattr__(self,k,v):
257 # if k in ('min','max','value','step'):
258 # return setattr(self.slider,k,v)
261 # def __getattr__(self,k):
262 # if k in ('min','max','value','step'):
263 # return getattr(self.slider,k)
264 # return table.Table.__getattr__(self,k) #self.__dict__[k]
266 class VScrollBar(table.Table):
267 """A vertical scroll bar."""
269 def __init__(self,value,min,max,size,step=1,**params):
270 params.setdefault('cls','vscrollbar')
272 table.Table.__init__(self,**params)
274 # Check that these styles are defined
275 self.style.check("minus")
276 self.style.check("plus")
278 self.minus = basic.Image(self.style.minus)
279 self.minus.connect(MOUSEBUTTONDOWN,self._click,-1)
281 self.minus2 = basic.Image(self.style.minus)
282 self.minus2.connect(MOUSEBUTTONDOWN,self._click,-1)
284 self.plus = basic.Image(self.style.plus)
285 self.plus.connect(MOUSEBUTTONDOWN,self._click,1)
287 self.slider = _slider(value,_SLIDER_VERTICAL,min,max,size,step=step,cls=self.cls+'.slider')
288 self.slider.connect(CHANGE,self.send,CHANGE)
292 def _click(self,value):
293 self.slider.value += self.slider.step*value
295 def resize(self,width=None,height=None):
298 h = self.style.height
299 w = self.slider.style.width
302 if h > (w*2 + self.minus.style.height+self.plus.style.height):
305 hh += self.minus.style.height
310 if h > (w*2 + self.minus.style.height+self.minus2.style.height+self.plus.style.height):
313 hh += self.minus2.style.height
315 if h > (w*2 + self.minus.style.height+self.plus.style.height):
318 hh += self.plus.style.height
321 #HACK: handle theme sizing properly
322 xt,xr,xb,xl = pguglobals.app.theme.getspacing(self.slider)
325 self.slider.style.height = self.style.height - hh
326 setattr(self.slider,'size',self.size * self.slider.style.height / max(1,self.style.height))
327 return table.Table.resize(self,width,height)
329 def __setattr__(self,k,v):
330 if k in ('min','max','value','step'):
331 return setattr(self.slider,k,v)
334 def __getattr__(self,k):
335 if k in ('min','max','value','step'):
336 return getattr(self.slider,k)
337 return table.Table.__getattr__(self,k)