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