Mercurial > libervia-backend
view frontends/src/wix/xmlui.py @ 796:46aa5ada61bf
core, frontends: XMLUI refactoring:
- now there is a base XMLUI class. Frontends inherits from this class, and add their specific widgets/containers/behaviour
- wix: param.py has been removed, as the same behaviour has been reimplemented through XMLUI
- removed "misc" argument in XMLUI.__init__
- severals things are broken (gateway, directory search), following patches will fix them
- core: elements names in xml_tools.dataForm2XMLUI now use a construction with category_name/param_name to avoid name conflicts (could happen with 2 parameters of the same name in differents categories).
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 04 Feb 2014 18:02:35 +0100 |
parents | bfabeedbf32e |
children | 9007bb133009 |
line wrap: on
line source
#!/usr/bin/python # -*- coding: utf-8 -*- # wix: a SAT frontend # Copyright (C) 2009, 2010, 2011, 2012, 2013 Jérôme Poisson (goffi@goffi.org) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from sat.core.i18n import _ import wx from logging import debug, info, warning, error from sat.tools.jid import JID from sat_frontends.tools import xmlui class EventWidget(object): """ Used to manage change event of widgets """ def _xmluiOnChange(self, callback): """ Call callback with widget as only argument """ def change_cb(event): callback(self) self.Bind(self._xmlui_change_event, change_cb) class WixWidget(object): _xmlui_proportion = 0 class ValueWidget(WixWidget): def _xmluiGetValue(self): return self.GetValue() class EmptyWidget(WixWidget, xmlui.EmptyWidget, wx.Window): def __init__(self, parent): wx.Window.__init__(self, parent, -1) class TextWidget(WixWidget, xmlui.TextWidget, wx.StaticText): def __init__(self, parent, value): wx.StaticText.__init__(self, parent, -1, value) class StringWidget(EventWidget, ValueWidget, xmlui.StringWidget, wx.TextCtrl): _xmlui_change_event = wx.EVT_TEXT def __init__(self, parent, value): wx.TextCtrl.__init__(self, parent, -1, value) self._xmlui_proportion = 1 class PasswordWidget(EventWidget, ValueWidget, xmlui.PasswordWidget, wx.TextCtrl): _xmlui_change_event = wx.EVT_TEXT def __init__(self, parent, value): wx.TextCtrl.__init__(self, parent, -1, value, style=wx.TE_PASSWORD) self._xmlui_proportion = 1 class TextBoxWidget(EventWidget, ValueWidget, xmlui.TextBoxWidget, wx.TextCtrl): _xmlui_change_event = wx.EVT_TEXT def __init__(self, parent, value): wx.TextCtrl.__init__(self, parent, -1, value, style=wx.TE_MULTILINE) self._xmlui_proportion = 1 class BoolWidget(EventWidget, ValueWidget, xmlui.BoolWidget, wx.CheckBox): _xmlui_change_event = wx.EVT_CHECKBOX def __init__(self, parent, state): wx.CheckBox.__init__(self, parent, -1, "", style=wx.CHK_2STATE) self.SetValue(state) self._xmlui_proportion = 1 def _xmluiGetValue(self): return "true" if self.GetValue() else "false" class ButtonWidget(EventWidget, WixWidget, xmlui.ButtonWidget, wx.Button): _xmlui_change_event = wx.EVT_BUTTON def __init__(self, parent, value, click_callback): wx.Button.__init__(self, parent, -1, value) self._xmlui_click_callback = click_callback parent.Bind(wx.EVT_BUTTON, lambda evt: click_callback(evt.GetEventObject()), self) def _xmluiOnClick(self, event): self._xmlui_click_callback(event.GetEventObject()) event.Skip() class ListWidget(EventWidget, WixWidget, xmlui.ListWidget, wx.ListBox): _xmlui_change_event = wx.EVT_LISTBOX def __init__(self, parent, options, flags): styles = wx.LB_MULTIPLE if not 'single' in flags else wx.LB_SINGLE wx.ListBox.__init__(self, parent, -1, choices=[option[1] for option in options], style=styles) self._xmlui_attr_map = {label: value for value, label in options} self._xmlui_proportion = 1 def _xmluiSelectValue(self, value): try: label = [label for label, _value in self._xmlui_attr_map.items() if _value == value][0] except IndexError: warning(_("Can't find value [%s] to select" % value)) return for idx in xrange(self.GetCount()): self.SetSelection(idx, self.GetString(idx) == label) def _xmluiGetSelectedValues(self): ret = [] labels = [self.GetString(idx) for idx in self.GetSelections()] for label in labels: ret.append(self._xmlui_attr_map[label]) return ret class AdvancedListWidget(ListWidget): #TODO def __init__(self, parent, options, flags): super(ListWidget, self).__init__(parent, options, flags) class WixContainer(object): _xmlui_proportion = 1 def _xmluiAppend(self, widget): self.sizer.Add(widget, self._xmlui_proportion, flag=wx.EXPAND) class PairsContainer(WixContainer, xmlui.PairsContainer, wx.Panel): def __init__(self, parent, weight_0='1', weight_1='1'): wx.Panel.__init__(self, parent) self.sizer = wx.FlexGridSizer(cols=2) self.sizer.AddGrowableCol(1) #The growable column need most of time to be the right one in pairs self.SetSizer(self.sizer) class TabsContainer(WixContainer, xmlui.TabsContainer, wx.Notebook): def __init__(self, parent): wx.Notebook.__init__(self, parent, -1, style=wx.NB_LEFT if self._xmlui_main.type=='param' else 0) def _xmluiAddTab(self, label): tab_panel = wx.Panel(self, -1) tab_panel.sizer = wx.BoxSizer(wx.VERTICAL) tab_panel.SetSizer(tab_panel.sizer) self.AddPage(tab_panel, label) VerticalContainer._xmluiAdapt(tab_panel) return tab_panel class VerticalContainer(WixContainer, xmlui.VerticalContainer, wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(self.sizer) class WidgetFactory(object): def __getattr__(self, attr): if attr.startswith("create"): cls = globals()[attr[6:]] cls._xmlui_main = self._xmlui_main return cls class XMLUI(xmlui.XMLUI, wx.Frame, WixContainer): """Create an user interface from a SàT XML""" widget_factory = WidgetFactory() def __init__(self, host, xml_data, title=None, flags = None,): self.widget_factory._xmlui_main = self xmlui.XMLUI.__init__(self, host, xml_data, title, flags) def constructUI(self, xml_data): style = wx.DEFAULT_FRAME_STYLE & ~wx.CLOSE_BOX if 'NO_CANCEL' in self.flags else wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, None, style=style) self.sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(self.sizer) def postTreat(ret_wid): if self.title: self.SetTitle(self.title) if self.type == 'form': dialogButtons = wx.StdDialogButtonSizer() submitButton = wx.Button(ret_wid,wx.ID_OK, label=_("Submit")) dialogButtons.AddButton(submitButton) ret_wid.Bind(wx.EVT_BUTTON, self.onFormSubmitted, submitButton) if not 'NO_CANCEL' in self.flags: cancelButton = wx.Button(ret_wid,wx.ID_CANCEL) dialogButtons.AddButton(cancelButton) ret_wid.Bind(wx.EVT_BUTTON, self.onFormCancelled, cancelButton) dialogButtons.Realize() ret_wid.sizer.Add(dialogButtons, flag=wx.ALIGN_CENTER_HORIZONTAL) self._xmluiAppend(ret_wid) self.sizer.Fit(self) self.Show() return ret_wid super(XMLUI, self).constructUI(xml_data, postTreat) if not 'NO_CANCEL' in self.flags: self.Bind(wx.EVT_CLOSE, self.onClose, self) self.MakeModal() def _xmluiClose(self): self.MakeModal(False) self.Destroy() ###events def onParamChange(self, ctrl): super(XMLUI, self).onParamChange(ctrl) ### FIXME # Some hacks for better presentation, should be generic # FIXME ### if (ctrl._param_category, ctrl._param_name) == ('Connection', 'JabberID'): domain = JID(ctrl._xmluiGetValue()).domain for widget in (ctl['control'] for ctl in self.ctrl_list.values()): if (widget._param_category, widget._param_name) == ('Connection', 'Server'): widget.SetValue(domain) break def onFormSubmitted(self, event): """Called when submit button is clicked""" button = event.GetEventObject() super(XMLUI, self).onFormSubmitted(button) def onClose(self, event): """Close event: we have to send the form.""" debug(_("close")) if self.type == 'param': self.onSaveParams() event.Skip()