Make Input widget actionable. Includes example from kraskrom@github.
authorEdouard Tisserant <edouard@beremiz.fr>
Mon, 06 Jan 2025 17:00:03 +0100 (2 months ago)
changeset 4078 5a1593e27171
parent 4077 03ed01134858
child 4079 4ce63b8647d7
Make Input widget actionable. Includes example from kraskrom@github.
exemples/svghmi_jumps/svghmi_0@svghmi/svghmi.svg
svghmi/gen_index_xhtml.xslt
svghmi/widget_input.ysl2
--- a/exemples/svghmi_jumps/svghmi_0@svghmi/svghmi.svg	Tue Dec 17 21:18:40 2024 +0100
+++ b/exemples/svghmi_jumps/svghmi_0@svghmi/svghmi.svg	Mon Jan 06 17:00:03 2025 +0100
@@ -45,12 +45,12 @@
      id="namedview4"
      showgrid="false"
      inkscape:zoom="1.04375"
-     inkscape:cx="626.58683"
-     inkscape:cy="1233.5329"
+     inkscape:cx="3312.0958"
+     inkscape:cy="360.71856"
      inkscape:window-x="0"
      inkscape:window-y="0"
      inkscape:window-maximized="1"
-     inkscape:current-layer="g845"
+     inkscape:current-layer="g2763"
      showguides="true"
      inkscape:guide-bbox="true"
      borderlayer="true"
@@ -656,6 +656,16 @@
        id="g2763"
        inkscape:label="=1">
       <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.628;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect3080"
+         width="93.054001"
+         height="80.952995"
+         x="3491.4041"
+         y="94.901985"
+         ry="20.439945"
+         rx="20.554585"
+         inkscape:label="active" />
+      <rect
          rx="21.355932"
          ry="21.355932"
          y="93.088097"
@@ -663,7 +673,8 @@
          height="84.580788"
          width="96.681831"
          id="rect114-6"
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77952766;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77953;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         inkscape:label="inactive" />
       <text
          id="text118-3"
          y="149.95857"
@@ -679,14 +690,25 @@
        id="g2758"
        inkscape:label="=2">
       <rect
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77952766;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.628;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect3077"
+         width="93.054001"
+         height="80.952995"
+         x="3591.4041"
+         y="94.901985"
+         ry="20.439945"
+         rx="20.554585"
+         inkscape:label="active" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77953;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
          id="rect2531"
          width="96.681831"
          height="84.580788"
          x="3589.5898"
          y="93.088097"
          ry="21.355932"
-         rx="21.355932" />
+         rx="21.355932"
+         inkscape:label="inactive" />
       <text
          xml:space="preserve"
          style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
@@ -702,6 +724,16 @@
        id="g2753"
        inkscape:label="=3">
       <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.628;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect3073"
+         width="93.054001"
+         height="80.952995"
+         x="3691.4041"
+         y="94.901985"
+         ry="20.439945"
+         rx="20.554585"
+         inkscape:label="active" />
+      <rect
          rx="21.355932"
          ry="21.355932"
          y="93.088097"
@@ -709,7 +741,8 @@
          height="84.580788"
          width="96.681831"
          id="rect2533"
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77952766;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77953;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         inkscape:label="inactive" />
       <text
          id="text2561"
          y="149.95857"
@@ -725,14 +758,25 @@
        id="g2748"
        inkscape:label="=4">
       <rect
-         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77952766;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.628;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
          id="rect2535"
+         width="93.054001"
+         height="80.952995"
+         x="3791.4038"
+         y="94.901985"
+         ry="20.439945"
+         rx="20.554585"
+         inkscape:label="active" />
+      <rect
+         style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77953;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+         id="rect3978"
          width="96.681831"
          height="84.580788"
          x="3789.5898"
          y="93.088097"
          ry="21.355932"
-         rx="21.355932" />
+         rx="21.355932"
+         inkscape:label="inactive" />
       <text
          xml:space="preserve"
          style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
--- a/svghmi/gen_index_xhtml.xslt	Tue Dec 17 21:18:40 2024 +0100
+++ b/svghmi/gen_index_xhtml.xslt	Mon Jan 06 17:00:03 2025 +0100
@@ -4997,12 +4997,6 @@
     <xsl:text>InputWidget</xsl:text>
     <xsl:text> extends Widget{
 </xsl:text>
-    <xsl:text>     on_op_click(opstr) {
-</xsl:text>
-    <xsl:text>         this.change_hmi_value(0, opstr);
-</xsl:text>
-    <xsl:text>     }
-</xsl:text>
     <xsl:text>     edit_callback(new_val) {
 </xsl:text>
     <xsl:text>         this.apply_hmi_value(0, new_val);
@@ -5143,6 +5137,58 @@
       <xsl:value-of select="@id"/>
       <xsl:text>"),
 </xsl:text>
+      <xsl:variable name="current_id" select="@id"/>
+      <xsl:variable name="active" select="$hmi_element/*[@id = $current_id]/*[regexp:test(@inkscape:label,'active')]"/>
+      <xsl:text>    activable_sub_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>: {
+</xsl:text>
+      <xsl:for-each select="$active">
+        <xsl:text>            </xsl:text>
+        <xsl:value-of select="@inkscape:label"/>
+        <xsl:text>_elt: id("</xsl:text>
+        <xsl:value-of select="@id"/>
+        <xsl:text>")</xsl:text>
+        <xsl:if test="position()!=last()">
+          <xsl:text>,</xsl:text>
+        </xsl:if>
+        <xsl:text>
+</xsl:text>
+      </xsl:for-each>
+      <xsl:text>    },
+</xsl:text>
+      <xsl:text>    on_op_mouse_down_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>: function(){
+</xsl:text>
+      <xsl:text>        svg_root.addEventListener("pointerup", this.bound_on_op_mouse_up_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>, true);
+</xsl:text>
+      <xsl:text>        set_activity_state(this.activable_sub_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>, true);
+</xsl:text>
+      <xsl:text>    },
+</xsl:text>
+      <xsl:text>    on_op_mouse_up_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>: function(){
+</xsl:text>
+      <xsl:text>        svg_root.removeEventListener("pointerup", this.bound_on_op_mouse_up_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>, true);
+</xsl:text>
+      <xsl:text>        set_activity_state(this.activable_sub_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>, false);
+</xsl:text>
+      <xsl:text>        this.change_hmi_value(0, "</xsl:text>
+      <xsl:value-of select="func:escape_quotes(@inkscape:label)"/>
+      <xsl:text>");
+</xsl:text>
+      <xsl:text>    },
+</xsl:text>
     </xsl:for-each>
     <xsl:text>    init: function() {
 </xsl:text>
@@ -5163,9 +5209,15 @@
     <xsl:for-each select="$action_elements">
       <xsl:text>        this.action_elt_</xsl:text>
       <xsl:value-of select="position()"/>
-      <xsl:text>.onclick = () =&gt; this.on_op_click("</xsl:text>
-      <xsl:value-of select="func:escape_quotes(@inkscape:label)"/>
-      <xsl:text>");
+      <xsl:text>.onmousedown = () =&gt; this.on_op_mouse_down_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>();
+</xsl:text>
+      <xsl:text>        this.bound_on_op_mouse_up_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text> = this.on_op_mouse_up_</xsl:text>
+      <xsl:value-of select="position()"/>
+      <xsl:text>.bind(this);
 </xsl:text>
     </xsl:for-each>
     <xsl:if test="$have_value">
--- a/svghmi/widget_input.ysl2	Tue Dec 17 21:18:40 2024 +0100
+++ b/svghmi/widget_input.ysl2	Mon Jan 06 17:00:03 2025 +0100
@@ -23,9 +23,6 @@
 
 widget_class("Input")
 ||
-     on_op_click(opstr) {
-         this.change_hmi_value(0, opstr);
-     }
      edit_callback(new_val) {
          this.apply_hmi_value(0, new_val);
      }
@@ -98,6 +95,22 @@
 
     foreach "$action_elements" {
     |     action_elt_«position()»: id("«@id»"),
+        const "current_id", "@id";
+        const "active", "$hmi_element/*[@id = $current_id]/*[regexp:test(@inkscape:label,'active')]";
+    |     activable_sub_«position()»: {
+        foreach "$active" {
+    |             «@inkscape:label»_elt: id("«@id»")`if "position()!=last()" > ,`
+        }
+    |     },
+    |     on_op_mouse_down_«position()»: function(){
+    |         svg_root.addEventListener("pointerup", this.bound_on_op_mouse_up_«position()», true);
+    |         set_activity_state(this.activable_sub_«position()», true);
+    |     },
+    |     on_op_mouse_up_«position()»: function(){
+    |         svg_root.removeEventListener("pointerup", this.bound_on_op_mouse_up_«position()», true);
+    |         set_activity_state(this.activable_sub_«position()», false);
+    |         this.change_hmi_value(0, "«func:escape_quotes(@inkscape:label)»");
+    |     },
     }
     |     init: function() {
 
@@ -110,7 +123,8 @@
     }
 
     foreach "$action_elements" {
-    |         this.action_elt_«position()».onclick = () => this.on_op_click("«func:escape_quotes(@inkscape:label)»");
+    |         this.action_elt_«position()».onmousedown = () => this.on_op_mouse_down_«position()»();
+    |         this.bound_on_op_mouse_up_«position()» = this.on_op_mouse_up_«position()».bind(this);
     }
 
     if "$have_value" {