SVGHMI: UI: added prefill of arguments according to values in widget instance in library. Also added library's widget instance description to description field.
--- a/svghmi/parse_labels.ysl2 Thu Jun 10 14:05:44 2021 +0200
+++ b/svghmi/parse_labels.ysl2 Wed Jun 16 18:27:05 2021 +0200
@@ -19,6 +19,7 @@
{
const "label","@inkscape:label";
const "id","@id";
+
const "description", "substring-after($label,'HMI:')";
const "_args", "substring-before($description,'@')";
@@ -86,6 +87,7 @@
}
}
}
+ if "svg:desc" desc value "svg:desc/text()";
}
}
--- a/svghmi/ui.py Thu Jun 10 14:05:44 2021 +0200
+++ b/svghmi/ui.py Wed Jun 16 18:27:05 2021 +0200
@@ -12,6 +12,7 @@
import weakref
import re
from functools import reduce
+from itertools import izip
from operator import or_
from tempfile import NamedTemporaryFile
@@ -213,15 +214,19 @@
models = { typename: re.compile(regex) for typename, regex in [
("string", r".*"),
- ("int", r"^-?[1-9][0-9]*$"),
- ("real", r"^-?[1-9][0-9]*(\.[0-9]+)?$")]}
+ ("int", r"^-?([1-9][0-9]|0)*$"),
+ ("real", r"^-?([1-9][0-9]|0)*(\.[0-9]+)?$")]}
class ArgEditor(ParamEditor):
- def __init__(self, parent, argdesc):
+ def __init__(self, parent, argdesc, prefillargdesc):
ParamEditor.__init__(self, parent, argdesc)
self.ParentObj = parent
self.argdesc = argdesc
self.Bind(wx.EVT_TEXT, self.OnArgChanged, self.edit)
+ prefill = "" if prefillargdesc is None else prefillargdesc.get("value")
+ self.edit.SetValue(prefill)
+ # TODO add a button to add more ArgEditror instance
+ # when ordinality is multiple
def OnArgChanged(self, event):
txt = self.edit.GetValue()
@@ -258,6 +263,10 @@
self.setValidity(None)
event.Skip()
+def KeepDoubleNewLines(txt):
+ return "\n\n".join(map(
+ lambda s:re.sub(r'\s+',' ',s),
+ txt.split("\n\n")))
_conf_key = "SVGHMIWidgetLib"
_preview_height = 200
@@ -311,11 +320,11 @@
self.signature_sizer = wx.BoxSizer(wx.VERTICAL)
self.args_box = wx.StaticBox(self.main_panel, -1,
_("Widget's arguments"),
- style = wx.ALIGN_RIGHT)
+ style = wx.ALIGN_CENTRE_HORIZONTAL)
self.args_sizer = wx.StaticBoxSizer(self.args_box, wx.VERTICAL)
self.paths_box = wx.StaticBox(self.main_panel, -1,
_("Widget's variables"),
- style = wx.ALIGN_RIGHT)
+ style = wx.ALIGN_CENTRE_HORIZONTAL)
self.paths_sizer = wx.StaticBoxSizer(self.paths_box, wx.VERTICAL)
self.signature_sizer.Add(self.args_sizer, flag=wx.GROW)
self.signature_sizer.AddSpacer(5)
@@ -352,8 +361,8 @@
editor.Destroy()
self.paths_editors = []
- def AddArgToSignature(self, arg):
- new_editor = ArgEditor(self, arg)
+ def AddArgToSignature(self, arg, prefillarg):
+ new_editor = ArgEditor(self, arg, prefillarg)
self.args_editors.append(new_editor)
self.args_sizer.Add(new_editor, flag=wx.GROW)
@@ -531,41 +540,56 @@
except Exception as e:
self.msg += str(e)
+ return
except XSLTApplyError as e:
self.msg += "Widget " + fname + " analysis error: " + e.message
- else:
+ return
- self.msg += "Widget " + fname + ": OK"
-
- print(etree.tostring(signature, pretty_print=True))
- widgets = signature.getroot()
- for defs in widgets.iter("defs"):
-
- # Keep double newlines (to mark paragraphs)
- self.desc.SetValue(defs.find("type").text + ":\n" + "\n\n".join(map(
- lambda s:s.replace("\n"," ").replace(" ", " "),
- defs.find("longdesc").text.split("\n\n"))))
- args = [arg for arg in defs.iter("arg")]
- self.args_box.Show(len(args)!=0)
- for arg in args:
- self.AddArgToSignature(arg)
- print(arg.get("name"))
- print(arg.get("accepts"))
- paths = [path for path in defs.iter("path")]
- self.paths_box.Show(len(paths)!=0)
- for path in paths:
- self.AddPathToSignature(path)
- print(path.get("name"))
- print(path.get("accepts"))
-
- for widget in widgets:
- widget_type = widget.get("type")
- print(widget_type)
- for path in widget.iterchildren("path"):
- path_value = path.get("value")
- path_accepts = map(
- str.strip, path.get("accepts", '')[1:-1].split(','))
- print(path, path_value, path_accepts)
+ self.msg += "Widget " + fname + ": OK"
+
+ print(etree.tostring(signature, pretty_print=True))
+ widgets = signature.getroot()
+ widget = widgets.find("widget")
+ defs = widget.find("defs")
+ # Keep double newlines (to mark paragraphs)
+ widget_desc = widget.find("desc")
+ self.desc.SetValue(
+ fname + ":\n" + (
+ _("No description given") if widget_desc is None else
+ KeepDoubleNewLines(widget_desc.text)
+ ) + "\n\n" +
+ defs.find("type").text + ":\n" +
+ KeepDoubleNewLines(defs.find("longdesc").text))
+ prefillargs = widget.findall("arg")
+ args = defs.findall("arg")
+ # extend args description in prefilled args in longer
+ # (case of variable list of args)
+ if len(prefillargs) < len(args):
+ prefillargs += [None]*(len(args)-len(prefillargs))
+ if args and len(prefillargs) > len(args):
+ # TODO: check ordinality of last arg
+ # TODO: check that only last arg has multiple ordinality
+ args += [args[-1]]*(len(prefillargs)-len(args))
+ self.args_box.Show(len(args)!=0)
+ for arg, prefillarg in izip(args,prefillargs):
+ self.AddArgToSignature(arg, prefillarg)
+ print(arg.get("name"))
+ print(arg.get("accepts"))
+ paths = defs.findall("path")
+ self.paths_box.Show(len(paths)!=0)
+ for path in paths:
+ self.AddPathToSignature(path)
+ print(path.get("name"))
+ print(path.get("accepts"))
+
+ for widget in widgets:
+ widget_type = widget.get("type")
+ print(widget_type)
+ for path in widget.iterchildren("path"):
+ path_value = path.get("value")
+ path_accepts = map(
+ str.strip, path.get("accepts", '')[1:-1].split(','))
+ print(path, path_value, path_accepts)
self.main_panel.SetupScrolling(scroll_x=False)
--- a/svghmi/widgetlib/voltmeter.svg Thu Jun 10 14:05:44 2021 +0200
+++ b/svghmi/widgetlib/voltmeter.svg Wed Jun 16 18:27:05 2021 +0200
@@ -93,9 +93,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="3.312923"
- inkscape:cx="554.2857"
- inkscape:cy="554.2857"
+ inkscape:zoom="1.1712952"
+ inkscape:cx="601.92253"
+ inkscape:cy="607.41638"
inkscape:document-units="mm"
inkscape:current-layer="svg2354"
showgrid="false"
@@ -438,9 +438,11 @@
id="path4304" />
</g>
<g
- inkscape:label="HMI:Meter@/PUMP0/SLOTH,0,666"
+ inkscape:label="HMI:Meter:0:500@/PUMP0/SLOTH,0,666"
transform="matrix(0.57180538,0,0,0.57180538,88.118425,163.79208)"
id="g19348">
+ <desc
+ id="desc132">Old Style Russian Voltmeter, from openclipart https://openclipart.org/detail/205486/voltmeter-and-ammeter</desc>
<path
inkscape:label="range"
sodipodi:open="true"