--- a/svghmi/gen_index_xhtml.xslt Sat Apr 04 17:47:16 2020 +0200
+++ b/svghmi/gen_index_xhtml.xslt Sat Apr 04 22:32:54 2020 +0200
@@ -687,15 +687,16 @@
<xsl:template name="defs_by_labels">
<xsl:param name="labels" select="''"/>
<xsl:param name="mandatory" select="'yes'"/>
+ <xsl:param name="subelements" select="/.."/> <xsl:param name="hmi_element"/>
<xsl:variable name="widget_type" select="@type"/>
<xsl:for-each select="str:split($labels)">
<xsl:variable name="name" select="."/>
- <xsl:variable name="elt_id" select="$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]/@id"/>
+ <xsl:variable name="elt" select="$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]"/> - <xsl:when test="not($elt_id)">
+ <xsl:when test="not($elt/@id)"> <xsl:if test="$mandatory='yes'">
- <xsl:message terminate="no">
+ <xsl:message terminate="yes"> <xsl:value-of select="$widget_type"/>
<xsl:text> widget must have a </xsl:text>
<xsl:value-of select="$name"/>
@@ -707,9 +708,53 @@
<xsl:value-of select="$name"/>
<xsl:text>_elt: id("</xsl:text>
- <xsl:value-of select="$elt_id"/>
+ <xsl:value-of select="$elt/@id"/> + <xsl:if test="$subelements"> + <xsl:value-of select="$name"/> + <xsl:for-each select="str:split($subelements)"> + <xsl:variable name="subname" select="."/> + <xsl:variable name="subelt" select="$elt/*[@inkscape:label=$subname][1]"/> + <xsl:when test="not($subelt/@id)"> + <xsl:if test="$mandatory='yes'"> + <xsl:message terminate="yes"> + <xsl:value-of select="$widget_type"/> + <xsl:text> widget must have a </xsl:text> + <xsl:value-of select="$name"/> + <xsl:value-of select="$subname"/> + <xsl:text> element</xsl:text> + <xsl:text> /* missing </xsl:text> + <xsl:value-of select="$name"/> + <xsl:value-of select="$subname"/> + <xsl:text> "</xsl:text> + <xsl:value-of select="$subname"/> + <xsl:text>": id("</xsl:text> + <xsl:value-of select="$subelt/@id"/> + <xsl:text>")</xsl:text> + <xsl:if test="position()!=last()"> @@ -1197,10 +1242,18 @@
<xsl:call-template name="defs_by_labels">
<xsl:with-param name="hmi_element" select="$hmi_element"/>
<xsl:with-param name="labels">
- <xsl:text>Sign CapsLock Shift Space</xsl:text>
+ <xsl:text>Sign Space NumDot</xsl:text> <xsl:with-param name="mandatory" select="'no'"/>
+ <xsl:call-template name="defs_by_labels"> + <xsl:with-param name="hmi_element" select="$hmi_element"/> + <xsl:with-param name="labels"> + <xsl:text>CapsLock Shift</xsl:text> + <xsl:with-param name="mandatory" select="'no'"/> + <xsl:with-param name="subelements" select="'active inactive'"/> <xsl:text> init: function() {
<xsl:for-each select="$hmi_element/*[@inkscape:label = 'Keys']/*">
@@ -1213,7 +1266,7 @@
- <xsl:for-each select="str:split('Esc Enter BackSpace Sign Space CapsLock Shift')">
+ <xsl:for-each select="str:split('Esc Enter BackSpace Sign Space NumDot CapsLock Shift')"> <xsl:text> if(this.</xsl:text>
<xsl:value-of select="."/>
@@ -1241,16 +1294,12 @@
<xsl:text> this.update();
- <xsl:text> console.log(symbols);
<xsl:text> on_Esc_click: function() {
<xsl:text> end_modal.call(this);
- <xsl:text> console.log("Esc");
<xsl:text> on_Enter_click: function() {
@@ -1261,8 +1310,6 @@
<xsl:text> callback_obj.edit_callback(this.editstr);
- <xsl:text> console.log("Enter");
<xsl:text> on_BackSpace_click: function() {
@@ -1271,8 +1318,6 @@
<xsl:text> this.update();
- <xsl:text> console.log("BackSpace");
<xsl:text> on_Sign_click: function() {
@@ -1285,7 +1330,19 @@
<xsl:text> this.editstr = "-" + this.editstr;
- <xsl:text> console.log("Sign");
+ <xsl:text> this.update(); + <xsl:text> on_NumDot_click: function() { + <xsl:text> if(this.editstr.indexOf(".") == "-1"){ + <xsl:text> this.editstr += "."; + <xsl:text> this.update(); @@ -1293,27 +1350,33 @@
<xsl:text> this.editstr += " ";
- <xsl:text> console.log("Space");
+ <xsl:text> this.update(); + <xsl:text> _caps: undefined, <xsl:text> on_CapsLock_click: function() {
<xsl:text> this.caps = !this.caps;
- <xsl:text> console.log("CapsLock");
+ <xsl:text> this.update(); + <xsl:text> _shift: undefined, <xsl:text> on_Shift_click: function() {
- <xsl:text> this.shift = true;
- <xsl:text> console.log("Shift");
+ <xsl:text> this.shift = !this.shift; + <xsl:text> this.caps = false; + <xsl:text> this.update(); @@ -1326,6 +1389,8 @@
+ <xsl:text> _editstr: undefined, <xsl:text> result_callback_obj: undefined,
<xsl:text> start_edit: function(info, valuetype, callback_obj, initial) {
@@ -1348,9 +1413,29 @@
<xsl:text> update: function() {
- <xsl:text> /* TODO Swith shift and capslock active/inactive elements */
- <xsl:text> this.Value_elt.textContent = this.editstr;
+ <xsl:text> if(this.editstr != this._editstr){ + <xsl:text> this._editstr = this.editstr; + <xsl:text> this.Value_elt.textContent = this.editstr; + <xsl:text> if(this.shift != this._shift){ + <xsl:text> this._shift = this.shift; + <xsl:text> (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); + <xsl:text> if(this.caps != this._caps){ + <xsl:text> this._caps = this.caps; + <xsl:text> (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); @@ -2605,5 +2690,39 @@
+ <xsl:text>function widget_active_activable(eltsub) { + <xsl:text> if(eltsub.inactive_style === undefined) + <xsl:text> eltsub.inactive_style = eltsub.inactive.getAttribute("style"); + <xsl:text> eltsub.inactive.setAttribute("style", "display:none"); + <xsl:text> if(eltsub.active_style !== undefined) + <xsl:text> eltsub.active.setAttribute("style", eltsub.active_style); + <xsl:text> console.log("active", eltsub); + <xsl:text>function widget_inactive_activable(eltsub) { + <xsl:text> if(eltsub.active_style === undefined) + <xsl:text> eltsub.active_style = eltsub.active.getAttribute("style"); + <xsl:text> eltsub.active.setAttribute("style", "display:none"); + <xsl:text> if(eltsub.inactive_style !== undefined) + <xsl:text> eltsub.inactive.setAttribute("style", eltsub.inactive_style); + <xsl:text> console.log("inactive", eltsub); --- a/svghmi/widget_keypad.ysl2 Sat Apr 04 17:47:16 2020 +0200
+++ b/svghmi/widget_keypad.ysl2 Sat Apr 04 22:32:54 2020 +0200
@@ -3,12 +3,13 @@
template "widget[@type='Keypad']", mode="widget_defs" {
labels("Esc Enter BackSpace Keys Info Value");
- optional_labels("Sign CapsLock Shift Space");
+ optional_labels("Sign Space NumDot"); + activable_labels("CapsLock Shift"); foreach "$hmi_element/*[@inkscape:label = 'Keys']/*" {
| id("«@id»").setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_key_click('«func:escape_quotes(@inkscape:label)»')");
- foreach "str:split('Esc Enter BackSpace Sign Space CapsLock Shift')" {
+ foreach "str:split('Esc Enter BackSpace Sign Space NumDot CapsLock Shift')" { | this.«.»_elt.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_«.»_click()");
@@ -19,51 +20,53 @@
| this.editstr += syms[this.shift?syms.length-1:0];
- | console.log(symbols);
| on_Esc_click: function() {
| on_Enter_click: function() {
| callback_obj = this.result_callback_obj;
| callback_obj.edit_callback(this.editstr);
- | console.log("Enter");
| on_BackSpace_click: function() {
| this.editstr = this.editstr.slice(0,this.editstr.length-1);
- | console.log("BackSpace");
| on_Sign_click: function() {
| if(this.editstr[0] == "-")
| this.editstr = this.editstr.slice(1,this.editstr.length);
| this.editstr = "-" + this.editstr;
+ | on_NumDot_click: function() { + | if(this.editstr.indexOf(".") == "-1"){ | on_Space_click: function() {
- | console.log("Space");
| on_CapsLock_click: function() {
| this.caps = !this.caps;
- | console.log("CapsLock");
| on_Shift_click: function() {
+ | this.shift = !this.shift; - | console.log("Shift");
const "g", "$geometry[@Id = $hmi_element/@id]";
| coordinates: [«$g/@x», «$g/@y»],
| result_callback_obj: undefined,
| start_edit: function(info, valuetype, callback_obj, initial) {
@@ -75,7 +78,17 @@
- | /* TODO Swith shift and capslock active/inactive elements */
- | this.Value_elt.textContent = this.editstr;
+ | if(this.editstr != this._editstr){ + | this._editstr = this.editstr; + | this.Value_elt.textContent = this.editstr; + | if(this.shift != this._shift){ + | this._shift = this.shift; + | (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); + | if(this.caps != this._caps){ + | this._caps = this.caps; + | (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); --- a/svghmi/widgets_common.ysl2 Sat Apr 04 17:47:16 2020 +0200
+++ b/svghmi/widgets_common.ysl2 Sat Apr 04 22:32:54 2020 +0200
@@ -11,6 +11,13 @@
+in xsl decl activable_labels(*ptr, name="defs_by_labels") alias call-template { + with "hmi_element", "$hmi_element"; + with "labels"{text *ptr}; + with "mandatory","'no'"; + with "subelements","'active inactive'"; template "svg:*", mode="hmi_elements" {
const "widget", "func:widget(@id)";
@@ -51,21 +58,40 @@
function "defs_by_labels" {
param "mandatory","'yes'";
+ param "subelements","/.."; const "widget_type","@type";
foreach "str:split($labels)" {
- const "elt_id","$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]/@id";
+ const "elt","$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]";
- // TODO FIXME error > «$widget_type» widget must have a «$name» element
- warning > «$widget_type» widget must have a «$name» element
+ error > «$widget_type» widget must have a «$name» element // otherwise produce nothing
- | «$name»_elt: id("«$elt_id»"),
+ | «$name»_elt: id("«$elt/@id»"), + foreach "str:split($subelements)" { + const "subelt","$elt/*[@inkscape:label=$subname][1]"; + when "not($subelt/@id)" { + if "$mandatory='yes'" { + error > «$widget_type» widget must have a «$name»/«$subname» element + | /* missing «$name»/«$subname» element */ + | "«$subname»": id("«$subelt/@id»")`if "position()!=last()" > ,` --- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg Sat Apr 04 17:47:16 2020 +0200
+++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg Sat Apr 04 22:32:54 2020 +0200
@@ -1529,22 +1529,6 @@
transform="scale(1.0007154,0.99928514)">0</text>
- style="stroke-width:0.13585199"
- inkscape:connector-curvature="0"
- d="m 697,197 h 20 c 2,0 3,1 3,2 v 19 c 0,1 -1,2 -3,2 h -20 c -1,0 -3,-1 -3,-2 v -19 c 0,-1 2,-2 3,-2 z"
- style="opacity:1;vector-effect:none;fill:#d3d2d2;fill-opacity:1;stroke:none;stroke-width:0.10074359;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- style="font-weight:normal;font-size:6.96602964px;font-family:Arial;fill:#2b2828;stroke-width:0.10514989"
- transform="scale(1.0007154,0.99928514)">.</text>
@@ -1608,6 +1592,23 @@
style="stroke-width:0.30784383px">information</tspan></text>
+ transform="matrix(1.6700128,0,0,1.6700128,-826.83854,-145.60856)" + style="fill-rule:evenodd;stroke-width:0.13585199" + inkscape:label="NumDot"> + inkscape:connector-curvature="0" + d="m 697,197 h 20 c 2,0 3,1 3,2 v 19 c 0,1 -1,2 -3,2 h -20 c -1,0 -3,-1 -3,-2 v -19 c 0,-1 2,-2 3,-2 z" + style="opacity:1;vector-effect:none;fill:#d3d2d2;fill-opacity:1;stroke:none;stroke-width:0.10074359;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + style="font-weight:normal;font-size:6.96602964px;font-family:Arial;fill:#2b2828;stroke-width:0.10514989" + transform="scale(1.0007154,0.99928514)">.</text> transform="matrix(3.3549332,0,0,3.14525,-181.87457,1556.0198)"