Mercurial > boomslang
comparison pyntnclick/widgets/base.py @ 602:1aac5a3b17e1 pyntnclick
Remove anything that has to do with focus (hopefully not breaking anything)
author | Stefano Rivera <stefano@rivera.za.net> |
---|---|
date | Sat, 11 Feb 2012 20:05:22 +0200 |
parents | b7d8b89de71a |
children | fdc63049b08c |
comparison
equal
deleted
inserted
replaced
601:0ae62d824d2f | 602:1aac5a3b17e1 |
---|---|
11 | 11 |
12 def __init__(self, rect): | 12 def __init__(self, rect): |
13 if not isinstance(rect, pygame.Rect): | 13 if not isinstance(rect, pygame.Rect): |
14 rect = pygame.Rect(rect, (0, 0)) | 14 rect = pygame.Rect(rect, (0, 0)) |
15 self.rect = rect | 15 self.rect = rect |
16 self.focussable = False | |
17 self.focussed = False | |
18 self.modal = False | 16 self.modal = False |
19 self.parent = None | 17 self.parent = None |
20 self.disabled = False | 18 self.disabled = False |
21 self.callbacks = collections.defaultdict(list) | 19 self.callbacks = collections.defaultdict(list) |
22 | 20 |
43 | 41 |
44 def draw(self, surface): | 42 def draw(self, surface): |
45 "Override me" | 43 "Override me" |
46 pass | 44 pass |
47 | 45 |
48 def grab_focus(self): | |
49 if self.focussable: | |
50 # Find the root and current focus | |
51 root = self | |
52 while root.parent is not None: | |
53 root = root.parent | |
54 focus = root | |
55 focus_modal_base = None | |
56 while (isinstance(focus, Container) | |
57 and focus.focussed_child is not None): | |
58 if focus.modal: | |
59 focus_modal_base = focus | |
60 focus = focus.children[focus.focussed_child] | |
61 | |
62 # Don't leave a modal heirarchy | |
63 if focus_modal_base: | |
64 widget = self | |
65 while widget.parent is not None: | |
66 if widget == focus_modal_base: | |
67 break | |
68 widget = widget.parent | |
69 else: | |
70 return False | |
71 | |
72 root.defocus() | |
73 widget = self | |
74 while widget.parent is not None: | |
75 parent = widget.parent | |
76 if isinstance(parent, Container): | |
77 idx = parent.children.index(widget) | |
78 parent.focussed_child = idx | |
79 widget = parent | |
80 self.focussed = True | |
81 return True | |
82 return False | |
83 | |
84 def disable(self): | 46 def disable(self): |
85 if not self.disabled: | 47 if not self.disabled: |
86 self.disabled = True | 48 self.disabled = True |
87 self._focussable_when_enabled = self.focussable | |
88 self.focussable = False | |
89 if hasattr(self, 'prepare'): | 49 if hasattr(self, 'prepare'): |
90 self.prepare() | 50 self.prepare() |
91 | 51 |
92 def enable(self): | 52 def enable(self): |
93 if self.disabled: | 53 if self.disabled: |
94 self.disabled = False | 54 self.disabled = False |
95 self.focussable = self._focussable_when_enabled | |
96 if hasattr(self, 'prepare'): | 55 if hasattr(self, 'prepare'): |
97 self.prepare() | 56 self.prepare() |
98 | 57 |
99 | 58 |
100 class Button(Widget): | 59 class Button(Widget): |
108 return True | 67 return True |
109 return False | 68 return False |
110 | 69 |
111 def forced_click(self): | 70 def forced_click(self): |
112 """Force calling the clicked handler""" | 71 """Force calling the clicked handler""" |
113 self.grab_focus() | |
114 for callback, args in self.callbacks['clicked']: | 72 for callback, args in self.callbacks['clicked']: |
115 if callback(None, self, *args): | 73 if callback(None, self, *args): |
116 return True | 74 return True |
117 return False | 75 return False |
118 | 76 |
122 def __init__(self, rect=None): | 80 def __init__(self, rect=None): |
123 if rect is None: | 81 if rect is None: |
124 rect = pygame.Rect(0, 0, 0, 0) | 82 rect = pygame.Rect(0, 0, 0, 0) |
125 super(Container, self).__init__(rect) | 83 super(Container, self).__init__(rect) |
126 self.children = [] | 84 self.children = [] |
127 self.focussed_child = None | |
128 | 85 |
129 def event(self, ev): | 86 def event(self, ev): |
130 """Push an event down through the tree, and fire our own event as a | 87 """Push an event down through the tree, and fire our own event as a |
131 last resort | 88 last resort |
132 """ | 89 """ |
133 if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN): | 90 if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN): |
134 for child in self.children[:]: | 91 for child in self.children[:]: |
135 if child.rect.collidepoint(ev.pos): | 92 if child.rect.collidepoint(ev.pos): |
136 if ev.type == MOUSEBUTTONDOWN and child.focussable: | |
137 if not child.grab_focus(): | |
138 continue | |
139 if child.event(ev): | 93 if child.event(ev): |
140 return True | 94 return True |
141 | 95 |
142 else: | 96 else: |
143 # Other events go to all children first | 97 # Other events go to all children first |
152 self.children.append(widget) | 106 self.children.append(widget) |
153 self.rect = self.rect.union(widget.rect) | 107 self.rect = self.rect.union(widget.rect) |
154 | 108 |
155 def remove(self, widget): | 109 def remove(self, widget): |
156 widget.parent = None | 110 widget.parent = None |
157 if self.focussed_child is not None: | |
158 child = self.children[self.focussed_child] | |
159 self.children.remove(widget) | 111 self.children.remove(widget) |
160 # We don't update the rect, for reasons of simplificty and laziness | |
161 if self.focussed_child is not None and child in self.children: | |
162 # Fix focus index | |
163 self.focussed_child = self.children.index(child) | |
164 else: | |
165 self.focussed_child = None | |
166 | |
167 def defocus(self): | |
168 if self.focussed_child is not None: | |
169 child = self.children[self.focussed_child] | |
170 if isinstance(child, Container): | |
171 if not child.defocus(): | |
172 return False | |
173 child.focussed = False | |
174 self.focussed_child = None | |
175 return True | |
176 | |
177 def adjust_focus(self, direction): | |
178 """Try and adjust focus in direction (integer) | |
179 """ | |
180 if self.focussed_child is not None: | |
181 child = self.children[self.focussed_child] | |
182 if isinstance(child, Container): | |
183 if child.adjust_focus(direction): | |
184 return True | |
185 elif child.modal: | |
186 # We're modal, go back | |
187 if child.adjust_focus(-direction): | |
188 return True | |
189 else: | |
190 child.focussed = False | |
191 | |
192 current = self.focussed_child | |
193 if current is None: | |
194 current = -1 if direction > 0 else len(self.children) | |
195 if direction > 0: | |
196 possibles = list(enumerate(self.children))[current + 1:] | |
197 else: | |
198 possibles = list(enumerate(self.children))[:current] | |
199 possibles.reverse() | |
200 for i, child in possibles: | |
201 if child.focussable: | |
202 child.focussed = True | |
203 self.focussed_child = i | |
204 return True | |
205 if isinstance(child, Container): | |
206 if child.adjust_focus(direction): | |
207 self.focussed_child = i | |
208 return True | |
209 else: | |
210 if self.parent is None: | |
211 if self.focussed_child is not None: | |
212 # At the end, mark the last one as focussed, again | |
213 child = self.children[self.focussed_child] | |
214 if isinstance(child, Container): | |
215 if child.adjust_focus(-direction): | |
216 return True | |
217 else: | |
218 child.focussed = True | |
219 return True | |
220 else: | |
221 self.focussed_child = None | |
222 return False | |
223 | 112 |
224 def draw(self, surface): | 113 def draw(self, surface): |
225 if self.parent is None and not self.focussed: | |
226 self.focussed = True | |
227 self.adjust_focus(1) | |
228 for child in self.children: | 114 for child in self.children: |
229 child.draw(surface) | 115 child.draw(surface) |
230 | 116 |
231 | 117 |
232 class GridContainer(Container): | 118 class GridContainer(Container): |
241 def add(self, widget): | 127 def add(self, widget): |
242 assert not isinstance(widget, Container) | 128 assert not isinstance(widget, Container) |
243 assert not widget.modal | 129 assert not widget.modal |
244 super(GridContainer, self).add(widget) | 130 super(GridContainer, self).add(widget) |
245 | 131 |
246 def adjust_focus(self, direction): | |
247 if isinstance(direction, int): | |
248 direction = (direction, 0) | |
249 | |
250 if len(self.children) == 0: | |
251 return False | |
252 | |
253 if self.focussed_child is None: | |
254 if sum(direction) > 0: | |
255 self.focussed_child = 0 | |
256 else: | |
257 self.focussed_child = len(self.children) - 1 | |
258 else: | |
259 self.children[self.focussed_child].focussed = False | |
260 if direction[0] != 0: | |
261 self.focussed_child += direction[0] | |
262 if direction[1] != 0: | |
263 self.focussed_child += self.width * direction[1] | |
264 if not 0 <= self.focussed_child < len(self.children): | |
265 self.focussed_child = None | |
266 return False | |
267 self.children[self.focussed_child].focussed = True | |
268 return True | |
269 | |
270 | 132 |
271 class Box(Container): | 133 class Box(Container): |
272 """A container that draws a filled background with a border""" | 134 """A container that draws a filled background with a border""" |
273 padding = 4 | 135 padding = 4 |
274 | 136 |