Mercurial > libervia-web
comparison src/browser/sat_browser/xmlui.py @ 500:67a4e8383b70
browser side (XMLUI): XMLUI update to follow core changes:
- Dialogs are now managed
- FileDialog raise a NotImplementedError, it's not yet possible in Libervia
- XMLUIPanel.show is implemented
- following core changes, we now create an XMLUI with xmlui.create(...)
- WidgetFactory now inherit from GenericFactory
- workaround for __getattr__ bug in pyjamas, now createXXX are automaticaly created with inspection
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 13 Aug 2014 14:09:09 +0200 |
parents | 1ce6133993e4 |
children | f030491cff75 |
comparison
equal
deleted
inserted
replaced
499:ec3f30253040 | 500:67a4e8383b70 |
---|---|
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from sat.core.log import getLogger | 20 from sat.core.log import getLogger |
21 log = getLogger(__name__) | 21 log = getLogger(__name__) |
22 from sat_frontends.tools import xmlui | 22 from sat_frontends.tools import xmlui |
23 from sat_browser.constants import Const as C | |
24 from sat_browser import dialog | |
23 | 25 |
24 from pyjamas.ui.VerticalPanel import VerticalPanel | 26 from pyjamas.ui.VerticalPanel import VerticalPanel |
25 from pyjamas.ui.HorizontalPanel import HorizontalPanel | 27 from pyjamas.ui.HorizontalPanel import HorizontalPanel |
26 from pyjamas.ui.TabPanel import TabPanel | 28 from pyjamas.ui.TabPanel import TabPanel |
27 from pyjamas.ui.Grid import Grid | 29 from pyjamas.ui.Grid import Grid |
37 import nativedom | 39 import nativedom |
38 | 40 |
39 | 41 |
40 class EmptyWidget(xmlui.EmptyWidget, Label): | 42 class EmptyWidget(xmlui.EmptyWidget, Label): |
41 | 43 |
42 def __init__(self, parent): | 44 def __init__(self, _xmlui_parent): |
43 Label.__init__(self, '') | 45 Label.__init__(self, '') |
44 | 46 |
45 | 47 |
46 class TextWidget(xmlui.TextWidget, Label): | 48 class TextWidget(xmlui.TextWidget, Label): |
47 | 49 |
48 def __init__(self, parent, value): | 50 def __init__(self, _xmlui_parent, value): |
49 Label.__init__(self, value) | 51 Label.__init__(self, value) |
50 | 52 |
51 | 53 |
52 class LabelWidget(xmlui.LabelWidget, TextWidget): | 54 class LabelWidget(xmlui.LabelWidget, TextWidget): |
53 | 55 |
54 def __init__(self, parent, value): | 56 def __init__(self, _xmlui_parent, value): |
55 TextWidget.__init__(self, parent, value + ": ") | 57 TextWidget.__init__(self, _xmlui_parent, value + ": ") |
56 | 58 |
57 | 59 |
58 class JidWidget(xmlui.JidWidget, TextWidget): | 60 class JidWidget(xmlui.JidWidget, TextWidget): |
59 | 61 |
60 def __init__(self, parent, value): | 62 def __init__(self, _xmlui_parent, value): |
61 TextWidget.__init__(self, parent, value) | 63 TextWidget.__init__(self, _xmlui_parent, value) |
62 | 64 |
63 | 65 |
64 class DividerWidget(xmlui.DividerWidget, HTML): | 66 class DividerWidget(xmlui.DividerWidget, HTML): |
65 | 67 |
66 def __init__(self, parent, style='line'): | 68 def __init__(self, _xmlui_parent, style='line'): |
67 """Add a divider | 69 """Add a divider |
68 | 70 |
69 @param parent | 71 @param _xmlui_parent |
70 @param style (string): one of: | 72 @param style (string): one of: |
71 - line: a simple line | 73 - line: a simple line |
72 - dot: a line of dots | 74 - dot: a line of dots |
73 - dash: a line of dashes | 75 - dash: a line of dashes |
74 - plain: a full thick line | 76 - plain: a full thick line |
78 self.addStyleName(style) | 80 self.addStyleName(style) |
79 | 81 |
80 | 82 |
81 class StringWidget(xmlui.StringWidget, TextBox): | 83 class StringWidget(xmlui.StringWidget, TextBox): |
82 | 84 |
83 def __init__(self, parent, value, read_only=False): | 85 def __init__(self, _xmlui_parent, value, read_only=False): |
84 TextBox.__init__(self) | 86 TextBox.__init__(self) |
85 self.setText(value) | 87 self.setText(value) |
86 self.setReadonly(read_only) | 88 self.setReadonly(read_only) |
87 | 89 |
88 def _xmluiSetValue(self, value): | 90 def _xmluiSetValue(self, value): |
95 self.addChangeListener(callback) | 97 self.addChangeListener(callback) |
96 | 98 |
97 | 99 |
98 class PasswordWidget(xmlui.PasswordWidget, PasswordTextBox): | 100 class PasswordWidget(xmlui.PasswordWidget, PasswordTextBox): |
99 | 101 |
100 def __init__(self, parent, value, read_only=False): | 102 def __init__(self, _xmlui_parent, value, read_only=False): |
101 PasswordTextBox.__init__(self) | 103 PasswordTextBox.__init__(self) |
102 self.setText(value) | 104 self.setText(value) |
103 self.setReadonly(read_only) | 105 self.setReadonly(read_only) |
104 | 106 |
105 def _xmluiSetValue(self, value): | 107 def _xmluiSetValue(self, value): |
112 self.addChangeListener(callback) | 114 self.addChangeListener(callback) |
113 | 115 |
114 | 116 |
115 class TextBoxWidget(xmlui.TextBoxWidget, TextArea): | 117 class TextBoxWidget(xmlui.TextBoxWidget, TextArea): |
116 | 118 |
117 def __init__(self, parent, value, read_only=False): | 119 def __init__(self, _xmlui_parent, value, read_only=False): |
118 TextArea.__init__(self) | 120 TextArea.__init__(self) |
119 self.setText(value) | 121 self.setText(value) |
120 self.setReadonly(read_only) | 122 self.setReadonly(read_only) |
121 | 123 |
122 def _xmluiSetValue(self, value): | 124 def _xmluiSetValue(self, value): |
129 self.addChangeListener(callback) | 131 self.addChangeListener(callback) |
130 | 132 |
131 | 133 |
132 class BoolWidget(xmlui.BoolWidget, CheckBox): | 134 class BoolWidget(xmlui.BoolWidget, CheckBox): |
133 | 135 |
134 def __init__(self, parent, state, read_only=False): | 136 def __init__(self, _xmlui_parent, state, read_only=False): |
135 CheckBox.__init__(self) | 137 CheckBox.__init__(self) |
136 self.setChecked(state) | 138 self.setChecked(state) |
137 self.setReadonly(read_only) | 139 self.setReadonly(read_only) |
138 | 140 |
139 def _xmluiSetValue(self, value): | 141 def _xmluiSetValue(self, value): |
146 self.addClickListener(callback) | 148 self.addClickListener(callback) |
147 | 149 |
148 | 150 |
149 class ButtonWidget(xmlui.ButtonWidget, Button): | 151 class ButtonWidget(xmlui.ButtonWidget, Button): |
150 | 152 |
151 def __init__(self, parent, value, click_callback): | 153 def __init__(self, _xmlui_parent, value, click_callback): |
152 Button.__init__(self, value, click_callback) | 154 Button.__init__(self, value, click_callback) |
153 | 155 |
154 def _xmluiOnClick(self, callback): | 156 def _xmluiOnClick(self, callback): |
155 self.addClickListener(callback) | 157 self.addClickListener(callback) |
156 | 158 |
157 | 159 |
158 class ListWidget(xmlui.ListWidget, ListBox): | 160 class ListWidget(xmlui.ListWidget, ListBox): |
159 | 161 |
160 def __init__(self, parent, options, selected, flags): | 162 def __init__(self, _xmlui_parent, options, selected, flags): |
161 ListBox.__init__(self) | 163 ListBox.__init__(self) |
162 multi_selection = 'single' not in flags | 164 multi_selection = 'single' not in flags |
163 self.setMultipleSelect(multi_selection) | 165 self.setMultipleSelect(multi_selection) |
164 if multi_selection: | 166 if multi_selection: |
165 self.setVisibleItemCount(5) | 167 self.setVisibleItemCount(5) |
207 self.append(widget) | 209 self.append(widget) |
208 | 210 |
209 | 211 |
210 class AdvancedListContainer(xmlui.AdvancedListContainer, Grid): | 212 class AdvancedListContainer(xmlui.AdvancedListContainer, Grid): |
211 | 213 |
212 def __init__(self, parent, columns, selectable='no'): | 214 def __init__(self, _xmlui_parent, columns, selectable='no'): |
213 Grid.__init__(self, 0, columns) | 215 Grid.__init__(self, 0, columns) |
214 self.columns = columns | 216 self.columns = columns |
215 self.row = -1 | 217 self.row = -1 |
216 self.col = 0 | 218 self.col = 0 |
217 self._xmlui_rows_idx = [] | 219 self._xmlui_rows_idx = [] |
253 self._xmlui_select_cb = callback | 255 self._xmlui_select_cb = callback |
254 | 256 |
255 | 257 |
256 class PairsContainer(xmlui.PairsContainer, Grid): | 258 class PairsContainer(xmlui.PairsContainer, Grid): |
257 | 259 |
258 def __init__(self, parent): | 260 def __init__(self, _xmlui_parent): |
259 Grid.__init__(self, 0, 0) | 261 Grid.__init__(self, 0, 0) |
260 self.row = 0 | 262 self.row = 0 |
261 self.col = 0 | 263 self.col = 0 |
262 | 264 |
263 def _xmluiAppend(self, widget): | 265 def _xmluiAppend(self, widget): |
270 self.col = 0 | 272 self.col = 0 |
271 | 273 |
272 | 274 |
273 class TabsContainer(LiberviaContainer, xmlui.TabsContainer, TabPanel): | 275 class TabsContainer(LiberviaContainer, xmlui.TabsContainer, TabPanel): |
274 | 276 |
275 def __init__(self, parent): | 277 def __init__(self, _xmlui_parent): |
276 TabPanel.__init__(self) | 278 TabPanel.__init__(self) |
277 self.setStyleName('liberviaTabPanel') | 279 self.setStyleName('liberviaTabPanel') |
278 | 280 |
279 def _xmluiAddTab(self, label): | 281 def _xmluiAddTab(self, label): |
280 tab_panel = VerticalContainer(self) | 282 tab_panel = VerticalContainer(self) |
285 | 287 |
286 | 288 |
287 class VerticalContainer(LiberviaContainer, xmlui.VerticalContainer, VerticalPanel): | 289 class VerticalContainer(LiberviaContainer, xmlui.VerticalContainer, VerticalPanel): |
288 __bases__ = (LiberviaContainer, xmlui.VerticalContainer, VerticalPanel) | 290 __bases__ = (LiberviaContainer, xmlui.VerticalContainer, VerticalPanel) |
289 | 291 |
290 def __init__(self, parent): | 292 def __init__(self, _xmlui_parent): |
291 VerticalPanel.__init__(self) | 293 VerticalPanel.__init__(self) |
292 | 294 |
293 | 295 |
294 class WidgetFactory(object): | 296 ## Dialogs ## |
295 # XXX: __getattr__ doesn't work here for an unknown reason | 297 |
296 | 298 |
297 def createVerticalContainer(self, *args, **kwargs): | 299 class Dlg(object): |
298 instance = VerticalContainer(*args, **kwargs) | 300 |
299 instance._xmlui_main = self._xmlui_main | 301 def _xmluiShow(self): |
302 self.show() | |
303 | |
304 def _xmluiClose(self): | |
305 pass | |
306 | |
307 | |
308 class MessageDialog(Dlg, xmlui.MessageDialog, dialog.InfoDialog): | |
309 | |
310 def __init__(self, _xmlui_parent, title, message, level): | |
311 #TODO: level is not managed | |
312 Dlg.__init__(self) | |
313 xmlui.MessageDialog.__init__(self, _xmlui_parent) | |
314 dialog.InfoDialog.__init__(self, title, message, self._xmluiValidated()) | |
315 | |
316 | |
317 class NoteDialog(xmlui.NoteDialog, MessageDialog): | |
318 # TODO: separate NoteDialog | |
319 | |
320 def __init__(self, _xmlui_parent, title, message, level): | |
321 xmlui.NoteDialog.__init__(self, _xmlui_parent) | |
322 MessageDialog.__init__(self, _xmlui_parent, title, message, level) | |
323 | |
324 | |
325 class ConfirmDialog(xmlui.ConfirmDialog, Dlg, dialog.ConfirmDialog): | |
326 | |
327 def __init__(self, _xmlui_parent, title, message, level): | |
328 #TODO: level is not managed | |
329 xmlui.ConfirmDialog.__init__(self, _xmlui_parent) | |
330 print "self.parent = %s" % self._xmlui_parent | |
331 Dlg.__init__(self) | |
332 dialog.ConfirmDialog.__init__(self, self.answered, message, title) | |
333 | |
334 def answered(self, validated): | |
335 if validated: | |
336 self._xmluiValidated() | |
337 else: | |
338 self._xmluiCancelled() | |
339 | |
340 | |
341 class FileDialog(xmlui.FileDialog, Dlg): | |
342 #TODO: | |
343 | |
344 def __init__(self, _xmlui_parent, title, message, level, filetype): | |
345 raise NotImplementedError("FileDialog is not implemented in Libervia yet") | |
346 | |
347 | |
348 class GenericFactory(object): | |
349 # XXX: __getattr__ doens't work here with pyjamas for an unknown reason | |
350 # so an introspection workaround is used | |
351 | |
352 def __init__(self): | |
353 | |
354 for name, cls in globals().items(): | |
355 if name.endswith("Widget") or name.endswith("Container") or name.endswith("Dialog"): | |
356 log.info("registering: %s" % name) | |
357 def createCreater(cls): | |
358 return lambda *args, **kwargs: self._genericCreate(cls, *args, **kwargs) | |
359 setattr(self, "create%s" % name, createCreater(cls)) | |
360 | |
361 def _genericCreate(self, cls, *args, **kwargs): | |
362 instance = cls(*args, **kwargs) | |
300 return instance | 363 return instance |
301 | |
302 def createPairsContainer(self, *args, **kwargs): | |
303 instance = PairsContainer(*args, **kwargs) | |
304 instance._xmlui_main = self._xmlui_main | |
305 return instance | |
306 | |
307 def createTabsContainer(self, *args, **kwargs): | |
308 instance = TabsContainer(*args, **kwargs) | |
309 instance._xmlui_main = self._xmlui_main | |
310 return instance | |
311 | |
312 def createAdvancedListContainer(self, *args, **kwargs): | |
313 instance = AdvancedListContainer(*args, **kwargs) | |
314 instance._xmlui_main = self._xmlui_main | |
315 return instance | |
316 | |
317 def createEmptyWidget(self, *args, **kwargs): | |
318 instance = EmptyWidget(*args, **kwargs) | |
319 instance._xmlui_main = self._xmlui_main | |
320 return instance | |
321 | |
322 def createTextWidget(self, *args, **kwargs): | |
323 instance = TextWidget(*args, **kwargs) | |
324 instance._xmlui_main = self._xmlui_main | |
325 return instance | |
326 | |
327 def createLabelWidget(self, *args, **kwargs): | |
328 instance = LabelWidget(*args, **kwargs) | |
329 instance._xmlui_main = self._xmlui_main | |
330 return instance | |
331 | |
332 def createJidWidget(self, *args, **kwargs): | |
333 instance = JidWidget(*args, **kwargs) | |
334 instance._xmlui_main = self._xmlui_main | |
335 return instance | |
336 | |
337 def createDividerWidget(self, *args, **kwargs): | |
338 instance = DividerWidget(*args, **kwargs) | |
339 instance._xmlui_main = self._xmlui_main | |
340 return instance | |
341 | |
342 def createStringWidget(self, *args, **kwargs): | |
343 instance = StringWidget(*args, **kwargs) | |
344 instance._xmlui_main = self._xmlui_main | |
345 return instance | |
346 | |
347 def createPasswordWidget(self, *args, **kwargs): | |
348 instance = PasswordWidget(*args, **kwargs) | |
349 instance._xmlui_main = self._xmlui_main | |
350 return instance | |
351 | |
352 def createTextBoxWidget(self, *args, **kwargs): | |
353 instance = TextBoxWidget(*args, **kwargs) | |
354 instance._xmlui_main = self._xmlui_main | |
355 return instance | |
356 | |
357 def createBoolWidget(self, *args, **kwargs): | |
358 instance = BoolWidget(*args, **kwargs) | |
359 instance._xmlui_main = self._xmlui_main | |
360 return instance | |
361 | |
362 def createButtonWidget(self, *args, **kwargs): | |
363 instance = ButtonWidget(*args, **kwargs) | |
364 instance._xmlui_main = self._xmlui_main | |
365 return instance | |
366 | |
367 def createListWidget(self, *args, **kwargs): | |
368 instance = ListWidget(*args, **kwargs) | |
369 instance._xmlui_main = self._xmlui_main | |
370 return instance | |
371 | |
372 | 364 |
373 # def __getattr__(self, attr): | 365 # def __getattr__(self, attr): |
374 # if attr.startswith("create"): | 366 # if attr.startswith("create"): |
375 # cls = globals()[attr[6:]] | 367 # cls = globals()[attr[6:]] |
376 # cls._xmlui_main = self._xmlui_main | 368 # cls._xmlui_main = self._xmlui_main |
377 # return cls | 369 # return cls |
378 | 370 |
379 | 371 |
380 class XMLUI(xmlui.XMLUI, VerticalPanel): | 372 class WidgetFactory(GenericFactory): |
373 | |
374 def _genericCreate(self, cls, *args, **kwargs): | |
375 instance = GenericFactory._genericCreate(self, cls, *args, **kwargs) | |
376 instance._xmlui_main = self._xmlui_main | |
377 return instance | |
378 | |
379 class LiberviaXMLUIBase(object): | |
380 | |
381 def _xmluiLaunchAction(self, action_id, data): | |
382 self.host.launchAction(action_id, data) | |
383 | |
384 | |
385 class XMLUIPanel(LiberviaXMLUIBase, xmlui.XMLUIPanel, VerticalPanel): | |
381 widget_factory = WidgetFactory() | 386 widget_factory = WidgetFactory() |
382 | 387 |
383 def __init__(self, host, xml_data, title=None, flags=None): | 388 def __init__(self, host, parsed_xml, title=None, flags=None): |
384 self.widget_factory._xmlui_main = self | 389 self.widget_factory._xmlui_main = self |
385 self.dom = nativedom.NativeDOM() | |
386 dom_parse = lambda xml_data: self.dom.parseString(xml_data) | |
387 VerticalPanel.__init__(self) | 390 VerticalPanel.__init__(self) |
388 self.setSize('100%', '100%') | 391 self.setSize('100%', '100%') |
389 xmlui.XMLUI.__init__(self, host, xml_data, title, flags, dom_parse) | 392 xmlui.XMLUIPanel.__init__(self, host, parsed_xml, title, flags) |
390 | 393 |
391 def setCloseCb(self, close_cb): | 394 def setCloseCb(self, close_cb): |
392 self.close_cb = close_cb | 395 self.close_cb = close_cb |
393 | 396 |
394 def _xmluiClose(self): | 397 def _xmluiClose(self): |
395 if self.close_cb: | 398 if self.close_cb: |
396 self.close_cb() | 399 self.close_cb() |
397 else: | 400 else: |
398 log.warning("no close method defined") | 401 log.warning("no close method defined") |
399 | 402 |
400 def _xmluiLaunchAction(self, action_id, data): | |
401 self.host.launchAction(action_id, data) | |
402 | |
403 def _xmluiSetParam(self, name, value, category): | 403 def _xmluiSetParam(self, name, value, category): |
404 self.host.bridge.call('setParam', None, name, value, category) | 404 self.host.bridge.call('setParam', None, name, value, category) |
405 | 405 |
406 def constructUI(self, xml_data): | 406 def constructUI(self, parsed_dom): |
407 super(XMLUI, self).constructUI(xml_data) | 407 super(XMLUIPanel, self).constructUI(parsed_dom) |
408 self.add(self.main_cont) | 408 self.add(self.main_cont) |
409 self.setCellHeight(self.main_cont, '100%') | 409 self.setCellHeight(self.main_cont, '100%') |
410 if self.type == 'form': | 410 if self.type == 'form': |
411 hpanel = HorizontalPanel() | 411 hpanel = HorizontalPanel() |
412 hpanel.setStyleName('marginAuto') | 412 hpanel.setStyleName('marginAuto') |
418 assert(isinstance(self.children[0][0], TabPanel)) | 418 assert(isinstance(self.children[0][0], TabPanel)) |
419 hpanel = HorizontalPanel() | 419 hpanel = HorizontalPanel() |
420 hpanel.add(Button('Save', self.onSaveParams)) | 420 hpanel.add(Button('Save', self.onSaveParams)) |
421 hpanel.add(Button('Cancel', lambda ignore: self._xmluiClose())) | 421 hpanel.add(Button('Cancel', lambda ignore: self._xmluiClose())) |
422 self.add(hpanel) | 422 self.add(hpanel) |
423 | |
424 def show(self): | |
425 options = ['NO_CLOSE'] if self.type == C.XMLUI_FORM else [] | |
426 _dialog = dialog.GenericDialog(self.title, self, options=options) | |
427 self.setCloseCb(_dialog.close) | |
428 _dialog.show() | |
429 | |
430 | |
431 class XMLUIDialog(LiberviaXMLUIBase, xmlui.XMLUIDialog): | |
432 dialog_factory = GenericFactory() | |
433 | |
434 def __init__(self, host, parsed_dom, title = None, flags = None): | |
435 xmlui.XMLUIDialog.__init__(self, host, parsed_dom, title, flags) | |
436 | |
437 xmlui.registerClass(xmlui.CLASS_PANEL, XMLUIPanel) | |
438 xmlui.registerClass(xmlui.CLASS_DIALOG, XMLUIDialog) | |
439 | |
440 def create(*args, **kwargs): | |
441 dom = nativedom.NativeDOM() | |
442 kwargs['dom_parse'] = lambda xml_data: dom.parseString(xml_data) | |
443 return xmlui.create(*args, **kwargs) |