4 from pygame
.locals import *
10 class Container(widget
.Widget
):
11 """The base container widget, can be used as a template as well as stand alone.
13 <pre>Container()</pre>
15 def __init__(self
,**params
):
16 widget
.Widget
.__init
__(self
,**params
)
29 if self
.myfocus
: self
.toupdate
[self
.myfocus
] = self
.myfocus
31 for w
in self
.topaint
:
32 if w
is self
.mywindow
:
35 sub
= surface
.subsurface(s
,w
.rect
)
36 #if (hasattr(w, "_container_bkgr")):
37 # sub.blit(w._container_bkgr,(0,0))
39 updates
.append(pygame
.rect
.Rect(w
.rect
))
41 for w
in self
.toupdate
:
42 if w
is self
.mywindow
:
45 us
= w
.update(surface
.subsurface(s
,w
.rect
))
48 updates
.append(pygame
.rect
.Rect(u
.x
+ w
.rect
.x
,u
.y
+w
.rect
.y
,u
.w
,u
.h
))
50 for w
in self
.topaint
:
51 if w
is self
.mywindow
:
52 w
.paint(self
.top_surface(s
,w
))
53 updates
.append(pygame
.rect
.Rect(w
.rect
))
57 for w
in self
.toupdate
:
58 if w
is self
.mywindow
:
59 us
= w
.update(self
.top_surface(s
,w
))
64 updates
.append(pygame
.rect
.Rect(u
.x
+ w
.rect
.x
,u
.y
+w
.rect
.y
,u
.w
,u
.h
))
71 def repaint(self
,w
=None):
73 return widget
.Widget
.repaint(self
)
77 def reupdate(self
,w
=None):
79 return widget
.Widget
.reupdate(self
)
86 for w
in self
.widgets
:
88 sub
= surface
.subsurface(s
, w
.rect
)
90 print 'container.paint(): %s not inside %s' % (
91 w
.__class
__.__name
__,self
.__class
__.__name
__)
92 print s
.get_width(), s
.get_height(), w
.rect
95 # if (not hasattr(w,'_container_bkgr') or
96 # w._container_bkgr.get_size() != sub.get_size()):
97 # #w._container_bkgr.get_width() == sub.get_width() and
98 # #w._container_bkgr.get_height() == sub.get_height())):
99 # w._container_bkgr = sub.copy()
100 # w._container_bkgr.fill((0,0,0,0))
101 # w._container_bkgr.blit(sub,(0,0))
104 for w
in self
.windows
:
105 w
.paint(self
.top_surface(s
,w
))
107 def top_surface(self
,s
,w
):
108 x
,y
= s
.get_abs_offset()
109 s
= s
.get_abs_parent()
110 return surface
.subsurface(s
,(x
+w
.rect
.x
,y
+w
.rect
.y
,w
.rect
.w
,w
.rect
.h
))
115 if self
.mywindow
and e
.type == MOUSEBUTTONDOWN
:
117 if self
.myfocus
is w
:
118 if not w
.rect
.collidepoint(e
.pos
): self
.blur(w
)
120 if w
.rect
.collidepoint(e
.pos
): self
.focus(w
)
122 if not self
.mywindow
:
125 ## if e.type == FOCUS:
126 if e
.type == FOCUS
and not self
.myfocus
:
130 if self
.myhover
: self
.exit(self
.myhover
)
132 if self
.myfocus
: self
.blur(self
.myfocus
)
133 elif e
.type == MOUSEBUTTONDOWN
:
135 for w
in self
.widgets
:
136 if not w
.disabled
: #focusable not considered, since that is only for tabs
137 if w
.rect
.collidepoint(e
.pos
):
139 if self
.myfocus
is not w
: self
.focus(w
)
140 if not h
and self
.myfocus
:
141 self
.blur(self
.myfocus
)
142 elif e
.type == MOUSEMOTION
:
144 if self
.myfocus
: ws
= [self
.myfocus
]
146 else: ws
= self
.widgets
150 if w
.rect
.collidepoint(e
.pos
):
152 if self
.myhover
is not w
: self
.enter(w
)
153 if not h
and self
.myhover
:
154 self
.exit(self
.myhover
)
157 if w
and w
is not self
.myfocus
:
158 sub
= pygame
.event
.Event(e
.type,{
160 'pos':(e
.pos
[0]-w
.rect
.x
,e
.pos
[1]-w
.rect
.y
),
168 if e
.type == MOUSEBUTTONUP
or e
.type == MOUSEBUTTONDOWN
:
169 sub
= pygame
.event
.Event(e
.type,{
171 'pos':(e
.pos
[0]-w
.rect
.x
,e
.pos
[1]-w
.rect
.y
)})
173 elif e
.type == CLICK
and self
.myhover
is w
:
174 sub
= pygame
.event
.Event(e
.type,{
176 'pos':(e
.pos
[0]-w
.rect
.x
,e
.pos
[1]-w
.rect
.y
)})
178 elif e
.type == CLICK
: #a dead click
180 elif e
.type == MOUSEMOTION
:
181 sub
= pygame
.event
.Event(e
.type,{
183 'pos':(e
.pos
[0]-w
.rect
.x
,e
.pos
[1]-w
.rect
.y
),
190 if e
.type is KEYDOWN
:
191 if e
.key
is K_TAB
and self
.myfocus
:
192 if (e
.mod
&KMOD_SHIFT
) == 0:
195 self
.myfocus
.previous()
198 self
._move
_focus
(0,-1)
200 elif e
.key
== K_RIGHT
:
201 self
._move
_focus
(1,0)
203 elif e
.key
== K_DOWN
:
204 self
._move
_focus
(0,1)
206 elif e
.key
== K_LEFT
:
207 self
._move
_focus
(-1,0)
211 def _move_focus(self
,dx_
,dy_
):
212 myfocus
= self
.myfocus
213 if not self
.myfocus
: return
215 widgets
= self
._get
_widgets
(pguglobals
.app
)
216 #if myfocus not in widgets: return
217 #widgets.remove(myfocus)
218 if myfocus
in widgets
:
219 widgets
.remove(myfocus
)
220 rect
= myfocus
.get_abs_rect()
221 fx
,fy
= rect
.centerx
,rect
.centery
230 wrect
= w
.get_abs_rect()
231 wx
,wy
= wrect
.centerx
,wrect
.centery
233 if dx_
> 0 and wrect
.left
< rect
.right
: continue
234 if dx_
< 0 and wrect
.right
> rect
.left
: continue
235 if dy_
> 0 and wrect
.top
< rect
.bottom
: continue
236 if dy_
< 0 and wrect
.bottom
> rect
.top
: continue
237 dist
.append((dx
*dx
+dy
*dy
,w
))
238 if not len(dist
): return
243 def _get_widgets(self
,c
):
246 widgets
.extend(self
._get
_widgets
(c
.mywindow
))
249 if isinstance(w
,Container
):
250 widgets
.extend(self
._get
_widgets
(w
))
251 elif not w
.disabled
and w
.focusable
:
256 """Remove a widget from the container.
258 <pre>Container.remove(w)</pre>
261 self
.widgets
.remove(w
)
266 """Add a widget to the container.
268 <pre>Container.add(w,x,y)</pre>
271 <dt>x, y<dd>position of the widget
277 #NOTE: this might fix it, sort of...
278 #but the thing is, we don't really want to resize
279 #something if it is going to get resized again later
281 #w.rect.x,w.rect.y = w.style.x,w.style.y
282 #w.rect.w, w.rect.h = w.resize()
283 self
.widgets
.append(w
)
286 def open(self
,w
=None,x
=None,y
=None):
291 # The position is relative to this container
292 rect
= self
.get_abs_rect()
293 pos
= (rect
.x
+ x
, rect
.y
+ y
)
296 # Have the application open the window
297 pguglobals
.app
.open(w
, pos
)
299 def focus(self
,w
=None):
300 widget
.Widget
.focus(self
) ### by Gal koren
302 # return widget.Widget.focus(self)
304 if self
.myfocus
: self
.blur(self
.myfocus
)
305 if self
.myhover
is not w
: self
.enter(w
)
307 w
._event
(pygame
.event
.Event(FOCUS
))
309 #print self.myfocus,self.myfocus.__class__.__name__
311 def blur(self
,w
=None):
313 return widget
.Widget
.blur(self
)
314 if self
.myfocus
is w
:
315 if self
.myhover
is w
: self
.exit(w
)
317 w
._event
(pygame
.event
.Event(BLUR
))
320 if self
.myhover
: self
.exit(self
.myhover
)
322 w
._event
(pygame
.event
.Event(ENTER
))
325 if self
.myhover
and self
.myhover
is w
:
327 w
._event
(pygame
.event
.Event(EXIT
))
331 # for w in self.widgets:
335 # if self.container: self.container.next(self)
338 # if w not in self.widgets: return #HACK: maybe. this happens in windows for some reason...
340 # for w in self.widgets[self.widgets.index(w)+1:]:
344 # if self.container: return self.container.next(self)
347 def _next(self
,orig
=None):
349 if orig
in self
.widgets
: start
= self
.widgets
.index(orig
)+1
350 for w
in self
.widgets
[start
:]:
351 if not w
.disabled
and w
.focusable
:
352 if isinstance(w
,Container
):
360 def _previous(self
,orig
=None):
361 end
= len(self
.widgets
)
362 if orig
in self
.widgets
: end
= self
.widgets
.index(orig
)
363 ws
= self
.widgets
[:end
]
366 if not w
.disabled
and w
.focusable
:
367 if isinstance(w
,Container
):
375 def next(self
,w
=None):
376 if w
!= None and w
not in self
.widgets
: return #HACK: maybe. this happens in windows for some reason...
378 if self
._next
(w
): return True
379 if self
.container
: return self
.container
.next(self
)
382 def previous(self
,w
=None):
383 if w
!= None and w
not in self
.widgets
: return #HACK: maybe. this happens in windows for some reason...
385 if self
._previous
(w
): return True
386 if self
.container
: return self
.container
.previous(self
)
388 def resize(self
,width
=None,height
=None):
392 if self
.style
.width
: ww
= self
.style
.width
393 if self
.style
.height
: hh
= self
.style
.height
395 for w
in self
.widgets
:
396 #w.rect.w,w.rect.h = 0,0
397 w
.rect
.x
,w
.rect
.y
= w
.style
.x
,w
.style
.y
398 w
.rect
.w
, w
.rect
.h
= w
.resize()
401 ww
= max(ww
,w
.rect
.right
)
402 hh
= max(hh
,w
.rect
.bottom
)
405 # Returns the widget with the given name
406 def find(self
, name
):
407 for w
in self
.widgets
:
410 elif (isinstance(w
, Container
)):