5 from . import pguglobals
8 from . import container, table
10 from . import basic, button, slider
12 class SlideBox(container.Container):
13 """A scrollable area with no scrollbars.
16 c = SlideBox(w,100,100)
24 def __init__(self, widget, width, height, **params):
25 """SlideBox constructor.
28 widget -- widget to be able to scroll around
29 width, height -- size of scrollable area
32 params.setdefault('width', width)
33 params.setdefault('height', height)
34 container.Container.__init__(self, **params)
43 def widget(self, val):
44 # Remove the old widget first
46 self.remove(self._widget)
47 # Now add in the new widget
52 #if not hasattr(self,'surface'):
53 self.surface = pygame.Surface((self.max_rect.w,self.max_rect.h),0,s)
54 #self.surface.fill((0,0,0,0))
55 pguglobals.app.theme.render(self.surface,self.style.background,pygame.Rect(0,0,self.max_rect.w,self.max_rect.h))
56 self.bkgr = pygame.Surface((s.get_width(),s.get_height()),0,s)
57 self.bkgr.blit(s,(0,0))
58 container.Container.paint(self,self.surface)
59 s.blit(self.surface,(-self.offset[0],-self.offset[1]))
60 self._offset = self.offset[:]
63 def paint_for_when_pygame_supports_other_tricks(self,s):
64 #this would be ideal if pygame had support for it!
65 #and if pgu also had a paint(self,s,rect) method to paint small parts
66 sr = (self.offset[0],self.offset[1],self.max_rect.w,self.max_rect.h)
67 cr = (-self.offset[0],-self.offset[1],s.get_width(),s.get_height())
70 container.Container.paint(self,s2)
72 def proxy_paint(self, s):
73 container.Container.paint(self, surface.ProxySurface(parent=None,
78 rects = container.Container.update(self,self.surface)
81 s_rect = pygame.Rect(0,0,s.get_width(),s.get_height())
83 if self.offset == self._offset:
85 r2 = r.move((-self.offset[0],-self.offset[1]))
86 if r2.colliderect(s_rect):
87 s.blit(self.surface.subsurface(r),r2)
90 s.blit(self.bkgr,(0,0))
91 sub = pygame.Rect(self.offset[0],self.offset[1],min(s.get_width(),self.max_rect.w-self.offset[0]),min(s.get_height(),self.max_rect.h-self.offset[1]))
93 # print self.surface.get_width(),self.surface.get_height()
94 # print s.get_width(),s.get_height()
96 # print self.style.width,self.style.height
97 s.blit(self.surface.subsurface(sub),(0,0))
99 self._offset = self.offset[:]
102 def proxy_update(self, s):
103 rects = container.Container.update(self, surface.ProxySurface(parent=None,
108 for r in rects: result.append(pygame.Rect(r).move(self.offset))
111 def resize(self, width=None, height=None):
112 container.Container.resize(self)
113 self.max_rect = pygame.Rect(self.widget.rect)
114 #self.max_rect.w = max(self.max_rect.w,self.style.width)
115 #self.max_rect.h = max(self.max_rect.h,self.style.height)
116 return self.style.width,self.style.height
117 #self.rect = pygame.Rect(self.rect[0], self.rect[1], self.style.width, self.style.height)
120 if e.type in [MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION]:
121 pos = (e.pos[0] + self.offset[0], e.pos[1] + self.offset[1])
122 if self.max_rect.collidepoint(pos):
123 e_params = {'pos': pos }
124 if e.type == MOUSEMOTION:
125 e_params['buttons'] = e.buttons
126 e_params['rel'] = e.rel
128 e_params['button'] = e.button
129 e = pygame.event.Event(e.type, e_params)
130 container.Container.event(self, e)
132 #class SlideBox(Area):
133 # def __init__(self,*args,**params):
134 # print 'gui.SlideBox','Scheduled to be renamed to Area.'
135 # Area.__init__(self,*args,**params)
137 class ScrollArea(table.Table):
138 """A scrollable area with scrollbars."""
142 def __init__(self, widget, width=0, height=0, hscrollbar=True, vscrollbar=True,step=24, **params):
143 """ScrollArea constructor.
146 widget -- widget to be able to scroll around
147 width, height -- size of scrollable area. Set either to 0 to default to size of widget.
148 hscrollbar -- set to False if you do not wish to have a horizontal scrollbar
149 vscrollbar -- set to False if you do not wish to have a vertical scrollbar
150 step -- set to how far clicks on the icons will step
154 params.setdefault('cls', 'scrollarea')
155 table.Table.__init__(self, width=width,height=height,**params)
157 self.sbox = SlideBox(w, width=width, height=height, cls=self.cls+".content")
159 self.vscrollbar = vscrollbar
160 self.hscrollbar = hscrollbar
169 def widget(self, val):
171 self.sbox.widget = val
173 def resize(self,width=None,height=None):
178 table.Table.clear(self)
179 #print 'resize',self,self._rows
184 widget.rect.w, widget.rect.h = widget.resize()
185 my_width,my_height = self.style.width,self.style.height
187 my_width = widget.rect.w
188 self.hscrollbar = False
190 my_height = widget.rect.h
191 self.vscrollbar = False
193 box.style.width,box.style.height = my_width,my_height #self.style.width,self.style.height
195 box.rect.w,box.rect.h = box.resize()
199 #r = table.Table.resize(self,width,height)
205 # #this old code automatically adds in a scrollbar if needed
206 # #but it doesn't always work
207 # self.vscrollbar = None
208 # if widget.rect.h > box.rect.h:
209 # self.vscrollbar = slider.VScrollBar(box.offset[1],0, 65535, 0,step=self.step)
210 # self.td(self.vscrollbar)
211 # self.vscrollbar.connect(CHANGE, self._vscrollbar_changed, None)
213 # vs = self.vscrollbar
214 # vs.rect.w,vs.rect.h = vs.resize()
215 # box.style.width = self.style.width - vs.rect.w
218 # self.hscrollbar = None
219 # if widget.rect.w > box.rect.w:
220 # self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
221 # self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
223 # self.td(self.hscrollbar)
225 # hs = self.hscrollbar
226 # hs.rect.w,hs.rect.h = hs.resize()
227 # box.style.height = self.style.height - hs.rect.h
229 xt,xr,xb,xl = pguglobals.app.theme.getspacing(box)
233 self.vscrollbar = slider.VScrollBar(box.offset[1],0, 65535, 0,step=self.step)
234 self.td(self.vscrollbar)
235 self.vscrollbar.connect(CHANGE, self._vscrollbar_changed, None)
238 vs.rect.w,vs.rect.h = vs.resize()
240 box.style.width = self.style.width - (vs.rect.w + xl+xr)
243 self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
244 self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
246 self.td(self.hscrollbar)
249 hs.rect.w,hs.rect.h = hs.resize()
250 if self.style.height:
251 box.style.height = self.style.height - (hs.rect.h + xt + xb)
256 hs.max = widget.rect.w - box.style.width
257 hs.style.width = box.style.width
258 hs.size = hs.style.width * box.style.width / max(1,widget.rect.w)
265 vs.max = widget.rect.h - box.style.height
266 vs.style.height = box.style.height
267 vs.size = vs.style.height * box.style.height / max(1,widget.rect.h)
271 #print self.style.width,box.style.width, hs.style.width
273 r = table.Table.resize(self,width,height)
276 def x_resize(self, width=None, height=None):
277 w,h = table.Table.resize(self, width, height)
279 if self.widget.rect.w <= self.sbox.rect.w:
280 self.hscrollbar.size = self.hscrollbar.style.width
282 self.hscrollbar.size = max(20,self.hscrollbar.style.width * self.sbox.rect.w / self.widget.rect.w)
283 self._hscrollbar_changed(None)
284 if self.widget.rect.h <= self.sbox.rect.h:
285 self.vscrollbar.size = self.vscrollbar.style.height
287 self.vscrollbar.size = max(20,self.vscrollbar.style.height * self.sbox.rect.h / self.widget.rect.h)
288 self._vscrollbar_changed(None)
291 def _vscrollbar_changed(self, xxx):
292 #y = (self.widget.rect.h - self.sbox.rect.h) * self.vscrollbar.value / 1000
293 #if y >= 0: self.sbox.offset[1] = -y
294 self.sbox.offset[1] = self.vscrollbar.value
297 def _hscrollbar_changed(self, xxx):
298 #x = (self.widget.rect.w - self.sbox.rect.w) * self.hscrollbar.value / 1000
299 #if x >= 0: self.sbox.offset[0] = -x
300 self.sbox.offset[0] = self.hscrollbar.value
304 def set_vertical_scroll(self, percents):
305 #if not self.vscrollbar: return
306 if not hasattr(self.vscrollbar,'value'): return
307 self.vscrollbar.value = percents #min(max(percents*10, 0), 1000)
308 self._vscrollbar_changed(None)
310 def set_horizontal_scroll(self, percents):
311 #if not self.hscrollbar: return
312 if not hasattr(self.hscrollbar,'value'): return
313 self.hscrollbar.value = percents #min(max(percents*10, 0), 1000)
314 self._hscrollbar_changed(None)
317 #checking for event recipient
318 if (table.Table.event(self, e)):
321 #mouse wheel scrolling
323 if not hasattr(self.vscrollbar,'value'):
326 if e.type == pygame.locals.MOUSEBUTTONDOWN:
327 if e.button == 4: #wheel up
328 self.vscrollbar._click(-1)
330 elif e.button == 5: #wheel down
331 self.vscrollbar._click(1)
338 class _List_Item(button._button):
339 def __init__(self,label=None,image=None,value=None,**params): #TODO label= could conflict with the module label
340 #param image: an imagez.Image object (optional)
341 #param text: a string object
342 params.setdefault('cls','list.item')
343 button._button.__init__(self,**params)
345 self.value = value #(self, value)
348 if type(label) == str:
349 label = basic.Label(label, cls=self.cls+".label")
352 self.widget = container.Container()
353 self.widget.add(image, 0, 0)
354 #HACK: improper use of .resize()
355 image.rect.w,image.rect.h = image.resize()
356 self.widget.add(label, image.rect.w, 0)
357 elif image: self.widget = image
358 elif label: self.widget = label
362 def resize(self,width=None,height=None):
363 self.widget.rect.w,self.widget.rect.h = self.widget.resize()
364 return self.widget.rect.w,self.widget.rect.h
365 # self.widget._resize()
366 # self.rect.w,self.rect.h = self.widget.rect_margin.w,self.widget.rect_margin.h
369 button._button.event(self,e)
370 if self.group.value == self.value: self.pcls = "down"
373 if self.group.value == self.value: self.pcls = "down"
374 self.widget.paint(surface.subsurface(s,self.widget.rect))
377 self.group.value = self.value
378 for w in self.group.widgets:
379 if w != self: w.pcls = ""
383 class List(ScrollArea):
384 """A list of items in an area.
386 This widget can be a form element, it has a value set to whatever item is selected.
389 def _change(self, value):
390 self.value = self.group.value
393 def __init__(self, width, height, **params):
394 params.setdefault('cls', 'list')
395 self.table = table.Table(width=width)
396 ScrollArea.__init__(self, self.table, width, height,hscrollbar=False ,**params)
402 g.connect(CHANGE,self._change,None)
403 self.value = self.group.value = None
406 self.remove = self._remove
409 """Clear the list."""
411 self.group = group.Group()
412 self.group.connect(CHANGE,self._change,None)
414 self.set_vertical_scroll(0)
415 self.blur(self.myfocus)
417 def _add(self, label, image = None, value=None):
418 item = _List_Item(label,image=image,value=value)
421 self.items.append(item)
422 item.group = self.group
425 def _remove(self, item):
427 if i.value == item: item = i
428 if item not in self.items:
431 self.items.remove(item)
432 self.group.widgets.remove(item)
433 self.table.remove_row(item.style.row)