svghmi/ui.py
branchsvghmi
changeset 3221 3d307ad803ea
parent 3213 afef7011f475
child 3222 6adeeb16ac3e
--- a/svghmi/ui.py	Thu Apr 01 16:00:58 2021 +0200
+++ b/svghmi/ui.py	Fri Apr 02 21:16:18 2021 +0200
@@ -10,14 +10,22 @@
 import os
 import hashlib
 import weakref
+from tempfile import NamedTemporaryFile
 
 import wx
 
+from lxml import etree
+from lxml.etree import XSLTApplyError
+from XSLTransform import XSLTransform
+
+import util.paths as paths
 from IDEFrame import EncodeFileSystemPath, DecodeFileSystemPath
 from docutil import get_inkscape_path
 
 from util.ProcessLogger import ProcessLogger
 
+ScriptDirectory = paths.AbsDir(__file__)
+
 class HMITreeSelector(wx.TreeCtrl):
     def __init__(self, parent):
         global on_hmitree_update
@@ -35,13 +43,13 @@
                 display_name = ('{} (class={})'.format(c.name, c.hmiclass)) \
                                if c.hmiclass is not None else c.name
                 tc_child = self.AppendItem(current_tc_root, display_name)
-                self.SetPyData(tc_child, None) # TODO
+                self.SetPyData(tc_child, c)
 
                 self._recurseTree(c,tc_child)
             else:
                 display_name = '{} {}'.format(c.nodetype[4:], c.name)
                 tc_child = self.AppendItem(current_tc_root, display_name)
-                self.SetPyData(tc_child, None) # TODO
+                self.SetPyData(tc_child, c)
 
     def MakeTree(self, hmi_tree_root=None):
 
@@ -53,7 +61,7 @@
         root_display_name = _("Please build to see HMI Tree") \
             if hmi_tree_root is None else "HMI"
         self.root = self.AddRoot(root_display_name)
-        self.SetPyData(self.root, None)
+        self.SetPyData(self.root, hmi_tree_root)
 
         if hmi_tree_root is not None:
             self._recurseTree(hmi_tree_root, self.root)
@@ -139,8 +147,7 @@
         sizer.AddGrowableRow(1)
         self.libbutton = wx.Button(self, -1, _("Select SVG widget library"))
         self.widgetpicker = WidgetPicker(self, self.libdir)
-        self.preview = wx.Panel(self, size=(-1, _preview_height + 10))  #, style=wx.SIMPLE_BORDER)
-        #self.preview.SetBackgroundColour(wx.WHITE)
+        self.preview = wx.Panel(self, size=(-1, _preview_height + 10))
         sizer.AddWindow(self.libbutton, flag=wx.GROW)
         sizer.AddWindow(self.widgetpicker, flag=wx.GROW)
         sizer.AddWindow(self.preview, flag=wx.GROW)
@@ -155,6 +162,7 @@
         self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnWidgetSelection, self.widgetpicker)
 
         self.msg = _("Drag selected Widget from here to Inkscape")
+        self.tempf = None 
 
     def RecallLibDir(self):
         conf = self.Config.Read(_conf_key)
@@ -248,22 +256,20 @@
             thumbdir = os.path.join(dname, ".svghmithumbs") 
             thumbpath = os.path.join(thumbdir, thumbfname) 
 
-            self.msg = None
             have_thumb = os.path.exists(thumbpath)
 
-            if not have_thumb:
-                try:
+            try:
+                if not have_thumb:
                     if not os.path.exists(thumbdir):
                         os.mkdir(thumbdir)
-                except IOError:
-                    self.msg = _("Widget library must be writable")
-                else:
                     have_thumb = self.GenThumbnail(svgpath, thumbpath)
 
-            self.bmp = wx.Bitmap(thumbpath) if have_thumb else None
-
-            self.selected_SVG = svgpath if have_thumb else None
-            self.ValidateWidget()
+                self.bmp = wx.Bitmap(thumbpath) if have_thumb else None
+
+                self.selected_SVG = svgpath if have_thumb else None
+                self.ValidateWidget()
+            except IOError:
+                self.msg = _("Widget library must be writable")
 
             self.Refresh()
         event.Skip()
@@ -274,23 +280,56 @@
         self.Refresh()
 
     def OnLeftDown(self, evt):
-        if self.selected_SVG is not None:
-            # TODO replace with generated widget file
-            filename = self.selected_SVG
+        if self.tempf is not None:
+            filename = self.tempf.name
             data = wx.FileDataObject()
             data.AddFile(filename)
             dropSource = wx.DropSource(self)
             dropSource.SetData(data)
             dropSource.DoDragDrop(wx.Drag_AllowMove)
 
+    def GiveDetails(self, _context, msgs):
+        for msg in msgs:
+            self.msg += msg+"\n"
+        
     def ValidateWidget(self):
-        if self.selected_SVG is not None:
-            if self.hmitree_node is not None:
-                pass
-        # XXX TODO: 
-        #      - check SVG is valid for selected HMI tree item
-        #      - prepare for D'n'D
-
+        self.msg = ""
+
+        if self.tempf is not None:
+            os.unlink(self.tempf.name)
+            self.tempf = None
+
+        try:
+            if self.selected_SVG is None:
+                raise Exception(_("No widget selected"))
+            if self.hmitree_node is None:
+                raise Exception(_("No HMI tree node selected"))
+
+            transform = XSLTransform(
+                os.path.join(ScriptDirectory, "gen_dnd_widget_svg.xslt"),
+                [("GiveDetails", self.GiveDetails)])
+
+            svgdom = etree.parse(self.selected_SVG)
+
+            result = transform.transform(svgdom) 
+                # hmi_path=self.hmitree_node.path,
+                # hmi_type=self.hmitree_node.nodetype)
+
+            for entry in transform.get_error_log():
+                self.msg += "XSLT: " + entry.message + "\n" 
+
+            self.tempf = NamedTemporaryFile(suffix='.svg', delete=False)
+            result.write(self.tempf, encoding="utf-8")
+            self.tempf.close()
+
+        except Exception as e:
+            self.msg += str(e)
+        except XSLTApplyError as e:
+            self.msg += "Widget transform error: " + e.message
+                
+    def __del__(self):
+        if self.tempf is not None:
+            os.unlink(self.tempf.name)
 
 class SVGHMI_UI(wx.SplitterWindow):
 
@@ -302,6 +341,12 @@
         self.Staging = WidgetLibBrowser(self)
         self.SplitVertically(self.SelectionTree, self.Staging, 300)
         register_for_HMI_tree_updates(weakref.ref(self))
+        self.Bind(wx.EVT_TREE_SEL_CHANGED,
+            self.OnHMITreeNodeSelection, self.SelectionTree)
+
+    def OnHMITreeNodeSelection(self, event):
+        item_pydata = self.SelectionTree.GetPyData(event.GetItem())
+        self.Staging.OnHMITreeNodeSelection(item_pydata)
 
     def HMITreeUpdate(self, hmi_tree_root):
             self.SelectionTree.MakeTree(hmi_tree_root)