12 """ |
12 """ |
13 |
13 |
14 def __init__(self, layout_class=FixedLayout): |
14 def __init__(self, layout_class=FixedLayout): |
15 Widget.__init__(self) |
15 Widget.__init__(self) |
16 #: List of child widgets. |
16 #: List of child widgets. |
17 self.children = [] |
17 self._widgets = [] |
18 self.focus_child = None |
18 #: Widget with keyboard focus |
|
19 self.focus_widget = None |
|
20 #: If True, tab cycles inside container |
|
21 self.trap_focus = False |
19 self.layout = layout_class() |
22 self.layout = layout_class() |
20 |
23 |
21 def add(self, widget): |
24 def add(self, widget): |
22 """Add widget into container.""" |
25 """Add widget into container.""" |
23 self.children.append(widget) |
26 self._widgets.append(widget) |
24 widget.parent = self |
27 widget.parent = self |
25 widget.window = self.window |
28 widget.window = self.window |
26 widget.set_theme(self.theme) |
29 widget.set_theme(self.theme) |
27 self.layout.add(widget) |
30 self.layout.add(widget) |
28 if self.focus_child is None: |
31 if self.focus_widget is None and widget.can_focus(): |
29 self.focus_child = widget |
32 self.focus_widget = widget |
30 |
33 |
31 def resize(self, w, h): |
34 def resize(self, w, h): |
32 Widget.resize(self, w, h) |
35 Widget.resize(self, w, h) |
33 self.layout.resize() |
36 self.layout.resize() |
34 |
37 |
35 def draw(self, buffer): |
38 def draw(self, buffer): |
36 """Draw child widgets.""" |
39 """Draw child widgets.""" |
37 Widget.draw(self, buffer) |
40 Widget.draw(self, buffer) |
38 for child in self.children: |
41 for child in self._widgets: |
39 with buffer.moved_origin(child.x, child.y): |
42 with buffer.moved_origin(child.x, child.y): |
40 with buffer.clip(buffer.origin.x, buffer.origin.y, |
43 with buffer.clip(buffer.origin.x, buffer.origin.y, |
41 child.width, child.height): |
44 child.width, child.height): |
42 child.draw(buffer) |
45 child.draw(buffer) |
43 |
46 |
44 def set_theme(self, theme): |
47 def set_theme(self, theme): |
45 Widget.set_theme(self, theme) |
48 Widget.set_theme(self, theme) |
46 for child in self.children: |
49 for child in self._widgets: |
47 child.set_theme(theme) |
50 child.set_theme(theme) |
48 |
51 |
49 @property |
52 @property |
50 def cursor(self): |
53 def cursor(self): |
51 if self.focus_child: |
54 if self.focus_widget: |
52 cursor = self.focus_child.cursor |
55 cursor = self.focus_widget.cursor |
53 if cursor is not None: |
56 if cursor is not None: |
54 return cursor.moved(*self.focus_child.pos) |
57 return cursor.moved(*self.focus_widget.pos) |
55 else: |
58 else: |
56 if self._cursor is not None: |
59 if self._cursor is not None: |
57 return Point(self._cursor) |
60 return Point(self._cursor) |
58 |
61 |
59 ## input events ## |
62 ## input events ## |
60 |
63 |
61 def keypress(self, keyname, char, mod=0): |
64 def keypress(self, keyname, char, mod): |
62 if self.focus_child: |
65 # First, handle the keypress event to focused child widget |
63 self.focus_child.keypress(keyname, char, mod) |
66 if self.focus_widget is not None: |
|
67 if self.focus_widget.keypress(keyname, char, mod): |
|
68 return True |
|
69 # Next, handle default key behaviour by Container |
|
70 if keyname == 'tab': |
|
71 return self.focus_next(-1 if 'shift' in mod else 1) |
|
72 # Finally, handle default keys by Widget |
|
73 # and send keypress signal |
|
74 if Widget.keypress(self, keyname, char, mod): |
|
75 return True |
|
76 |
|
77 ## focus ## |
|
78 |
|
79 def focus_next(self, step=1): |
|
80 """Focus next child. |
|
81 |
|
82 Sets focus to next child, if there is one |
|
83 which can be focused. Cycles from last child |
|
84 to first when needed. Return value depends on |
|
85 this cycling: |
|
86 |
|
87 * False means there wasn't any child to focus |
|
88 before end of list. Focus was either not changed |
|
89 or first child was focused. |
|
90 |
|
91 * True when focus is set to next child in normal |
|
92 way or when self.trap_focus is set. |
|
93 |
|
94 Return value is supposed to be returned from keypress |
|
95 event - in that case, True stops event propagation. |
|
96 |
|
97 """ |
|
98 if self.focus_widget is None: |
|
99 idx_current = 0 |
|
100 else: |
|
101 idx_current = self._widgets.index(self.focus_widget) |
|
102 idx_new = idx_current |
|
103 cycled = False |
|
104 while True: |
|
105 idx_new += step |
|
106 if idx_new >= len(self._widgets): |
|
107 idx_new = 0 |
|
108 cycled = True |
|
109 if idx_new < 0: # for focus_previous |
|
110 idx_new = len(self._widgets) - 1 |
|
111 cycled = True |
|
112 if idx_current == idx_new: |
|
113 return False |
|
114 if self._widgets[idx_new].can_focus(): |
|
115 self.focus_widget = self._widgets[idx_new] |
|
116 return self.trap_focus or not cycled |
|
117 |
|
118 def focus_previous(self): |
|
119 """Focus previous child.""" |
|
120 self.focus_next(-1) |