annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
55
671d027f1b71 Callbacks for events in widgets
Stefano Rivera <stefano@rivera.za.net>
parents: 43
diff changeset
1 import collections
671d027f1b71 Callbacks for events in widgets
Stefano Rivera <stefano@rivera.za.net>
parents: 43
diff changeset
2
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
3 import pygame
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
4 from pygame.constants import K_UP, K_DOWN
58
7fa000c4b3c7 Dispatch key events
Stefano Rivera <stefano@rivera.za.net>
parents: 55
diff changeset
5 from pygame.locals import MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN, KEYDOWN
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
6
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
7
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
8 class Widget(object):
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
9
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
10 def __init__(self, rect):
38
047273a63054 Main menu says hello
Stefano Rivera <stefano@rivera.za.net>
parents: 24
diff changeset
11 if not isinstance(rect, pygame.Rect):
41
3f44c30a1c39 Correct Text placement
Stefano Rivera <stefano@rivera.za.net>
parents: 38
diff changeset
12 rect = pygame.Rect(rect, (0, 0))
3f44c30a1c39 Correct Text placement
Stefano Rivera <stefano@rivera.za.net>
parents: 38
diff changeset
13 self.rect = rect
58
7fa000c4b3c7 Dispatch key events
Stefano Rivera <stefano@rivera.za.net>
parents: 55
diff changeset
14 self.focussable = False
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
15 self.focussed = False
55
671d027f1b71 Callbacks for events in widgets
Stefano Rivera <stefano@rivera.za.net>
parents: 43
diff changeset
16 self.callbacks = collections.defaultdict(list)
671d027f1b71 Callbacks for events in widgets
Stefano Rivera <stefano@rivera.za.net>
parents: 43
diff changeset
17
671d027f1b71 Callbacks for events in widgets
Stefano Rivera <stefano@rivera.za.net>
parents: 43
diff changeset
18 def add_callback(self, eventtype, callback, *args):
671d027f1b71 Callbacks for events in widgets
Stefano Rivera <stefano@rivera.za.net>
parents: 43
diff changeset
19 self.callbacks[eventtype].append((callback, args))
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
20
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
21 def event(self, ev):
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
22 for callback, args in self.callbacks[ev.type]:
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
23 if callback(ev, self, *args):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
24 return True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
25 return False
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
26
24
30d4f3e62bcf Refactor widgets *again*, add container to Habitat
Stefano Rivera <stefano@rivera.za.net>
parents: 23
diff changeset
27 def draw(self, surface):
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
28 "Override me"
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
29 pass
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
30
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
31
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
32 class Container(Widget):
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
33
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
34 def __init__(self, rect, root=False):
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
35 super(Container, self).__init__(rect)
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
36 self.children = []
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
37 self.root = root
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
38 self.focussed = root
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
39 self.focussable = True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
40 self.focussed_child = None
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
41
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
42 def event(self, ev):
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
43 """Push an event down through the tree, and fire our own event as a
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
44 last resort
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
45 """
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
46 if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN):
58
7fa000c4b3c7 Dispatch key events
Stefano Rivera <stefano@rivera.za.net>
parents: 55
diff changeset
47 for child in self.children:
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
48 if child.rect.collidepoint(ev.pos):
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
49 if child.event(ev):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
50 return True
59
3cc917814579 Container subclasses Widget
Stefano Rivera <stefano@rivera.za.net>
parents: 58
diff changeset
51 if ev.type == KEYDOWN:
58
7fa000c4b3c7 Dispatch key events
Stefano Rivera <stefano@rivera.za.net>
parents: 55
diff changeset
52 for child in self.children:
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
53 if child.focussed:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
54 if child.event(ev):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
55 return True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
56 if super(Container, self).event(ev):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
57 return True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
58 if self.root and ev.type == KEYDOWN and ev.key in (K_UP, K_DOWN):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
59 self.adjust_focus(1 if ev.key == K_DOWN else -1)
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
60
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
61 def add(self, widget):
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
62 widget.parent = self
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
63 self.children.append(widget)
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
64
77
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
65 def adjust_focus(self, direction):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
66 """Try and adjust focus in direction (integer)
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
67 """
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
68 if self.focussed_child is not None:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
69 child = self.children[self.focussed_child]
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
70 if isinstance(child, Container):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
71 if child.adjust_focus(direction):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
72 return True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
73 child.focussed = False
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
74
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
75 current = self.focussed_child
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
76 if current is None:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
77 current = -1 if direction > 0 else len(self.children)
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
78 if direction > 0:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
79 possibles = list(enumerate(self.children))[current + 1:]
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
80 else:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
81 possibles = list(enumerate(self.children))[:current]
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
82 possibles.reverse()
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
83 for i, child in possibles:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
84 if child.focussable:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
85 child.focussed = True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
86 if isinstance(child, Container):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
87 if child.adjust_focus(direction):
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
88 self.focussed_child = i
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
89 return True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
90 child.focussed = False
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
91 continue
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
92 else:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
93 self.focussed_child = i
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
94 child.focussed = True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
95 return True
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
96 else:
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
97 return False
Stefano Rivera <stefano@rivera.za.net>
parents: 59
diff changeset
98
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
99 def draw(self, surface):
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents:
diff changeset
100 for child in self.children:
24
30d4f3e62bcf Refactor widgets *again*, add container to Habitat
Stefano Rivera <stefano@rivera.za.net>
parents: 23
diff changeset
101 child.draw(surface)