Mercurial > mamba
view mamba/widgets/base.py @ 97:c65046b5bafd
eat focus adjusting key events
author | Stefano Rivera <stefano@rivera.za.net> |
---|---|
date | Sun, 11 Sep 2011 19:24:59 +0200 |
parents | 7a17c5b74148 |
children | 2b6626f417f2 |
line wrap: on
line source
import collections import pygame from pygame.constants import K_UP, K_DOWN from pygame.locals import MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN, KEYDOWN class Widget(object): def __init__(self, rect): if not isinstance(rect, pygame.Rect): rect = pygame.Rect(rect, (0, 0)) self.rect = rect self.focussable = False self.focussed = False self.callbacks = collections.defaultdict(list) def add_callback(self, eventtype, callback, *args): self.callbacks[eventtype].append((callback, args)) def event(self, ev): for callback, args in self.callbacks[ev.type]: if callback(ev, self, *args): return True return False def draw(self, surface): "Override me" pass class Container(Widget): def __init__(self, rect, root=False): super(Container, self).__init__(rect) self.children = [] self.root = root self.focussable = True self.focussed_child = None def event(self, ev): """Push an event down through the tree, and fire our own event as a last resort """ if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN): for child in self.children: if child.rect.collidepoint(ev.pos): if child.event(ev): return True if ev.type == KEYDOWN: for child in self.children: if child.focussed: if child.event(ev): return True if super(Container, self).event(ev): return True if self.root and ev.type == KEYDOWN and ev.key in (K_UP, K_DOWN): return self.adjust_focus(1 if ev.key == K_DOWN else -1) def add(self, widget): widget.parent = self self.children.append(widget) def adjust_focus(self, direction): """Try and adjust focus in direction (integer) """ if self.focussed_child is not None: child = self.children[self.focussed_child] if isinstance(child, Container): if child.adjust_focus(direction): return True child.focussed = False current = self.focussed_child if current is None: current = -1 if direction > 0 else len(self.children) if direction > 0: possibles = list(enumerate(self.children))[current + 1:] else: possibles = list(enumerate(self.children))[:current] possibles.reverse() for i, child in possibles: if child.focussable: child.focussed = True if isinstance(child, Container): if child.adjust_focus(direction): self.focussed_child = i return True child.focussed = False continue else: self.focussed_child = i child.focussed = True return True else: if self.root: # At the end, mark the last one as focussed, again child = self.children[self.focussed_child] if isinstance(child, Container): if child.adjust_focus(-direction): return True child.focussed = True else: self.focussed_child = None return False def draw(self, surface): if self.root and not self.focussed: self.focussed = True self.adjust_focus(1) for child in self.children: child.draw(surface)