comparison mamba/widgets/base.py @ 77:2aa652b92449

Focus
author Stefano Rivera <stefano@rivera.za.net>
date Sun, 11 Sep 2011 18:30:19 +0200
parents 3cc917814579
children 7a17c5b74148
comparison
equal deleted inserted replaced
76:a2694a024c83 77:2aa652b92449
1 import collections 1 import collections
2 2
3 import pygame 3 import pygame
4 from pygame.constants import K_UP, K_DOWN
4 from pygame.locals import MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN, KEYDOWN 5 from pygame.locals import MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN, KEYDOWN
5 6
6 7
7 class Widget(object): 8 class Widget(object):
8 9
9 def __init__(self, rect): 10 def __init__(self, rect):
10 if not isinstance(rect, pygame.Rect): 11 if not isinstance(rect, pygame.Rect):
11 rect = pygame.Rect(rect, (0, 0)) 12 rect = pygame.Rect(rect, (0, 0))
12 self.rect = rect 13 self.rect = rect
13 self.focussable = False 14 self.focussable = False
15 self.focussed = False
14 self.callbacks = collections.defaultdict(list) 16 self.callbacks = collections.defaultdict(list)
15 17
16 def add_callback(self, eventtype, callback, *args): 18 def add_callback(self, eventtype, callback, *args):
17 self.callbacks[eventtype].append((callback, args)) 19 self.callbacks[eventtype].append((callback, args))
18 20
19 def event(self, ev): 21 def event(self, ev):
20 for callback, args in self.callbacks[ev.type]: 22 for callback, args in self.callbacks[ev.type]:
21 callback(ev, self, *args) 23 if callback(ev, self, *args):
24 return True
25 return False
22 26
23 def draw(self, surface): 27 def draw(self, surface):
24 "Override me" 28 "Override me"
25 pass 29 pass
26 30
27 31
28 class Container(Widget): 32 class Container(Widget):
29 33
30 def __init__(self, rect): 34 def __init__(self, rect, root=False):
31 super(Container, self).__init__(rect) 35 super(Container, self).__init__(rect)
32 self.children = [] 36 self.children = []
37 self.root = root
38 self.focussed = root
39 self.focussable = True
40 self.focussed_child = None
33 41
34 def event(self, ev): 42 def event(self, ev):
43 """Push an event down through the tree, and fire our own event as a
44 last resort
45 """
35 if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN): 46 if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN):
36 for child in self.children: 47 for child in self.children:
37 if child.rect.collidepoint(ev.pos): 48 if child.rect.collidepoint(ev.pos):
38 child.event(ev) 49 if child.event(ev):
50 return True
39 if ev.type == KEYDOWN: 51 if ev.type == KEYDOWN:
40 for child in self.children: 52 for child in self.children:
41 child.event(ev) 53 if child.focussed:
42 super(Container, self).event(ev) 54 if child.event(ev):
55 return True
56 if super(Container, self).event(ev):
57 return True
58 if self.root and ev.type == KEYDOWN and ev.key in (K_UP, K_DOWN):
59 self.adjust_focus(1 if ev.key == K_DOWN else -1)
43 60
44 def add(self, widget): 61 def add(self, widget):
62 widget.parent = self
45 self.children.append(widget) 63 self.children.append(widget)
64
65 def adjust_focus(self, direction):
66 """Try and adjust focus in direction (integer)
67 """
68 if self.focussed_child is not None:
69 child = self.children[self.focussed_child]
70 if isinstance(child, Container):
71 if child.adjust_focus(direction):
72 return True
73 child.focussed = False
74
75 current = self.focussed_child
76 if current is None:
77 current = -1 if direction > 0 else len(self.children)
78 if direction > 0:
79 possibles = list(enumerate(self.children))[current + 1:]
80 else:
81 possibles = list(enumerate(self.children))[:current]
82 possibles.reverse()
83 for i, child in possibles:
84 if child.focussable:
85 child.focussed = True
86 if isinstance(child, Container):
87 if child.adjust_focus(direction):
88 self.focussed_child = i
89 return True
90 child.focussed = False
91 continue
92 else:
93 self.focussed_child = i
94 child.focussed = True
95 return True
96 else:
97 return False
46 98
47 def draw(self, surface): 99 def draw(self, surface):
48 for child in self.children: 100 for child in self.children:
49 child.draw(surface) 101 child.draw(surface)