diff tools/xml_tools.py @ 103:6be927a465ed

XMLUI refactoring, step 1
author Goffi <goffi@goffi.org>
date Wed, 23 Jun 2010 00:23:26 +0800
parents 94011f553cd0
children 5458ac1380cc
line wrap: on
line diff
--- a/tools/xml_tools.py	Tue Jun 22 13:58:53 2010 +0800
+++ b/tools/xml_tools.py	Wed Jun 23 00:23:26 2010 +0800
@@ -30,19 +30,13 @@
 def dataForm2xml(form):
     """Take a data form (xep-0004, Wokkel's implementation) and convert it to a SàT xml"""
     
-    impl = minidom.getDOMImplementation()
-
-    doc = impl.createDocument(None, "form", None)
-    top_element = doc.documentElement
+    form_panel = XMLUI("form", "vertical")
     
-    #result_xml = ["<form>", "</form>"]
     if form.instructions:
-        elem = doc.createElement('elem')
-        elem.setAttribute('name','instructions')
-        elem.setAttribute('type','text')
-        text = doc.createTextNode('\n'.join(form.instructions))
-        elem.appendChild(text)
-        top_element.appendChild(elem)
+        form_panel.addText('\n'.join(form.instructions), 'instructions')
+    
+    form_panel.changeLayout("pairs")
+    
     for field in form.fieldList:
         if field.fieldType == 'fixed':
             __field_type = 'text'
@@ -56,21 +50,13 @@
             error (u"FIXME FIXME FIXME: Type [%s] is not managed yet by SàT" % field.fieldType)
             __field_type = "string"
         
-        elem = doc.createElement('elem')
-        if field.var:
-            elem.setAttribute('name', field.var)
-        elem.setAttribute('type', __field_type)
-        elem.setAttribute('label', field.label or "")
-        if field.value:
-            elem.setAttribute('value', field.value)
-        top_element.appendChild(elem)
-        for option in field.options:
-            opt = doc.createElement('option')
-            opt.setAttribute('value', option.value)
-            elem.appendChild(opt)
-    result = doc.toxml()
-    doc.unlink()
-    return result
+        if field.label:
+            form_panel.addLabel(field.label)
+        else:
+            form_panel.addEmpty()
+
+        elem = form_panel.addElement(__field_type, field.var, None, field.value, [option.value for option in field.options]) 
+    return form_panel.toXml()
 
 def tupleList2dataForm(values):
     """convert a list of tuples (name,value) to a wokkel submit data form"""
@@ -80,6 +66,130 @@
         form.addField(field)
 
     return form
-            
+
+class XMLUI:
+    """This class is used to create a user interface (form/window/parameters/etc) using SàT XML"""
+
+    def __init__(self, panel_type, layout="vertical"):
+        """Init SàT XML Panel
+        @param panel_type: one of
+            - window (new window)
+            - form (formulaire, depend of the frontend, usually a panel with cancel/submit buttons)
+            - param (parameters, presentatio depend of the frontend)
+        @param layout: disposition of elements, one of:
+            - VERTICAL: elements are disposed up to bottom
+            - HORIZONTAL: elements are disposed left to right
+            - PAIRS: elements come on two aligned columns
+              (usually one for a label, the next for the element)
+        """
+        if not panel_type in ['window', 'form', 'param']:
+            error(_("Unknown panel type [%s]") % panel_type)
+            assert(False)
+        self.type = panel_type
+        impl = minidom.getDOMImplementation()
+
+        self.doc = impl.createDocument(None, "sat_xmlui", None)
+        top_element = self.doc.documentElement
+        top_element.setAttribute("type", panel_type)
+        self.currentLayout = self.__createLayout(layout, top_element)
+
+    def __del__(self):
+        self.doc.unlink() 
     
+    def __createLayout(self, layout, parent=None):
+        """Create a layout element
+        @param type: layout type (cf init doc)
+        @parent: parent element or None
+        """
+        if not layout in ['vertical', 'horizontal', 'pairs']:
+            error (_("Unknown layout type [%s]") % layout)
+            assert (False)
+        layout_elt = self.doc.createElement('layout')
+        layout_elt.setAttribute('type',layout)
+        if parent != None:
+            parent.appendChild(layout_elt)
+        return layout_elt
 
+    def __createElem(self, type, name=None, parent = None):
+        """Create an element
+        @param type: one of
+            - empty: empty element (usefull to skip something in a layout, e.g. skip first element in a PAIRS layout)
+            - text: text to be displayed in an multi-line area, e.g. instructions
+        @param name: name of the element or None
+        @param parent: parent element or None
+        """
+        elem = self.doc.createElement('elem')
+        if name:
+            elem.setAttribute('name', name)
+        elem.setAttribute('type', type)
+        if parent != None:
+            parent.appendChild(elem)
+        return elem
+
+    def changeLayout(self, layout):
+        """Change the current layout"""
+        self.currentLayout = self.__createLayout(layout, self.doc.documentElement)
+
+
+    def addEmpty(self, name=None):
+        """Add a multi-lines text"""
+        elem = self.__createElem('empty', name, self.currentLayout)
+    
+    def addText(self, text, name=None):
+        """Add a multi-lines text"""
+        elem = self.__createElem('text', name, self.currentLayout)
+        text = self.doc.createTextNode(text)
+        elem.appendChild(text)
+
+    def addLabel(self, text, name=None):
+        """Add a single line text, mainly useful as label before element"""
+        elem = self.__createElem('label', name, self.currentLayout)
+        elem.setAttribute('value', text)
+
+    def addString(self, name=None, value=None):
+        """Add a string box"""
+        elem = self.__createElem('string', name, self.currentLayout)
+        if value:
+            elem.setAttribute('value', value)
+    
+    def addPassword(self, name=None, value=None):
+        """Add a password box"""
+        elem = self.__createElem('password', name, self.currentLayout)
+        if value:
+            elem.setAttribute('value', value)
+
+    def addList(self, options, name=None, value=None):
+        """Add a list of choices"""
+        assert (options)
+        elem = self.__createElem('list', name, self.currentLayout)
+        self.addOptions(options, elem) 
+        if value:
+            elem.setAttribute('value', value)
+    
+    def addElement(self, type, name = None, content = None, value = None, options = None):
+        """Convenience method to add element, the params correspond to the ones in addSomething methods"""
+        if type == 'empty':
+            self.addEmpty(name)
+        elif type == 'text':
+            assert(content)
+            self.addText(content, name)
+        elif type == 'label':
+            assert(value)
+        elif type == 'string':
+            self.addString(name, value)
+        elif type == 'password':
+            self.addPassword(name, value)
+        elif type == 'list':
+            self.addList(options, name, value)
+
+    def addOptions(self, options, parent):
+        """Add options to a multi-values element (e.g. list)
+        @param parent: multi-values element"""
+        for option in options:
+            opt = self.doc.createElement('option')
+            opt.setAttribute('value', option)
+            parent.appendChild(opt)
+
+    def toXml(self):
+        """return the XML representation of the panel""" 
+        return self.doc.toxml()