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