Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-08-11 19:11:30 +0400
committerCampbell Barton <ideasman42@gmail.com>2010-08-11 19:11:30 +0400
commitab8ccaa7098f6fee887f2a249fddada7864cd6c5 (patch)
tree672613464ff57264e76ca71cafa910cd26c8730a /release/scripts/modules/bpyml.py
parent2a72eb8c287bedd35908ace4f19b06e806592845 (diff)
python declarative UI
- remove XML testing feature - add 2 modules: bpyml - generic, bpyml_ui - blender spesific. nothing uses these now. ==bpyml_ui module== defines BPyML_BaseUI and its draw() function which uses the bpyml member of the class instance self.draw_data & self.draw_header_data. This way declarative ui is opt-in and easy to use by using BPyML_BaseUI as a mix-in class. ==bpyml module== This module translates a python like XML representation into XML or simple python blender/ui function calls. sometag(arg=10) [ another(), another(key="value") ] # converts into ... <sometag arg="10"> <another/> <another key="value" /> </sometag>
Diffstat (limited to 'release/scripts/modules/bpyml.py')
-rw-r--r--release/scripts/modules/bpyml.py204
1 files changed, 204 insertions, 0 deletions
diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py
new file mode 100644
index 00000000000..f30a4b8d9ac
--- /dev/null
+++ b/release/scripts/modules/bpyml.py
@@ -0,0 +1,204 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+"""
+This module translates a python like XML representation into XML
+or simple python blender/ui function calls.
+
+ sometag(arg=10) [
+ another()
+ another(key="value")
+ ]
+
+# converts into ...
+
+ <sometag arg="10">
+ <another/>
+ <another key="value" />
+ </sometag>
+
+"""
+
+TAG, ARGS, CHILDREN = range(3)
+class ReturnStore(tuple):
+ def __getitem__(self, key):
+
+ # single item get's
+ if type(key) is ReturnStore:
+ key = (key, )
+
+ if type(key) is tuple:
+ children = self[CHILDREN]
+ if children:
+ raise Exception("Only a single __getitem__ is allowed on the ReturnStore")
+ else:
+ children[:] = key
+ return self
+ else:
+ return tuple.__getitem__(self, key)
+
+
+class FunctionStore(object):
+ def __call__(self, **kwargs):
+ return ReturnStore((self.__class__.__name__, kwargs, []))
+
+
+def tag_vars(tags, module=__name__):
+ return {tag: type(tag, (FunctionStore, ), {"__module__": module})() for tag in tags}
+
+
+def tag_module(mod_name, tags):
+ import sys
+ from types import ModuleType
+ mod = ModuleType(mod_name)
+ sys.modules[mod_name] = mod
+ dict_values = tag_vars(tags, mod_name)
+ mod.__dict__.update(dict_values)
+ return mod
+
+
+def toxml(py_data, indent=" "):
+
+ if len(py_data) != 1 or type(py_data) != list:
+ raise Exception("Expected a list with one member")
+
+ def _to_xml(py_item, xml_node=None):
+ if xml_node is None:
+ xml_node = newdoc.createElement(py_item[TAG])
+
+ for key, value in py_item[ARGS].items():
+ xml_node.setAttribute(key, str(value))
+
+ for py_item_child in py_item[CHILDREN]:
+ xml_node.appendChild(_to_xml(py_item_child))
+
+ return xml_node
+
+ def _to_xml_iter(xml_parent, data_ls):
+ for py_item in data_ls:
+ xml_node = newdoc.createElement(py_item[TAG])
+
+
+ # ok if its empty
+ _to_xml_iter(xml_node, py_item[CHILDREN])
+
+ import xml.dom.minidom
+ impl = xml.dom.minidom.getDOMImplementation()
+ newdoc = impl.createDocument(None, py_data[0][TAG], None)
+
+ _to_xml(py_data[0], newdoc.documentElement)
+
+ return newdoc.documentElement.toprettyxml(indent=" ")
+
+
+def fromxml(data):
+ def _fromxml_kwargs(xml_node):
+ kwargs = {}
+ for key, value in xml_node.attributes.items():
+ kwargs[key] = value
+ return kwargs
+
+
+ def _fromxml(xml_node):
+ py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), [])
+ #_fromxml_iter(py_item, xml_node.childNodes)
+ for xml_node_child in xml_node.childNodes:
+ if xml_node_child.nodeType not in (xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE):
+ py_item[CHILDREN].append(_fromxml(xml_node_child))
+ return py_item
+
+ import xml.dom.minidom
+ xml_doc = xml.dom.minidom.parseString(data)
+ return [_fromxml(xml_doc.documentElement)]
+
+
+def topretty_py(py_data, indent=" "):
+
+ if len(py_data) != 1:
+ raise Exception("Expected a list with one member")
+
+ lines = []
+
+ def _to_kwargs(kwargs):
+ return ", ".join([("%s=%s" % (key, repr(value))) for key, value in sorted(kwargs.items())])
+
+ def _topretty(py_item, indent_ctx, last):
+ if py_item[CHILDREN]:
+ lines.append("%s%s(%s) [" % (indent_ctx, py_item[TAG], _to_kwargs(py_item[ARGS])))
+ py_item_last = py_item[CHILDREN][-1]
+ for py_item_child in py_item[CHILDREN]:
+ _topretty(py_item_child, indent_ctx + indent, (py_item_child is py_item_last))
+ lines.append("%s]%s" % (indent_ctx, ("" if last else ",")))
+ else:
+ lines.append("%s%s(%s)%s" % (indent_ctx, py_item[TAG], _to_kwargs(py_item[ARGS]), ("" if last else ",")))
+
+ _topretty(py_data[0], "", True)
+
+ return "\n".join(lines)
+
+if __name__ == "__main__":
+ # testing code.
+
+ tag_module("bpyml_test", ("ui", "prop", "row", "column", "active", "separator", "split"))
+ from bpyml_test import *
+
+ draw = [
+ ui() [
+ split() [
+ column() [
+ prop(data='context.scene.render', property='stamp_time', text='Time'),
+ prop(data='context.scene.render', property='stamp_date', text='Date'),
+ prop(data='context.scene.render', property='stamp_render_time', text='RenderTime'),
+ prop(data='context.scene.render', property='stamp_frame', text='Frame'),
+ prop(data='context.scene.render', property='stamp_scene', text='Scene'),
+ prop(data='context.scene.render', property='stamp_camera', text='Camera'),
+ prop(data='context.scene.render', property='stamp_filename', text='Filename'),
+ prop(data='context.scene.render', property='stamp_marker', text='Marker'),
+ prop(data='context.scene.render', property='stamp_sequencer_strip', text='Seq. Strip')
+ ],
+ column() [
+ active(expr='context.scene.render.render_stamp'),
+ prop(data='context.scene.render', property='stamp_foreground', slider=True),
+ prop(data='context.scene.render', property='stamp_background', slider=True),
+ separator(),
+ prop(data='context.scene.render', property='stamp_font_size', text='Font Size')
+ ]
+ ],
+ split(percentage=0.2) [
+ prop(data='context.scene.render', property='stamp_note', text='Note'),
+ row() [
+ active(expr='context.scene.render.stamp_note'),
+ prop(data='context.scene.render', property='stamp_note_text', text='')
+ ]
+ ]
+ ]
+ ]
+
+ xml_data = toxml(draw)
+ print(xml_data) # xml version
+
+ py_data = fromxml(xml_data)
+ print(py_data) # converted back to py
+
+ xml_data = toxml(py_data)
+ print(xml_data) # again back to xml
+
+ py_data = fromxml(xml_data) # pretty python version
+ print(topretty_py(py_data))