view browser_side/xmlui.py @ 335:e8c26e24a6c7

browser side: refactored XMLUI to use the new sat_frontends.tools.xmlui.XMLUI class, first draft
author Goffi <goffi@goffi.org>
date Tue, 04 Feb 2014 16:49:20 +0100
parents d07b54fdc60a
children ea1be522ba88
line wrap: on
line source

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Libervia: a Salut à Toi frontend
Copyright (C) 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 pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.CellPanel import CellPanel
from pyjamas.ui.TabPanel import TabPanel
from pyjamas.ui.Grid import Grid
from pyjamas.ui.Label import Label
from pyjamas.ui.TextBoxBase import TextBoxBase
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.PasswordTextBox import PasswordTextBox
from pyjamas.ui.TextArea import TextArea
from pyjamas.ui.CheckBox import CheckBox
from pyjamas.ui.ListBox import ListBox
from pyjamas.ui.Button import Button
from pyjamas.ui.HTML import HTML
from nativedom import NativeDOM
from sat_frontends.tools import xmlui


class EmptyWidget(xmlui.EmptyWidget, Label):

    def __init__(self, parent):
        Label.__init__(self, '')


class TextWidget(xmlui.TextWidget, Label):

    def __init__(self, parent, value):
        Label.__init__(self, value)


class LabelWidget(xmlui.LabelWidget, TextWidget):

    def __init__(self, parent, value):
        TextWidget.__init__(self, parent, value+": ")


class JidWidget(xmlui.JidWidget, TextWidget):
    pass


class DividerWidget(xmlui.DividerWidget, HTML):

    def __init__(self, parent, style='line'):
        HTML.__init__(self, "<hr/>") # gof: TODO:


class StringWidget(xmlui.StringWidget, TextBox):

    def __init__(self, parent, value):
        TextBox.__init__(self)
        self.setText(value)

    def _xmluiGetValue(self):
        return self.getText()

    def _xmluiOnChange(self, callback):
        self.addhangeListener(callback)


class PasswordWidget(xmlui.PasswordWidget, PasswordTextBox):

    def __init__(self, parent, value):
        TextBox.__init__(self)
        self.setText(value)

    def _xmluiGetValue(self):
        return self.getText()

    def _xmluiOnChange(self, callback):
        self.addChangeListener(callback)


class TextBoxWidget(xmlui.TextBoxWidget, TextArea):

    def __init__(self, parent, value):
        TextArea.__init__(self)
        self.setText(value)

    def _xmluiGetValue(self):
        return self.getText()

    def _xmluiOnChange(self, callback):
        self.addChangeListener(callback)


class BoolWidget(xmlui.BoolWidget, CheckBox):

    def __init__(self, parent, state):
        CheckBox.__init__(self)
        self.setChecked(state)

    def _xmluiGetValue(self):
        return "true" if self.isChecked() else "false"

    def _xmluiOnChange(self, callback):
        self.addClickListener(callback)


class ButtonWidget(xmlui.ButtonWidget, Button):

    def __init__(self, parent, value, click_callback):
        Button.__init__(self)

    def _xmluiOnClick(self, event):
        self.addClickListener(callback)


class ListWidget(xmlui.ListWidget, ListBox):

    def __init__(self, parent, options, flags):
        ListBox.__init__(self)
        self.setMultipleSelect('single' not in flags)
        for option in options:
            self.addItem(option[0])
        self._xmlui_attr_map = {label: value for value, label in options}

    def _xmluiSelectValue(self, value):
        try:
            label = [label for label, _value in self._xmlui_attr_map.items() if _value == value][0]
        except IndexError:
            print(_("WARNING: Can't find value [%s] to select" % value))
            return
        self.selectItem(label)

    def _xmluiGetSelectedValues(self):
        ret = []
        for label in self.getSelectedItemText():
            ret.append(self._xmlui_attr_map[label])
        return ret

    def _xmluiOnChange(self, callback):
        self.addChangeListener(callback)


class LiberviaContainer(object):

    def _xmluiAppend(self, widget):
        self.append(widget)


class AdvancedListContainer(xmlui.AdvancedListContainer, Grid):

    def __init__(self, parent, columns, selectable='no'):
        Grid.__init_(self, 0, columns)
        self.columns = columns
        self.row = 0
        self.col = 0
        self._xmlui_rows_idx = []
        self._xmlui_selectable = selectable != 'no'
        self._xmlui_selected_row = None
        self.addTableListener(self)

    def onCellClicked(self, grid, row, col):
        if not self._xmlui_selectable:
            return
        self._xmlui_selected_row = row
        try:
            self._xmlui_select_cb(self)
        except AttributeError:
            print "WARNING: no select callback set"


    def _xmluiAppend(self, widget):
        self.setWidget(self.row, self.col, widget)
        self.col += 1

    def _xmluiAddRow(self, idx):
        self._xmlui_rows_idx.insert(self.row, idx)
        self.row += 1
        self.col = 0
        self.resizeRows(self.row)

    def _xmluiGetSelectedWidgets(self):
        return [self.getWidget(self._xmlui_selected_row, col) for col in range(self.columns)]

    def _xmluiGetSelectedIndex(self):
        try:
            return self._xmlui_rows_idx[self._xmlui_selected_row]
        except TypeError:
            return None

    def _xmluiOnSelect(self, callback):
        self._xmlui_select_cb = callback


class PairsContainer(xmlui.PairsContainer, Grid):

    def __init__(self, parent):
        Grid.__init__(self, 0, 0)
        self.row = 0
        self.col = 0

    def _xmluiAppend(self, widget):
        if self.col == 0:
            self.resize(self.row+1, 2)
        self.setWidget(self.row, self.col, widget)
        self.col += 1
        if self.col == 2:
            self.row +=1
            self.col = 0



class TabsContainer(LiberviaContainer, xmlui.TabsContainer, TabPanel):

    def __init__(self, parent):
        TabPanel.__init__(self)
        self.setStyleName('liberviaTabPanel')

    def _xmluiAddTab(self, label):
        tab_panel = VerticalContainer(self)
        self.add(tab_panel, label)
        if len(self.getChildren()) == 1:
            self.selectTab(0)
        return tab_panel


class VerticalContainer(LiberviaContainer, xmlui.VerticalContainer, VerticalPanel):
    __bases__ = (LiberviaContainer, xmlui.VerticalContainer, VerticalPanel)

    def __init__(self, parent):
        VerticalPanel.__init__(self)


class WidgetFactory(object):
    # XXX: __getattr__ doesn't work here for an unknown reason

    def createVerticalContainer(self, *args, **kwargs):
        instance = VerticalContainer(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createPairsContainer(self, *args, **kwargs):
        instance = PairsContainer(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createTabsContainer(self, *args, **kwargs):
        instance = TabsContainer(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createEmptyWidget(self, *args, **kwargs):
        instance = EmptyWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createTextWidget(self, *args, **kwargs):
        instance = TextWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createLabelWidget(self, *args, **kwargs):
        instance = LabelWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createJidWidget(self, *args, **kwargs):
        instance = JidWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createDividerWidget(self, *args, **kwargs):
        instance = DividerWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createStringWidget(self, *args, **kwargs):
        instance = StringWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createPasswordWidget(self, *args, **kwargs):
        instance = PasswordWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createTextBoxWidget(self, *args, **kwargs):
        instance = TextBoxWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createBoolWidget(self, *args, **kwargs):
        instance = BoolWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createButtonWidget(self, *args, **kwargs):
        instance = ButtonWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance

    def createListWidget(self, *args, **kwargs):
        instance = ListWidget(*args, **kwargs)
        instance._xmlui_main = self._xmlui_main
        return instance


    # def __getattr__(self, attr):
    #     if attr.startswith("create"):
    #         cls = globals()[attr[6:]]
    #         cls._xmlui_main = self._xmlui_main
    #         return cls


class XMLUI(xmlui.XMLUI, VerticalPanel):
    widget_factory = WidgetFactory()

    def __init__(self, host, xml_data, title = None, flags = None):
        self.widget_factory._xmlui_main = self
        self.dom = NativeDOM()
        dom_parse = lambda xml_data: self.dom.parseString(xml_data)
        self._dest = "window"
        VerticalPanel.__init__(self)
        self.setSize('100%', '100%')
        xmlui.XMLUI.__init__(self, host, xml_data, title, flags, dom_parse)

    def setCloseCb(self, close_cb):
        self.close_cb = close_cb

    def _xmluiClose(self):
        if self.close_cb:
            self.close_cb()
        else:
            print "WARNING: no close method defined"

    def constructUI(self, xml_data):
        super(XMLUI, self).constructUI(xml_data)
        self.add(self.main_cont)
        self.setCellHeight(self.main_cont, '100%')
        if self.type == 'form':
            hpanel = HorizontalPanel()
            hpanel.add(Button('Submit',self.onFormSubmitted))
            if not 'NO_CANCEL' in self.flags:
                hpanel.add(Button('Cancel',self.onFormCancelled))
            self.add(hpanel)
        elif self.type == 'param':
            assert(isinstance(self.children[0][0],TabPanel))
            hpanel = HorizontalPanel()
            hpanel.add(Button('Cancel', lambda ignore: self._xmluiClose()))
            hpanel.add(Button('Save', self.onSaveParams))
            self.add(hpanel)

    ##EVENTS##

    def onSaveParams(self, ignore=None):
        def postTreat(name, value, category):
            self.host.bridge.call('setParam', None, name, value, category)
        xmlui.XMLUI.onSaveParams(self, ignore, postTreat)