Mercurial > libervia-backend
comparison frontends/src/wix/xmlui.py @ 1106:e2e1e27a3680
frontends: XMLUI refactoring + dialogs:
- there are now XMLUIPanel and XMLUIDialog both inheriting from XMLUIBase
- following dialogs are managed:
- MessageDialog
- NoteDialog
- ConfirmDialog
- FileDialog
- XMLUI creation is now made using xmlui.create(...) instead of instanciating directly XMLUI
- classes must be registed in frontends
- "parent" attribute renamed to "_xmlui_parent" to avoid name conflicts with frontends toolkits
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 13 Aug 2014 14:48:49 +0200 |
parents | 8e0072754413 |
children | f91e7028e2c3 |
comparison
equal
deleted
inserted
replaced
1105:018bdd687747 | 1106:e2e1e27a3680 |
---|---|
21 | 21 |
22 from sat.core.i18n import _ | 22 from sat.core.i18n import _ |
23 import wx | 23 import wx |
24 from sat.core.log import getLogger | 24 from sat.core.log import getLogger |
25 log = getLogger(__name__) | 25 log = getLogger(__name__) |
26 from sat.tools.jid import JID | |
27 from sat_frontends.tools import xmlui | 26 from sat_frontends.tools import xmlui |
28 from sat_frontends.constants import Const | 27 from sat_frontends.constants import Const as C |
29 | 28 |
30 | 29 |
31 class EventWidget(object): | 30 class EventWidget(object): |
32 """ Used to manage change event of widgets """ | 31 """ Used to manage change event of widgets """ |
33 | 32 |
51 return self.GetValue() | 50 return self.GetValue() |
52 | 51 |
53 | 52 |
54 class EmptyWidget(WixWidget, xmlui.EmptyWidget, wx.Window): | 53 class EmptyWidget(WixWidget, xmlui.EmptyWidget, wx.Window): |
55 | 54 |
56 def __init__(self, parent): | 55 def __init__(self, _xmlui_parent): |
57 wx.Window.__init__(self, parent, -1) | 56 wx.Window.__init__(self, _xmlui_parent, -1) |
58 | 57 |
59 | 58 |
60 class TextWidget(WixWidget, xmlui.TextWidget, wx.StaticText): | 59 class TextWidget(WixWidget, xmlui.TextWidget, wx.StaticText): |
61 | 60 |
62 def __init__(self, parent, value): | 61 def __init__(self, _xmlui_parent, value): |
63 wx.StaticText.__init__(self, parent, -1, value) | 62 wx.StaticText.__init__(self, _xmlui_parent, -1, value) |
64 | 63 |
65 | 64 |
66 class LabelWidget(xmlui.LabelWidget, TextWidget): | 65 class LabelWidget(xmlui.LabelWidget, TextWidget): |
67 | 66 |
68 def __init__(self, parent, value): | 67 def __init__(self, _xmlui_parent, value): |
69 super(LabelWidget, self).__init__(parent, value+": ") | 68 super(LabelWidget, self).__init__(_xmlui_parent, value+": ") |
70 | 69 |
71 | 70 |
72 class JidWidget(xmlui.JidWidget, TextWidget): | 71 class JidWidget(xmlui.JidWidget, TextWidget): |
73 pass | 72 pass |
74 | 73 |
75 | 74 |
76 class DividerWidget(WixWidget, xmlui.DividerWidget, wx.StaticLine): | 75 class DividerWidget(WixWidget, xmlui.DividerWidget, wx.StaticLine): |
77 | 76 |
78 def __init__(self, parent, style='line'): | 77 def __init__(self, _xmlui_parent, style='line'): |
79 wx.StaticLine.__init__(self, parent, -1) | 78 wx.StaticLine.__init__(self, _xmlui_parent, -1) |
80 | 79 |
81 | 80 |
82 class StringWidget(EventWidget, ValueWidget, xmlui.StringWidget, wx.TextCtrl): | 81 class StringWidget(EventWidget, ValueWidget, xmlui.StringWidget, wx.TextCtrl): |
83 _xmlui_change_event = wx.EVT_TEXT | 82 _xmlui_change_event = wx.EVT_TEXT |
84 | 83 |
85 def __init__(self, parent, value, read_only=False): | 84 def __init__(self, _xmlui_parent, value, read_only=False): |
86 style = wx.TE_READONLY if read_only else 0 | 85 style = wx.TE_READONLY if read_only else 0 |
87 wx.TextCtrl.__init__(self, parent, -1, value, style=style) | 86 wx.TextCtrl.__init__(self, _xmlui_parent, -1, value, style=style) |
88 self._xmlui_proportion = 1 | 87 self._xmlui_proportion = 1 |
89 | 88 |
90 | 89 |
91 class PasswordWidget(EventWidget, ValueWidget, xmlui.PasswordWidget, wx.TextCtrl): | 90 class PasswordWidget(EventWidget, ValueWidget, xmlui.PasswordWidget, wx.TextCtrl): |
92 _xmlui_change_event = wx.EVT_TEXT | 91 _xmlui_change_event = wx.EVT_TEXT |
93 | 92 |
94 def __init__(self, parent, value, read_only=False): | 93 def __init__(self, _xmlui_parent, value, read_only=False): |
95 style = wx.TE_PASSWORD | 94 style = wx.TE_PASSWORD |
96 if read_only: | 95 if read_only: |
97 style |= wx.TE_READONLY | 96 style |= wx.TE_READONLY |
98 wx.TextCtrl.__init__(self, parent, -1, value, style=style) | 97 wx.TextCtrl.__init__(self, _xmlui_parent, -1, value, style=style) |
99 self._xmlui_proportion = 1 | 98 self._xmlui_proportion = 1 |
100 | 99 |
101 | 100 |
102 class TextBoxWidget(EventWidget, ValueWidget, xmlui.TextBoxWidget, wx.TextCtrl): | 101 class TextBoxWidget(EventWidget, ValueWidget, xmlui.TextBoxWidget, wx.TextCtrl): |
103 _xmlui_change_event = wx.EVT_TEXT | 102 _xmlui_change_event = wx.EVT_TEXT |
104 | 103 |
105 def __init__(self, parent, value, read_only=False): | 104 def __init__(self, _xmlui_parent, value, read_only=False): |
106 style = wx.TE_MULTILINE | 105 style = wx.TE_MULTILINE |
107 if read_only: | 106 if read_only: |
108 style |= wx.TE_READONLY | 107 style |= wx.TE_READONLY |
109 wx.TextCtrl.__init__(self, parent, -1, value, style=style) | 108 wx.TextCtrl.__init__(self, _xmlui_parent, -1, value, style=style) |
110 self._xmlui_proportion = 1 | 109 self._xmlui_proportion = 1 |
111 | 110 |
112 | 111 |
113 class BoolWidget(EventWidget, ValueWidget, xmlui.BoolWidget, wx.CheckBox): | 112 class BoolWidget(EventWidget, ValueWidget, xmlui.BoolWidget, wx.CheckBox): |
114 _xmlui_change_event = wx.EVT_CHECKBOX | 113 _xmlui_change_event = wx.EVT_CHECKBOX |
115 | 114 |
116 def __init__(self, parent, state, read_only=False): | 115 def __init__(self, _xmlui_parent, state, read_only=False): |
117 style = wx.CHK_2STATE | 116 style = wx.CHK_2STATE |
118 if read_only: | 117 if read_only: |
119 style |= wx.TE_READONLY | 118 style |= wx.TE_READONLY |
120 wx.CheckBox.__init__(self, parent, -1, "", style=wx.CHK_2STATE) | 119 wx.CheckBox.__init__(self, _xmlui_parent, -1, "", style=wx.CHK_2STATE) |
121 self.SetValue(state) | 120 self.SetValue(state) |
122 self._xmlui_proportion = 1 | 121 self._xmlui_proportion = 1 |
123 | 122 |
124 def _xmluiSetValue(self, value): | 123 def _xmluiSetValue(self, value): |
125 self.SetValue(value == 'true') | 124 self.SetValue(value == 'true') |
129 | 128 |
130 | 129 |
131 class ButtonWidget(EventWidget, WixWidget, xmlui.ButtonWidget, wx.Button): | 130 class ButtonWidget(EventWidget, WixWidget, xmlui.ButtonWidget, wx.Button): |
132 _xmlui_change_event = wx.EVT_BUTTON | 131 _xmlui_change_event = wx.EVT_BUTTON |
133 | 132 |
134 def __init__(self, parent, value, click_callback): | 133 def __init__(self, _xmlui_parent, value, click_callback): |
135 wx.Button.__init__(self, parent, -1, value) | 134 wx.Button.__init__(self, _xmlui_parent, -1, value) |
136 self._xmlui_click_callback = click_callback | 135 self._xmlui_click_callback = click_callback |
137 parent.Bind(wx.EVT_BUTTON, lambda evt: click_callback(evt.GetEventObject()), self) | 136 _xmlui_parent.Bind(wx.EVT_BUTTON, lambda evt: click_callback(evt.GetEventObject()), self) |
138 self.parent = parent | 137 self._xmlui_parent = _xmlui_parent |
139 | 138 |
140 def _xmluiOnClick(self, callback): | 139 def _xmluiOnClick(self, callback): |
141 self.parent.Bind(wx.EVT_BUTTON, lambda evt: callback(evt.GetEventObject()), self) | 140 self._xmlui_parent.Bind(wx.EVT_BUTTON, lambda evt: callback(evt.GetEventObject()), self) |
142 | 141 |
143 | 142 |
144 class ListWidget(EventWidget, WixWidget, xmlui.ListWidget, wx.ListBox): | 143 class ListWidget(EventWidget, WixWidget, xmlui.ListWidget, wx.ListBox): |
145 _xmlui_change_event = wx.EVT_LISTBOX | 144 _xmlui_change_event = wx.EVT_LISTBOX |
146 | 145 |
147 def __init__(self, parent, options, selected, flags): | 146 def __init__(self, _xmlui_parent, options, selected, flags): |
148 styles = wx.LB_MULTIPLE if not 'single' in flags else wx.LB_SINGLE | 147 styles = wx.LB_MULTIPLE if not 'single' in flags else wx.LB_SINGLE |
149 wx.ListBox.__init__(self, parent, -1, choices=[option[1] for option in options], style=styles) | 148 wx.ListBox.__init__(self, _xmlui_parent, -1, choices=[option[1] for option in options], style=styles) |
150 self._xmlui_attr_map = {label: value for value, label in options} | 149 self._xmlui_attr_map = {label: value for value, label in options} |
151 self._xmlui_proportion = 1 | 150 self._xmlui_proportion = 1 |
152 self._xmluiSelectValues(selected) | 151 self._xmluiSelectValues(selected) |
153 | 152 |
154 def _xmluiSelectValue(self, value): | 153 def _xmluiSelectValue(self, value): |
190 self.sizer.Add(widget, self._xmlui_proportion, flag=wx.EXPAND) | 189 self.sizer.Add(widget, self._xmlui_proportion, flag=wx.EXPAND) |
191 | 190 |
192 | 191 |
193 class AdvancedListContainer(WixContainer, xmlui.AdvancedListContainer, wx.ScrolledWindow): | 192 class AdvancedListContainer(WixContainer, xmlui.AdvancedListContainer, wx.ScrolledWindow): |
194 | 193 |
195 def __init__(self, parent, columns, selectable='no'): | 194 def __init__(self, _xmlui_parent, columns, selectable='no'): |
196 wx.ScrolledWindow.__init__(self, parent) | 195 wx.ScrolledWindow.__init__(self, _xmlui_parent) |
197 self._xmlui_selectable = selectable != 'no' | 196 self._xmlui_selectable = selectable != 'no' |
198 if selectable: | 197 if selectable: |
199 columns += 1 | 198 columns += 1 |
200 self.sizer = wx.FlexGridSizer(cols=columns) | 199 self.sizer = wx.FlexGridSizer(cols=columns) |
201 self.SetSizer(self.sizer) | 200 self.SetSizer(self.sizer) |
228 def _xmluiOnSelect(self, callback): | 227 def _xmluiOnSelect(self, callback): |
229 self._xmlui_select_cb = callback | 228 self._xmlui_select_cb = callback |
230 | 229 |
231 class PairsContainer(WixContainer, xmlui.PairsContainer, wx.Panel): | 230 class PairsContainer(WixContainer, xmlui.PairsContainer, wx.Panel): |
232 | 231 |
233 def __init__(self, parent): | 232 def __init__(self, _xmlui_parent): |
234 wx.Panel.__init__(self, parent) | 233 wx.Panel.__init__(self, _xmlui_parent) |
235 self.sizer = wx.FlexGridSizer(cols=2) | 234 self.sizer = wx.FlexGridSizer(cols=2) |
236 self.sizer.AddGrowableCol(1) #The growable column need most of time to be the right one in pairs | 235 self.sizer.AddGrowableCol(1) #The growable column need most of time to be the right one in pairs |
237 self.SetSizer(self.sizer) | 236 self.SetSizer(self.sizer) |
238 | 237 |
239 | 238 |
240 class TabsContainer(WixContainer, xmlui.TabsContainer, wx.Notebook): | 239 class TabsContainer(WixContainer, xmlui.TabsContainer, wx.Notebook): |
241 | 240 |
242 def __init__(self, parent): | 241 def __init__(self, _xmlui_parent): |
243 wx.Notebook.__init__(self, parent, -1, style=wx.NB_LEFT if self._xmlui_main.type=='param' else 0) | 242 wx.Notebook.__init__(self, _xmlui_parent, -1, style=wx.NB_LEFT if self._xmlui_main.type=='param' else 0) |
244 | 243 |
245 def _xmluiAddTab(self, label): | 244 def _xmluiAddTab(self, label): |
246 tab_panel = wx.Panel(self, -1) | 245 tab_panel = wx.Panel(self, -1) |
247 tab_panel.sizer = wx.BoxSizer(wx.VERTICAL) | 246 tab_panel.sizer = wx.BoxSizer(wx.VERTICAL) |
248 tab_panel.SetSizer(tab_panel.sizer) | 247 tab_panel.SetSizer(tab_panel.sizer) |
251 return tab_panel | 250 return tab_panel |
252 | 251 |
253 | 252 |
254 class VerticalContainer(WixContainer, xmlui.VerticalContainer, wx.Panel): | 253 class VerticalContainer(WixContainer, xmlui.VerticalContainer, wx.Panel): |
255 | 254 |
256 def __init__(self, parent): | 255 def __init__(self, _xmlui_parent): |
257 wx.Panel.__init__(self, parent) | 256 wx.Panel.__init__(self, _xmlui_parent) |
258 self.sizer = wx.BoxSizer(wx.VERTICAL) | 257 self.sizer = wx.BoxSizer(wx.VERTICAL) |
259 self.SetSizer(self.sizer) | 258 self.SetSizer(self.sizer) |
260 | 259 |
261 | 260 |
262 class WidgetFactory(object): | 261 ## Dialogs ## |
262 | |
263 | |
264 class WixDialog(object): | |
265 | |
266 def __init__(self, _xmlui_parent, level): | |
267 self.host = _xmlui_parent.host | |
268 self.ok_cb = None | |
269 self.cancel_cb = None | |
270 if level == C.XMLUI_DATA_LVL_INFO: | |
271 self.flags = wx.ICON_INFORMATION | |
272 elif level == C.XMLUI_DATA_LVL_ERROR: | |
273 self.flags = wx.ICON_ERROR | |
274 else: | |
275 self.flags = wx.ICON_INFORMATION | |
276 log.warning(_("Unmanaged dialog level: %s") % level) | |
277 | |
278 def _xmluiShow(self): | |
279 answer = self.ShowModal() | |
280 if answer == wx.ID_YES or answer == wx.ID_OK: | |
281 self._xmluiValidated() | |
282 else: | |
283 self._xmluiCancelled() | |
284 | |
285 def _xmluiClose(self): | |
286 self.Destroy() | |
287 | |
288 | |
289 class MessageDialog(WixDialog, xmlui.MessageDialog, wx.MessageDialog): | |
290 | |
291 def __init__(self, _xmlui_parent, title, message, level): | |
292 WixDialog.__init__(self, _xmlui_parent, level) | |
293 xmlui.MessageDialog.__init__(self, _xmlui_parent) | |
294 self.flags |= wx.OK | |
295 wx.MessageDialog.__init__(self, _xmlui_parent.host, message, title, style = self.flags) | |
296 | |
297 | |
298 class NoteDialog(xmlui.NoteDialog, MessageDialog): | |
299 # TODO: separate NoteDialog | |
300 pass | |
301 | |
302 | |
303 class ConfirmDialog(WixDialog, xmlui.ConfirmDialog, wx.MessageDialog): | |
304 | |
305 def __init__(self, _xmlui_parent, title, message, level, buttons_set): | |
306 WixDialog.__init__(self, _xmlui_parent, level) | |
307 xmlui.ConfirmDialog.__init__(self, _xmlui_parent) | |
308 if buttons_set == C.XMLUI_DATA_BTNS_SET_YESNO: | |
309 self.flags |= wx.YES_NO | |
310 else: | |
311 self.flags |= wx.OK | wx.CANCEL | |
312 wx.MessageDialog.__init__(self, _xmlui_parent.host, message, title, style = self.flags) | |
313 | |
314 | |
315 class FileDialog(WixDialog, xmlui.FileDialog, wx.FileDialog): | |
316 | |
317 def __init__(self, _xmlui_parent, title, message, level, filetype): | |
318 # TODO: message and filetype are not managed yet | |
319 WixDialog.__init__(self, _xmlui_parent, level) | |
320 self.flags = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT # FIXME: use the legacy flags, but must manage cases like dir or open | |
321 xmlui.FileDialog.__init__(self, _xmlui_parent) | |
322 wx.FileDialog.__init__(self, _xmlui_parent.host, title, style = self.flags) | |
323 | |
324 def _xmluiShow(self): | |
325 answer = self.ShowModal() | |
326 if answer == wx.ID_OK: | |
327 self._xmluiValidated({'path': self.GetPath()}) | |
328 else: | |
329 self._xmluiCancelled() | |
330 | |
331 | |
332 class GenericFactory(object): | |
263 | 333 |
264 def __getattr__(self, attr): | 334 def __getattr__(self, attr): |
265 if attr.startswith("create"): | 335 if attr.startswith("create"): |
266 cls = globals()[attr[6:]] | 336 cls = globals()[attr[6:]] |
337 return cls | |
338 | |
339 | |
340 class WidgetFactory(GenericFactory): | |
341 | |
342 def __getattr__(self, attr): | |
343 if attr.startswith("create"): | |
344 cls = GenericFactory.__getattr__(self, attr) | |
267 cls._xmlui_main = self._xmlui_main | 345 cls._xmlui_main = self._xmlui_main |
268 return cls | 346 return cls |
269 | 347 |
270 | 348 |
271 class XMLUI(xmlui.XMLUI, wx.Frame): | 349 class XMLUIPanel(xmlui.XMLUIPanel, wx.Frame): |
272 """Create an user interface from a SàT XML""" | 350 """Create an user interface from a SàT XML""" |
273 widget_factory = WidgetFactory() | 351 widget_factory = WidgetFactory() |
274 | 352 |
275 def __init__(self, host, xml_data, title=None, flags = None,): | 353 def __init__(self, host, parsed_xml, title=None, flags = None,): |
276 self.widget_factory._xmlui_main = self | 354 self.widget_factory._xmlui_main = self |
277 xmlui.XMLUI.__init__(self, host, xml_data, title, flags) | 355 xmlui.XMLUIPanel.__init__(self, host, parsed_xml, title, flags) |
278 | 356 |
279 def constructUI(self, xml_data): | 357 def constructUI(self, parsed_dom): |
280 style = wx.DEFAULT_FRAME_STYLE & ~wx.CLOSE_BOX if 'NO_CANCEL' in self.flags else wx.DEFAULT_FRAME_STYLE | 358 style = wx.DEFAULT_FRAME_STYLE & ~wx.CLOSE_BOX if 'NO_CANCEL' in self.flags else wx.DEFAULT_FRAME_STYLE |
281 wx.Frame.__init__(self, None, style=style) | 359 wx.Frame.__init__(self, None, style=style) |
282 self.sizer = wx.BoxSizer(wx.VERTICAL) | 360 self.sizer = wx.BoxSizer(wx.VERTICAL) |
283 self.SetSizer(self.sizer) | 361 self.SetSizer(self.sizer) |
284 | 362 |
300 | 378 |
301 self.sizer.Add(self.main_cont, 1, flag=wx.EXPAND) | 379 self.sizer.Add(self.main_cont, 1, flag=wx.EXPAND) |
302 self.sizer.Fit(self) | 380 self.sizer.Fit(self) |
303 self.Show() | 381 self.Show() |
304 | 382 |
305 super(XMLUI, self).constructUI(xml_data, postTreat) | 383 super(XMLUIPanel, self).constructUI(parsed_dom, postTreat) |
306 if not 'NO_CANCEL' in self.flags: | 384 if not 'NO_CANCEL' in self.flags: |
307 self.Bind(wx.EVT_CLOSE, self.onClose, self) | 385 self.Bind(wx.EVT_CLOSE, self.onClose, self) |
308 self.MakeModal() | 386 self.MakeModal() |
309 | 387 |
310 def _xmluiClose(self): | 388 def _xmluiClose(self): |
312 self.Destroy() | 390 self.Destroy() |
313 | 391 |
314 ###events | 392 ###events |
315 | 393 |
316 def onParamChange(self, ctrl): | 394 def onParamChange(self, ctrl): |
317 super(XMLUI, self).onParamChange(ctrl) | 395 super(XMLUIPanel, self).onParamChange(ctrl) |
318 | 396 |
319 def onFormSubmitted(self, event): | 397 def onFormSubmitted(self, event): |
320 """Called when submit button is clicked""" | 398 """Called when submit button is clicked""" |
321 button = event.GetEventObject() | 399 button = event.GetEventObject() |
322 super(XMLUI, self).onFormSubmitted(button) | 400 super(XMLUIPanel, self).onFormSubmitted(button) |
323 | 401 |
324 def onClose(self, event): | 402 def onClose(self, event): |
325 """Close event: we have to send the form.""" | 403 """Close event: we have to send the form.""" |
326 log.debug(_("close")) | 404 log.debug(_("close")) |
327 if self.type == 'param': | 405 if self.type == 'param': |
328 self.onSaveParams() | 406 self.onSaveParams() |
329 else: | 407 else: |
330 self._xmluiClose() | 408 self._xmluiClose() |
331 event.Skip() | 409 event.Skip() |
332 | 410 |
411 | |
412 class XMLUIDialog(xmlui.XMLUIDialog): | |
413 dialog_factory = WidgetFactory() | |
414 | |
415 | |
416 xmlui.registerClass(xmlui.CLASS_PANEL, XMLUIPanel) | |
417 xmlui.registerClass(xmlui.CLASS_DIALOG, XMLUIDialog) | |
418 create = xmlui.create |