Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / simulator / pgu-0.18 / build / lib / pgu / gui / area.py
1 """
2 """
3 import os
4
5 from . import pguglobals
6 from .const import *
7 from . import surface
8 from . import container, table
9 from . import group
10 from . import basic, button, slider
11
12 class SlideBox(container.Container):
13     """A scrollable area with no scrollbars.
14     
15     Example:
16         c = SlideBox(w,100,100)
17         c.offset = (10,10)
18         c.repaint()
19     
20     """
21
22     _widget = None
23     
24     def __init__(self, widget, width, height, **params):
25         """SlideBox constructor.
26
27         Arguments:
28             widget -- widget to be able to scroll around
29             width, height -- size of scrollable area
30     
31         """
32         params.setdefault('width', width)
33         params.setdefault('height', height)
34         container.Container.__init__(self, **params)
35         self.offset = [0, 0]
36         self.widget = widget
37
38     @property
39     def widget(self):
40         return self._widget
41
42     @widget.setter
43     def widget(self, val):
44         # Remove the old widget first
45         if self._widget:
46             self.remove(self._widget)
47         # Now add in the new widget
48         self._widget = val
49         self.add(val, 0, 0)
50     
51     def paint(self, s):
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[:]
61         return
62         
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())
68         s2 = s.subsurface(sr)
69         s2.set_clip(cr)
70         container.Container.paint(self,s2)
71         
72     def proxy_paint(self, s):
73         container.Container.paint(self, surface.ProxySurface(parent=None, 
74                                            rect=self.max_rect,
75                                            real_surface=s,
76                                            offset=self.offset))
77     def update(self, s):
78         rects = container.Container.update(self,self.surface)
79         
80         rets = []
81         s_rect = pygame.Rect(0,0,s.get_width(),s.get_height())
82         
83         if self.offset == self._offset:
84             for r in rects:
85                 r2 = r.move((-self.offset[0],-self.offset[1]))
86                 if r2.colliderect(s_rect):
87                     s.blit(self.surface.subsurface(r),r2)
88                     rets.append(r2)
89         else:
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]))
92 #             print sub
93 #             print self.surface.get_width(),self.surface.get_height()
94 #             print s.get_width(),s.get_height()
95 #             print self.offset
96 #             print self.style.width,self.style.height
97             s.blit(self.surface.subsurface(sub),(0,0))
98             rets.append(s_rect)
99         self._offset = self.offset[:]
100         return rets
101         
102     def proxy_update(self, s):
103         rects = container.Container.update(self, surface.ProxySurface(parent=None, 
104                                                     rect=self.max_rect,
105                                                     real_surface=s,
106                                                     offset=self.offset))
107         result = []
108         for r in rects: result.append(pygame.Rect(r).move(self.offset))
109         return result
110         
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)
118     
119     def event(self, e):
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
127                 else:
128                     e_params['button'] = e.button
129                 e = pygame.event.Event(e.type, e_params)
130         container.Container.event(self, e)
131
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)
136     
137 class ScrollArea(table.Table):
138     """A scrollable area with scrollbars."""
139
140     _widget = None
141
142     def __init__(self, widget, width=0, height=0, hscrollbar=True, vscrollbar=True,step=24, **params):
143         """ScrollArea constructor.
144
145         Arguments:
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 
151
152         """
153         w= widget
154         params.setdefault('cls', 'scrollarea')
155         table.Table.__init__(self, width=width,height=height,**params)
156         
157         self.sbox = SlideBox(w, width=width, height=height, cls=self.cls+".content")
158         self.widget = w
159         self.vscrollbar = vscrollbar
160         self.hscrollbar = hscrollbar
161         
162         self.step = step
163
164     @property
165     def widget(self):
166         return self._widget
167
168     @widget.setter
169     def widget(self, val):
170         self._widget = val
171         self.sbox.widget = val
172
173     def resize(self,width=None,height=None):
174         widget = self.widget
175         box = self.sbox
176         
177         #self.clear()
178         table.Table.clear(self)
179         #print 'resize',self,self._rows
180         
181         self.tr()
182         self.td(box)
183         
184         widget.rect.w, widget.rect.h = widget.resize()
185         my_width,my_height = self.style.width,self.style.height
186         if not my_width:
187             my_width = widget.rect.w
188             self.hscrollbar = False
189         if not my_height:
190             my_height = widget.rect.h
191             self.vscrollbar = False
192         
193         box.style.width,box.style.height = my_width,my_height #self.style.width,self.style.height
194         
195         box.rect.w,box.rect.h = box.resize()
196         
197         #print widget.rect
198         #print box.rect
199         #r = table.Table.resize(self,width,height)
200         #print r
201         #return r
202         
203         #print box.offset
204         
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)
212 #             
213 #             vs = self.vscrollbar
214 #             vs.rect.w,vs.rect.h = vs.resize()
215 #             box.style.width = self.style.width - vs.rect.w
216 #             
217 #             
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)
222 #             self.tr()
223 #             self.td(self.hscrollbar)
224 #             
225 #             hs = self.hscrollbar
226 #             hs.rect.w,hs.rect.h = hs.resize()
227 #             box.style.height = self.style.height - hs.rect.h
228
229         xt,xr,xb,xl  = pguglobals.app.theme.getspacing(box)
230         
231
232         if self.vscrollbar:
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)
236             
237             vs = self.vscrollbar
238             vs.rect.w,vs.rect.h = vs.resize()
239             if self.style.width:
240                 box.style.width = self.style.width - (vs.rect.w + xl+xr)
241
242         if self.hscrollbar:
243             self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
244             self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
245             self.tr()
246             self.td(self.hscrollbar)
247             
248             hs = 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)
252             
253         if self.hscrollbar:
254             hs = self.hscrollbar
255             hs.min = 0
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)
259         else:
260             box.offset[0] = 0
261             
262         if self.vscrollbar:
263             vs = self.vscrollbar
264             vs.min = 0
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)
268         else:
269             box.offset[1] = 0
270             
271         #print self.style.width,box.style.width, hs.style.width
272             
273         r = table.Table.resize(self,width,height)
274         return r
275     
276     def x_resize(self, width=None, height=None):
277         w,h = table.Table.resize(self, width, height)
278         if self.hscrollbar:
279             if self.widget.rect.w <= self.sbox.rect.w:
280                 self.hscrollbar.size = self.hscrollbar.style.width
281             else:
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
286         else:
287             self.vscrollbar.size = max(20,self.vscrollbar.style.height * self.sbox.rect.h / self.widget.rect.h)
288         self._vscrollbar_changed(None)
289         return w,h
290
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
295         self.sbox.reupdate()
296
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
301         self.sbox.reupdate()
302
303
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)
309
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)
315
316     def event(self, e):
317          #checking for event recipient
318          if (table.Table.event(self, e)):
319              return True
320
321          #mouse wheel scrolling
322          if self.vscrollbar:
323              if not hasattr(self.vscrollbar,'value'): 
324                  return False
325  
326              if e.type == pygame.locals.MOUSEBUTTONDOWN:
327                  if e.button == 4: #wheel up
328                      self.vscrollbar._click(-1)
329                      return True
330                  elif e.button == 5: #wheel down
331                      self.vscrollbar._click(1)
332                      return True
333          return False
334
335         
336
337
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)
344         self.group = None
345         self.value = value #(self, value)
346         self.widget = None
347         
348         if type(label) == str: 
349             label = basic.Label(label, cls=self.cls+".label")
350
351         if image and 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
359         
360         self.pcls = ""
361     
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
367     
368     def event(self,e):
369         button._button.event(self,e)
370         if self.group.value == self.value: self.pcls = "down"
371     
372     def paint(self,s):
373         if self.group.value == self.value: self.pcls = "down"
374         self.widget.paint(surface.subsurface(s,self.widget.rect))
375     
376     def click(self):
377         self.group.value = self.value
378         for w in self.group.widgets:
379             if w != self: w.pcls = ""
380
381
382
383 class List(ScrollArea):
384     """A list of items in an area.
385     
386     This widget can be a form element, it has a value set to whatever item is selected.
387
388     """
389     def _change(self, value):
390         self.value = self.group.value
391         self.send(CHANGE)
392
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)
397         
398         self.items = []
399         
400         g = group.Group()
401         self.group = g
402         g.connect(CHANGE,self._change,None)
403         self.value = self.group.value = None
404
405         self.add = self._add
406         self.remove = self._remove
407         
408     def clear(self):
409         """Clear the list."""
410         self.items = []
411         self.group = group.Group()
412         self.group.connect(CHANGE,self._change,None)
413         self.table.clear()
414         self.set_vertical_scroll(0)
415         self.blur(self.myfocus)
416         
417     def _add(self, label, image = None, value=None):
418         item = _List_Item(label,image=image,value=value)
419         self.table.tr()
420         self.table.add(item)
421         self.items.append(item)
422         item.group = self.group
423         item.group.add(item)
424         
425     def _remove(self, item):
426         for i in self.items:
427             if i.value == item: item = i
428         if item not in self.items: 
429             return
430         item.blur()
431         self.items.remove(item)
432         self.group.widgets.remove(item)
433         self.table.remove_row(item.style.row)
434

UCC git Repository :: git.ucc.asn.au