--- a/svghmi/gen_dnd_widget_svg.ysl2 Wed Jun 16 18:27:27 2021 +0200
+++ b/svghmi/gen_dnd_widget_svg.ysl2 Fri Jun 18 10:49:10 2021 +0200
@@ -18,28 +18,30 @@
extension-element-prefixes="ns func exsl regexp str dyn"
exclude-result-prefixes="ns func exsl regexp str dyn" {
const "hmi_elements", "//svg:*[starts-with(@inkscape:label, 'HMI:')]";
- const "subhmitree", "ns:GetSubHMITree()";
+ const "widgetparams", "ns:GetWidgetParams()"; const "indexed_hmitree", "/.."; // compatibility with parse_labels.ysl2
include parse_labels.ysl2
const "_parsed_widgets" apply "$hmi_elements", mode="parselabel";
const "parsed_widgets","exsl:node-set($_parsed_widgets)";
- const "selected_node_type","local-name($subhmitree)";
- const "svg_widget", "$parsed_widgets/widget[1]"; // TODO take all widgets
+ const "svg_widget", "$parsed_widgets/widget[1]"; const "svg_widget_type", "$svg_widget/@type";
const "svg_widget_path", "$svg_widget/@path";
const "svg_widget_count", "count($parsed_widgets/widget)";
// Templates to change label paths(s)
- template "@* | node()", mode="replace_path" {
- xsl:copy apply "@* | node()", mode="replace_path";
+ template "@* | node()", mode="replace_params" { + xsl:copy apply "@* | node()", mode="replace_params"; - template "path/@value", mode="replace_path" {
- attrib "value" > «$hmi_path»
+ template "arg", mode="replace_params"; + template "path", mode="replace_params"; + template "widget", mode="replace_params" { // all attribs are usually copied
@@ -52,7 +54,7 @@
// in case this node widget's main element inject label
if "@id = $svg_widget/@id" {
- const "substituted_widget" apply "$svg_widget", mode="replace_path";
+ const "substituted_widget" apply "$svg_widget", mode="replace_params"; const "substituted_widget_ns", "exsl:node-set($substituted_widget)";
const "new_label" apply "$substituted_widget_ns", mode="genlabel";
attrib "inkscape:label" > «$new_label»
@@ -61,8 +63,6 @@
apply "@* | node()", mode="inline_svg";
- const "NODES_TYPES","str:split('HMI_ROOT HMI_NODE')";
- const "HMI_NODES_COMPAT","str:split('Page Jump Foreach')";
comment > Widget dropped in Inkscape from Beremiz
@@ -71,14 +71,9 @@
error > No widget detected on selected SVG
when "$svg_widget_count > 1"
error > Multiple widget DnD not yet supported
- when """$selected_node_type = $NODES_TYPES and \
- not($svg_widget_type = $HMI_NODES_COMPAT)"""
- error > Widget incompatible with selected HMI tree node
- msg value "$selected_node_type";
msg value "$svg_widget_type";
--- a/svghmi/ui.py Wed Jun 16 18:27:27 2021 +0200
+++ b/svghmi/ui.py Fri Jun 18 10:49:10 2021 +0200
@@ -11,6 +11,7 @@
+from threading import Thread, Lock from functools import reduce
from itertools import izip
@@ -204,6 +205,9 @@
self.SetSizer(self.main_sizer)
self.main_sizer.Fit(self)
+ return self.edit.GetValue() def setValidity(self, validity):
bmp = self.valid_bmp if validity else self.invalid_bmp
@@ -238,6 +242,7 @@
if accepts and txt else None)
+ self.ParentObj.RegenSVGLater() class PathEditor(ParamEditor):
@@ -261,6 +266,7 @@
# TODO : find corresponding hmitre node and type to update validity
# Lazy way : hide validity
+ self.ParentObj.RegenSVGLater() def KeepDoubleNewLines(txt):
@@ -347,6 +353,14 @@
+ self.RegenSVGThread = None + self.RegenSVGLock = Lock() + self.RegenSVGTimer = wx.Timer(self, -1) + self.RegenSVGParams = None + self.Bind(wx.EVT_TIMER, @@ -378,6 +392,8 @@
self.paths_editors[dndindex:]):
editor.SetPath(hmitree_node)
conf = self.Config.Read(_conf_key)
@@ -481,12 +497,7 @@
self.AnalyseWidgetAndUpdateUI(fname)
- self.staticmsg.SetLabel(self.msg)
+ self.staticmsg.SetLabel(self.msg) self.msg = _("Widget library must be writable")
@@ -496,9 +507,6 @@
def OnHMITreeNodeSelection(self, hmitree_nodes):
self.hmitree_nodes = hmitree_nodes
- # [0] if len(hmitree_nodes) else None
- # self.ValidateWidget()
def OnLeftDown(self, evt):
if self.tempf is not None:
@@ -509,17 +517,49 @@
dropSource.DoDragDrop(wx.Drag_AllowMove)
- def GiveDetails(self, _context, msgs):
- self.msg += msg.text + "\n"
+ def RegenSVGLater(self, when=1): + self.RegenSVGTimer.Start(milliseconds=when*1000, oneShot=True) + self.RegenSVGLater(when=0) + def RegenSVG(self, event): + args = [arged.GetValue() for arged in self.args_editors] + paths = [pathed.GetValue() for pathed in self.paths_editors] + if self.RegenSVGLock.acquire(True): + self.RegenSVGParams = (args, paths) + if self.RegenSVGThread is None: + self.RegenSVGThread = \ + Thread(target=self.RegenSVGProc, + name="RegenSVGThread").start() + self.RegenSVGLock.release() + def RegenSVGProc(self): + self.RegenSVGLock.acquire(True) + newparams = self.RegenSVGParams + self.RegenSVGParams = None + while newparams is not None: + self.RegenSVGLock.release() + res = self.GenDnDSVG(newparams) + self.RegenSVGLock.acquire(True) + newparams = self.RegenSVGParams + self.RegenSVGParams = None + self.RegenSVGThread = None + self.RegenSVGLock.release() + wx.CallAfter(self.DoneRegenSVG) - def PassMessage(self, _context, msgs):
- self.msg += msg.text + "\n"
- def GetSubHMITree(self, _context):
- return [self.hmitree_node.etree()]
+ def DoneRegenSVG(self): + self.staticmsg.SetLabel(self.msg) def AnalyseWidgetAndUpdateUI(self, fname):
@@ -594,10 +634,25 @@
self.main_panel.SetupScrolling(scroll_x=False)
+ def PassMessage(self, _context, msgs): + self.msg += msg.text + "\n" - def ValidateWidget(self):
+ def GetWidgetParams(self, _context): + args,paths = self.GenDnDSVGParams + root = etree.Element("params") + etree.SubElement(root, "arg", value=arg) + etree.SubElement(root, "path", value=path) + def GenDnDSVG(self, newparams): + self.GenDnDSVGParams = newparams if self.tempf is not None:
os.unlink(self.tempf.name)
@@ -605,18 +660,15 @@
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"),
- [("GetSubHMITree", self.GetSubHMITree),
- ("PassMessage", self.GiveDetails)])
+ [("GetWidgetParams", self.GetWidgetParams), + ("PassMessage", self.PassMessage)]) svgdom = etree.parse(self.selected_SVG)
- result = transform.transform(
- svgdom, hmi_path = self.hmitree_node.hmi_path())
+ result = transform.transform(svgdom) for entry in transform.get_error_log():
self.msg += "XSLT: " + entry.message + "\n"