Mercurial > libervia-backend
comparison frontends/primitivus/custom_widgets.py @ 119:ded2431cea5a
Primitivus: chat window / text sending.
Primitivus has now the most basics features \o/
- core: new getVersion method
- primitivus: new debug key (C-d), only work if SàT is in dev version (D in version)
- quick_app: new post_init method, used for automatique task like auto-plug
- primitivus: lists now use genericList (Box) or List (Flow)
- primitivus: List now manage correctly its size
- primitivus: new FocusFrame widget which manage focus changing with 'tab'
- primitivus: advancedEdit now manage 'click' signal
- primitivus: contactList now manager 'change' and 'click' signals
- primitivus: Chat window now working
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 05 Jul 2010 19:13:36 +0800 |
parents | 76055a209ed9 |
children | 1ca5f254ce41 |
comparison
equal
deleted
inserted
replaced
118:76055a209ed9 | 119:ded2431cea5a |
---|---|
36 def get_edit_text(self): | 36 def get_edit_text(self): |
37 return self.__real_text | 37 return self.__real_text |
38 | 38 |
39 class AdvancedEdit(urwid.Edit): | 39 class AdvancedEdit(urwid.Edit): |
40 """Edit box with some custom improvments""" | 40 """Edit box with some custom improvments""" |
41 signals = urwid.Edit.signals + ['click'] | |
41 | 42 |
42 def keypress(self, size, key): | 43 def keypress(self, size, key): |
43 #TODO: insert mode is not managed yet | 44 #TODO: insert mode is not managed yet |
44 if key == 'ctrl a': | 45 if key == 'ctrl a': |
45 key = 'home' | 46 key = 'home' |
51 elif key == 'ctrl w': | 52 elif key == 'ctrl w': |
52 before = self.edit_text[:self.edit_pos] | 53 before = self.edit_text[:self.edit_pos] |
53 pos = before.rstrip().rfind(" ")+1 | 54 pos = before.rstrip().rfind(" ")+1 |
54 self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:]) | 55 self.set_edit_text(before[:pos] + self.edit_text[self.edit_pos:]) |
55 self.set_edit_pos(pos) | 56 self.set_edit_pos(pos) |
57 elif key == 'enter': | |
58 self._emit('click') | |
56 return super(AdvancedEdit, self).keypress(size, key) | 59 return super(AdvancedEdit, self).keypress(size, key) |
57 | 60 |
58 | 61 |
59 class SelectableText(urwid.FlowWidget): | 62 class SelectableText(urwid.FlowWidget): |
60 signals = ['change'] | 63 signals = ['change'] |
71 """Change state | 74 """Change state |
72 @param selected: boolean state value | 75 @param selected: boolean state value |
73 @param invisible: don't emit change signal if True""" | 76 @param invisible: don't emit change signal if True""" |
74 assert(type(selected)==bool) | 77 assert(type(selected)==bool) |
75 self.__selected=selected | 78 self.__selected=selected |
79 self._invalidate() | |
76 if not invisible: | 80 if not invisible: |
77 self._emit("change", self.__selected) | 81 self._emit("change", self.__selected) |
78 self._invalidate() | |
79 | 82 |
80 def getState(self): | 83 def getState(self): |
81 return self.__selected | 84 return self.__selected |
82 | 85 |
83 def selectable(self): | 86 def selectable(self): |
99 attr = 'selected' if self.__selected else 'default' | 102 attr = 'selected' if self.__selected else 'default' |
100 if focus: | 103 if focus: |
101 attr+="_focus" | 104 attr+="_focus" |
102 return urwid.Text((attr,self.text), align=self.align) | 105 return urwid.Text((attr,self.text), align=self.align) |
103 | 106 |
104 class List(urwid.WidgetWrap): | 107 class GenericList(urwid.WidgetWrap): |
105 signals = ['change'] | 108 signals = ['click','change'] |
106 | 109 |
107 def __init__(self, options, style=[], align='left', on_state_change=None, user_data=None): | 110 def __init__(self, options, style=[], align='left', on_click=None, on_change=None, user_data=None): |
111 """ | |
112 Widget managing list of string and their selection | |
113 @param options: list of strings used for options | |
114 @param style: list of string: | |
115 - 'single' if only one must be selected | |
116 - 'no_first_select' nothing selected when list is first displayed | |
117 - 'can_select_none' if we can select nothing | |
118 @param align: alignement of text inside the list | |
119 @param on_click: method called when click signal is emited | |
120 @param user_data: data sent to the callback for click signal | |
121 """ | |
108 self.single = 'single' in style | 122 self.single = 'single' in style |
123 self.no_first_select = 'no_first_select' in style | |
124 self.can_select_none = 'can_select_none' in style | |
109 self.align = align | 125 self.align = align |
126 self.first_display = True | |
110 | 127 |
111 if on_state_change: | 128 if on_click: |
112 urwid.connect_signal(self, 'change', on_state_change, user_data) | 129 urwid.connect_signal(self, 'click', on_click, user_data) |
130 | |
131 if on_change: | |
132 urwid.connect_signal(self, 'change', on_change, user_data) | |
113 | 133 |
114 self.content = urwid.SimpleListWalker([]) | 134 self.content = urwid.SimpleListWalker([]) |
115 self.list_box = urwid.ListBox(self.content) | 135 self.list_box = urwid.ListBox(self.content) |
116 urwid.WidgetWrap.__init__(self, self.list_box) | 136 urwid.WidgetWrap.__init__(self, self.list_box) |
117 self.changeValues(options) | 137 self.changeValues(options) |
118 | 138 |
119 def __onStateChange(self, widget, selected): | 139 def __onStateChange(self, widget, selected): |
120 if self.single: | 140 if self.single: |
121 if not selected: | 141 if not selected and not self.can_select_none: |
122 #if in single mode, it's forbidden to unselect a value | 142 #if in single mode, it's forbidden to unselect a value |
123 widget.setState(True, invisible=True) | 143 widget.setState(True, invisible=True) |
124 return | 144 return |
125 else: | 145 if selected: |
126 self.unselectAll(invisible=True) | 146 self.unselectAll(invisible=True) |
127 widget.setState(True, invisible=True) | 147 widget.setState(True, invisible=True) |
128 self._emit("change") | 148 self._emit("click") |
129 | 149 |
130 | 150 |
131 def unselectAll(self, invisible=False): | 151 def unselectAll(self, invisible=False): |
132 for widget in self.content: | 152 for widget in self.content: |
133 if widget.getState(): | 153 if widget.getState(): |
134 widget.setState(False, invisible) | 154 widget.setState(False, invisible) |
135 widget._invalidate() | 155 widget._invalidate() |
136 | 156 |
137 def deleteValue(self, value): | 157 def deleteValue(self, value): |
138 """Delete the first value equal to the param given""" | 158 """Delete the first value equal to the param given""" |
139 try: | 159 for widget in self.content: |
140 self.content.remove(value) | 160 if widget.getValue() == value: |
141 except ValueError: | 161 self.content.remove(widget) |
142 raise ValuError("%s ==> %s" % (str(value),str(self.content))) | 162 self._emit('change') |
143 | 163 return |
144 def getValue(self): | 164 raise ValueError("%s ==> %s" % (str(value),str(self.content))) |
165 | |
166 def getSelectedValue(self): | |
145 """Convenience method to get the value selected as a string in single mode, or None""" | 167 """Convenience method to get the value selected as a string in single mode, or None""" |
146 values = self.getValues() | 168 values = self.getSelectedValues() |
147 return values[0] if values else None | 169 return values[0] if values else None |
148 | 170 |
149 def getValues(self): | 171 def getAllValues(self): |
172 """Return values of all items""" | |
173 return [widget.getValue() for widget in self.content] | |
174 | |
175 def getSelectedValues(self): | |
176 """Return values of selected items""" | |
150 result = [] | 177 result = [] |
151 for widget in self.content: | 178 for widget in self.content: |
152 if widget.getState(): | 179 if widget.getState(): |
153 result.append(widget.getValue()) | 180 result.append(widget.getValue()) |
154 return result | 181 return result |
155 | 182 |
183 def getDisplayWidget(self): | |
184 return self.list_box | |
185 | |
156 def changeValues(self, new_values): | 186 def changeValues(self, new_values): |
157 """Change all value in one shot""" | 187 """Change all value in one shot""" |
158 widgets = [SelectableText(option, self.align) for option in new_values] | 188 if not self.first_display: |
159 for widget in widgets: | 189 old_selected = self.getSelectedValues() |
190 widgets = [] | |
191 for option in new_values: | |
192 widget = SelectableText(option, self.align) | |
193 if not self.first_display and option in old_selected: | |
194 widget.setState(True) | |
195 widgets.append(widget) | |
160 urwid.connect_signal(widget, 'change', self.__onStateChange) | 196 urwid.connect_signal(widget, 'change', self.__onStateChange) |
161 self.content[:] = widgets | 197 self.content[:] = widgets |
162 if self.single and new_values: | 198 if self.first_display and self.single and new_values and not self.no_first_select: |
163 self.content[0].setState(True) | 199 self.content[0].setState(True) |
164 display_widget = urwid.BoxAdapter(self.list_box, min(len(new_values),5) or 1) | 200 display_widget = self.getDisplayWidget() |
165 self._set_w(display_widget) | 201 self._set_w(display_widget) |
166 | 202 self._emit('change') |
203 self.first_display = False | |
204 | |
167 def selectValue(self, value): | 205 def selectValue(self, value): |
168 self.unselectAll() | 206 self.unselectAll() |
169 idx = 0 | 207 idx = 0 |
170 for widget in self.content: | 208 for widget in self.content: |
171 if widget.getValue() == value: | 209 if widget.getSelectedValue() == value: |
172 widget.setState(True) | 210 widget.setState(True) |
173 self.list_box.set_focus(idx) | 211 self.list_box.set_focus(idx) |
174 return | 212 return |
175 idx+=1 | 213 idx+=1 |
176 | 214 |
177 class genericDialog(urwid.WidgetWrap): | 215 class List(urwid.FlowWidget): |
216 """FlowWidget list, same arguments as GenericList, with an additional one 'max_height'""" | |
217 signals = ['click','change'] | |
218 | |
219 def __init__(self, options, style=[], max_height=5, align='left', on_click=None, on_change=None, user_data=None): | |
220 self.genericList = GenericList(options, style, align, on_click, on_change, user_data) | |
221 self.max_height = max_height | |
222 | |
223 def selectable(self): | |
224 return True | |
225 | |
226 def keypress(self, size, key): | |
227 return self.displayWidget(size,True).keypress(size, key) | |
228 | |
229 def unselectAll(self, invisible=False): | |
230 return self.genericList.unselectAll(invisible) | |
231 | |
232 def deleteValue(self, value): | |
233 return self.genericList.deleteValue(value) | |
234 | |
235 def getSelectedValue(self): | |
236 return self.genericList.getSelectedValue() | |
237 | |
238 def getAllValues(self): | |
239 return self.genericList.getAllValues() | |
240 | |
241 def getSelectedValues(self): | |
242 return self.genericList.getSelectedValues() | |
243 | |
244 def changeValues(self, new_values): | |
245 return self.genericList.changeValues(new_values) | |
246 | |
247 def selectValue(self, value): | |
248 return self.genericList.selectValue(value) | |
249 | |
250 def render(self, size, focus=False): | |
251 return self.displayWidget(size, focus).render(size, focus) | |
252 | |
253 def rows(self, size, focus=False): | |
254 return self.displayWidget(size, focus).rows(size, focus) | |
255 | |
256 def displayWidget(self, size, focus): | |
257 list_size = sum([wid.rows(size, focus) for wid in self.genericList.content]) | |
258 height = min(list_size,self.max_height) | |
259 return urwid.BoxAdapter(self.genericList, height) | |
260 | |
261 class GenericDialog(urwid.WidgetWrap): | |
178 | 262 |
179 def __init__(self, widgets_lst, title, style=[], **kwargs): | 263 def __init__(self, widgets_lst, title, style=[], **kwargs): |
180 frame_header = urwid.AttrMap(urwid.Text(title,'center'),'title') | 264 frame_header = urwid.AttrMap(urwid.Text(title,'center'),'title') |
181 | 265 |
182 buttons = None | 266 buttons = None |
198 decorated_frame = urwid.LineBox(frame) | 282 decorated_frame = urwid.LineBox(frame) |
199 urwid.WidgetWrap.__init__(self, decorated_frame) | 283 urwid.WidgetWrap.__init__(self, decorated_frame) |
200 | 284 |
201 | 285 |
202 | 286 |
203 class InputDialog(genericDialog): | 287 class InputDialog(GenericDialog): |
204 | 288 |
205 def __init__(self, title, instrucions, style=['OK/CANCEL'], **kwargs): | 289 def __init__(self, title, instrucions, style=['OK/CANCEL'], **kwargs): |
206 instr_wid = urwid.Text(instrucions+':') | 290 instr_wid = urwid.Text(instrucions+':') |
207 edit_box = urwid.Edit() | 291 edit_box = urwid.Edit() |
208 genericDialog.__init__(self, [instr_wid,edit_box], title, style, ok_value=edit_box, **kwargs) | 292 GenericDialog.__init__(self, [instr_wid,edit_box], title, style, ok_value=edit_box, **kwargs) |
209 | 293 |
210 class ConfirmDialog(genericDialog): | 294 class ConfirmDialog(GenericDialog): |
211 | 295 |
212 def __init__(self, title, style=['YES/NO'], **kwargs): | 296 def __init__(self, title, style=['YES/NO'], **kwargs): |
213 genericDialog.__init__(self, [], title, style, yes_value=None, **kwargs) | 297 GenericDialog.__init__(self, [], title, style, yes_value=None, **kwargs) |
214 | 298 |
215 class Alert(genericDialog): | 299 class Alert(GenericDialog): |
216 | 300 |
217 def __init__(self, title, message, style=['OK'], **kwargs): | 301 def __init__(self, title, message, style=['OK'], **kwargs): |
218 genericDialog.__init__(self, [urwid.Text(message, 'center')], title, style, ok_value=None, **kwargs) | 302 GenericDialog.__init__(self, [urwid.Text(message, 'center')], title, style, ok_value=None, **kwargs) |
303 | |
304 class FocusFrame(urwid.Frame): | |
305 """Frame which manage "tab" key""" | |
306 | |
307 def keypress(self, size, key): | |
308 if key == 'tab': | |
309 focus_list = ('header','body','footer') | |
310 focus_idx = focus_list.index(self.focus_part) | |
311 for i in range(2): | |
312 focus_idx = (focus_idx + 1) % len(focus_list) | |
313 focus_name = focus_list[focus_idx] | |
314 widget = getattr(self,'_'+focus_name) | |
315 if widget!=None and widget.selectable(): | |
316 self.set_focus(focus_name) | |
317 | |
318 return urwid.Frame.keypress(self, size, key) |