""" """ import pygame from pygame.locals import * from const import * import widget, surface import pguglobals class Container(widget.Widget): """The base container widget, can be used as a template as well as stand alone.
Container()""" def __init__(self,**params): widget.Widget.__init__(self,**params) self.myfocus = None self.mywindow = None self.myhover = None #self.background = 0 self.widgets = [] self.windows = [] self.toupdate = {} self.topaint = {} def update(self,s): updates = [] if self.myfocus: self.toupdate[self.myfocus] = self.myfocus for w in self.topaint: if w is self.mywindow: continue else: sub = surface.subsurface(s,w.rect) sub.blit(w._container_bkgr,(0,0)) w.paint(sub) updates.append(pygame.rect.Rect(w.rect)) for w in self.toupdate: if w is self.mywindow: continue else: us = w.update(surface.subsurface(s,w.rect)) if us: for u in us: updates.append(pygame.rect.Rect(u.x + w.rect.x,u.y+w.rect.y,u.w,u.h)) for w in self.topaint: if w is self.mywindow: w.paint(self.top_surface(s,w)) updates.append(pygame.rect.Rect(w.rect)) else: continue for w in self.toupdate: if w is self.mywindow: us = w.update(self.top_surface(s,w)) else: continue if us: for u in us: updates.append(pygame.rect.Rect(u.x + w.rect.x,u.y+w.rect.y,u.w,u.h)) self.topaint = {} self.toupdate = {} return updates def repaint(self,w=None): if not w: return widget.Widget.repaint(self) self.topaint[w] = w self.reupdate() def reupdate(self,w=None): if not w: return widget.Widget.reupdate(self) self.toupdate[w] = w self.reupdate() def paint(self,s): self.toupdate = {} self.topaint = {} for w in self.widgets: try: sub = surface.subsurface(s, w.rect) except: print 'container.paint(): %s not inside %s' % ( w.__class__.__name__,self.__class__.__name__) print s.get_width(), s.get_height(), w.rect print "" else: if (not (hasattr(w,'_container_bkgr') and w._container_bkgr.get_width() == sub.get_width() and w._container_bkgr.get_height() == sub.get_height())): w._container_bkgr = sub.copy() w._container_bkgr.fill((0,0,0,0)) w._container_bkgr.blit(sub,(0,0)) w.paint(sub) for w in self.windows: print 'container: windows', len(self.windows), s, w.rect w.paint(self.top_surface(s,w)) def top_surface(self,s,w): x,y = s.get_abs_offset() s = s.get_abs_parent() return surface.subsurface(s,(x+w.rect.x,y+w.rect.y,w.rect.w,w.rect.h)) def event(self,e): used = False if self.mywindow and e.type == MOUSEBUTTONDOWN: w = self.mywindow if self.myfocus is w: if not w.rect.collidepoint(e.pos): self.blur(w) if not self.myfocus: if w.rect.collidepoint(e.pos): self.focus(w) if not self.mywindow: #### by Gal Koren ## ## if e.type == FOCUS: if e.type == FOCUS and not self.myfocus: #self.first() pass elif e.type == EXIT: if self.myhover: self.exit(self.myhover) elif e.type == BLUR: if self.myfocus: self.blur(self.myfocus) elif e.type == MOUSEBUTTONDOWN: h = None for w in self.widgets: if not w.disabled: #focusable not considered, since that is only for tabs if w.rect.collidepoint(e.pos): h = w if self.myfocus is not w: self.focus(w) if not h and self.myfocus: self.blur(self.myfocus) elif e.type == MOUSEMOTION: if 1 in e.buttons: if self.myfocus: ws = [self.myfocus] else: ws = [] else: ws = self.widgets h = None for w in ws: if w.rect.collidepoint(e.pos): h = w if self.myhover is not w: self.enter(w) if not h and self.myhover: self.exit(self.myhover) w = self.myhover if w and w is not self.myfocus: sub = pygame.event.Event(e.type,{ 'buttons':e.buttons, 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y), 'rel':e.rel}) used = w._event(sub) w = self.myfocus if w: sub = e if e.type == MOUSEBUTTONUP or e.type == MOUSEBUTTONDOWN: sub = pygame.event.Event(e.type,{ 'button':e.button, 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y)}) used = w._event(sub) elif e.type == CLICK and self.myhover is w: sub = pygame.event.Event(e.type,{ 'button':e.button, 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y)}) used = w._event(sub) elif e.type == CLICK: #a dead click pass elif e.type == MOUSEMOTION: sub = pygame.event.Event(e.type,{ 'buttons':e.buttons, 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y), 'rel':e.rel}) used = w._event(sub) else: used = w._event(sub) if not used: if e.type is KEYDOWN: if e.key is K_TAB and self.myfocus: if (e.mod&KMOD_SHIFT) == 0: self.myfocus.next() else: self.myfocus.previous() return True elif e.key == K_UP: self._move_focus(0,-1) return True elif e.key == K_RIGHT: self._move_focus(1,0) return True elif e.key == K_DOWN: self._move_focus(0,1) return True elif e.key == K_LEFT: self._move_focus(-1,0) return True return used def _move_focus(self,dx_,dy_): myfocus = self.myfocus if not self.myfocus: return from pgu.gui import App widgets = self._get_widgets(pguglobals.app) #if myfocus not in widgets: return #widgets.remove(myfocus) if myfocus in widgets: widgets.remove(myfocus) rect = myfocus.get_abs_rect() fx,fy = rect.centerx,rect.centery def sign(v): if v < 0: return -1 if v > 0: return 1 return 0 dist = [] for w in widgets: wrect = w.get_abs_rect() wx,wy = wrect.centerx,wrect.centery dx,dy = wx-fx,wy-fy if dx_ > 0 and wrect.left < rect.right: continue if dx_ < 0 and wrect.right > rect.left: continue if dy_ > 0 and wrect.top < rect.bottom: continue if dy_ < 0 and wrect.bottom > rect.top: continue dist.append((dx*dx+dy*dy,w)) if not len(dist): return dist.sort() d,w = dist.pop(0) w.focus() def _get_widgets(self,c): widgets = [] if c.mywindow: widgets.extend(self._get_widgets(c.mywindow)) else: for w in c.widgets: if isinstance(w,Container): widgets.extend(self._get_widgets(w)) elif not w.disabled and w.focusable: widgets.append(w) return widgets def remove(self,w): """Remove a widget from the container.
Container.remove(w)""" self.blur(w) self.widgets.remove(w) #self.repaint() self.chsize() def add(self,w,x,y): """Add a widget to the container.
Container.add(w,x,y)