SVGHMI: Rewrote button widget. svghmi
authorEdouard Tisserant
Sat, 05 Dec 2020 16:59:27 +0100
branchsvghmi
changeset 3085 6b1b23971960
parent 3084 1ae4a871b6f9
child 3086 a70a97196654
SVGHMI: Rewrote button widget.
svghmi/gen_index_xhtml.xslt
svghmi/widget_button.ysl2
tests/svghmi/svghmi_0@svghmi/svghmi.svg
--- a/svghmi/gen_index_xhtml.xslt	Wed Dec 02 14:33:24 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt	Sat Dec 05 16:59:27 2020 +0100
@@ -1675,134 +1675,219 @@
     <xsl:text>}
 </xsl:text>
   </xsl:template>
+  <xsl:variable name="_button_fsm">
+    <fsm>
+      <state name="init">
+        <on-dispatch value="false">
+          <jump state="released"/>
+        </on-dispatch>
+        <on-dispatch value="true">
+          <jump state="pressed"/>
+        </on-dispatch>
+      </state>
+      <state name="pressing">
+        <hmi-value value="true"/>
+        <on-dispatch value="true">
+          <jump state="pressed"/>
+        </on-dispatch>
+        <on-mouse position="up">
+          <jump state="shortpress"/>
+        </on-mouse>
+      </state>
+      <state name="pressed">
+        <show eltname="active"/>
+        <on-mouse position="up">
+          <jump state="releasing"/>
+        </on-mouse>
+        <on-dispatch value="false">
+          <jump state="released"/>
+        </on-dispatch>
+      </state>
+      <state name="shortpress">
+        <on-dispatch value="true">
+          <jump state="releasing"/>
+        </on-dispatch>
+        <on-mouse position="down">
+          <jump state="pressing"/>
+        </on-mouse>
+      </state>
+      <state name="releasing">
+        <hmi-value value="false"/>
+        <on-dispatch value="false">
+          <jump state="released"/>
+        </on-dispatch>
+        <on-mouse position="down">
+          <jump state="shortrelease"/>
+        </on-mouse>
+      </state>
+      <state name="released">
+        <show eltname="inactive"/>
+        <on-mouse position="down">
+          <jump state="pressing"/>
+        </on-mouse>
+        <on-dispatch value="true">
+          <jump state="pressed"/>
+        </on-dispatch>
+      </state>
+      <state name="shortrelease">
+        <on-dispatch value="false">
+          <jump state="pressing"/>
+        </on-dispatch>
+        <on-mouse position="up">
+          <jump state="releasing"/>
+        </on-mouse>
+      </state>
+    </fsm>
+  </xsl:variable>
+  <xsl:template mode="dispatch_transition" match="fsm">
+    <xsl:text>        switch (this.state) {
+</xsl:text>
+    <xsl:apply-templates mode="dispatch_transition" select="state"/>
+    <xsl:text>        }
+</xsl:text>
+  </xsl:template>
+  <xsl:template mode="dispatch_transition" match="state">
+    <xsl:text>          case "</xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>":
+</xsl:text>
+    <xsl:apply-templates select="on-dispatch"/>
+    <xsl:text>            break;
+</xsl:text>
+  </xsl:template>
+  <xsl:template match="on-dispatch">
+    <xsl:text>            if(value ==  </xsl:text>
+    <xsl:value-of select="@value"/>
+    <xsl:text>) {
+</xsl:text>
+    <xsl:apply-templates mode="transition" select="jump"/>
+    <xsl:text>            }
+</xsl:text>
+  </xsl:template>
+  <xsl:template mode="mouse_transition" match="fsm">
+    <xsl:param name="position"/>
+    <xsl:text>        switch (this.state) {
+</xsl:text>
+    <xsl:apply-templates mode="mouse_transition" select="state">
+      <xsl:with-param name="position" select="$position"/>
+    </xsl:apply-templates>
+    <xsl:text>        }
+</xsl:text>
+  </xsl:template>
+  <xsl:template mode="mouse_transition" match="state">
+    <xsl:param name="position"/>
+    <xsl:text>          case "</xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>":
+</xsl:text>
+    <xsl:apply-templates select="on-mouse[@position = $position]"/>
+    <xsl:text>            break;
+</xsl:text>
+  </xsl:template>
+  <xsl:template match="on-mouse">
+    <xsl:apply-templates mode="transition" select="jump"/>
+  </xsl:template>
+  <xsl:template mode="transition" match="jump">
+    <xsl:text>            this.state = "</xsl:text>
+    <xsl:value-of select="@state"/>
+    <xsl:text>";
+</xsl:text>
+    <xsl:text>            this.</xsl:text>
+    <xsl:value-of select="@state"/>
+    <xsl:text>_action();
+</xsl:text>
+  </xsl:template>
+  <xsl:template mode="actions" match="fsm">
+    <xsl:apply-templates mode="actions" select="state"/>
+  </xsl:template>
+  <xsl:template mode="actions" match="state">
+    <xsl:text>    </xsl:text>
+    <xsl:value-of select="@name"/>
+    <xsl:text>_action(){
+</xsl:text>
+    <xsl:apply-templates mode="actions" select="*"/>
+    <xsl:text>    }
+</xsl:text>
+  </xsl:template>
+  <xsl:template mode="actions" match="show">
+    <xsl:text>        this.display = "</xsl:text>
+    <xsl:value-of select="@eltname"/>
+    <xsl:text>";
+</xsl:text>
+    <xsl:text>        this.request_animate();
+</xsl:text>
+  </xsl:template>
+  <xsl:template mode="actions" match="hmi-value">
+    <xsl:text>        this.apply_hmi_value(0, </xsl:text>
+    <xsl:value-of select="@value"/>
+    <xsl:text>);
+</xsl:text>
+  </xsl:template>
   <xsl:template mode="widget_class" match="widget[@type='Button']">
+    <xsl:variable name="fsm" select="exsl:node-set($_button_fsm)"/>
     <xsl:text>class ButtonWidget extends Widget{
 </xsl:text>
     <xsl:text>    frequency = 5;
 </xsl:text>
-    <xsl:text>    state_plc = 0;
-</xsl:text>
-    <xsl:text>    state_hmi = 0;
-</xsl:text>
-    <xsl:text>    plc_lock = false;
-</xsl:text>
-    <xsl:text>    active_style = undefined;
-</xsl:text>
-    <xsl:text>    inactive_style = undefined;
-</xsl:text>
-    <xsl:text>
+    <xsl:text>    display = "inactive";
+</xsl:text>
+    <xsl:text>    state = "init";
 </xsl:text>
     <xsl:text>    dispatch(value) {
 </xsl:text>
-    <xsl:text>        this.state_plc = value;
-</xsl:text>
-    <xsl:text>        if(this.plc_lock){
-</xsl:text>
-    <xsl:text>            if(this.state_plc == 1){
-</xsl:text>
-    <xsl:text>                this.apply_hmi_value(0, 0);
-</xsl:text>
-    <xsl:text>                this.plc_lock = false;
-</xsl:text>
-    <xsl:text>            }
-</xsl:text>
-    <xsl:text>        }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>        //redraw button
-</xsl:text>
-    <xsl:text>        this.state_hmi = this.state_plc;
-</xsl:text>
-    <xsl:text>        this.request_animate();
-</xsl:text>
-    <xsl:text>    }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
+    <xsl:apply-templates mode="dispatch_transition" select="$fsm"/>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>    onmouseup(evt) {
+</xsl:text>
+    <xsl:text>        svg_root.removeEventListener("pointerup", this.bound_onmouseup, true);
+</xsl:text>
+    <xsl:apply-templates mode="mouse_transition" select="$fsm">
+      <xsl:with-param name="position" select="'up'"/>
+    </xsl:apply-templates>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>    onmousedown(evt) {
+</xsl:text>
+    <xsl:text>        svg_root.addEventListener("pointerup", this.bound_onmouseup, true);
+</xsl:text>
+    <xsl:apply-templates mode="mouse_transition" select="$fsm">
+      <xsl:with-param name="position" select="'down'"/>
+    </xsl:apply-templates>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:apply-templates mode="actions" select="$fsm"/>
     <xsl:text>    animate(){
 </xsl:text>
-    <xsl:text>        if (this.active_style &amp;&amp; this.inactive_style) {
-</xsl:text>
-    <xsl:text>           // redraw button on screen refresh
-</xsl:text>
-    <xsl:text>           if (this.state_hmi) {
-</xsl:text>
-    <xsl:text>               this.active_elt.setAttribute("style", this.active_style);
-</xsl:text>
-    <xsl:text>               this.inactive_elt.setAttribute("style", "display:none");
-</xsl:text>
-    <xsl:text>           } else {
-</xsl:text>
-    <xsl:text>               this.inactive_elt.setAttribute("style", this.inactive_style);
-</xsl:text>
-    <xsl:text>               this.active_elt.setAttribute("style", "display:none");
-</xsl:text>
-    <xsl:text>           }
-</xsl:text>
-    <xsl:text>       }
-</xsl:text>
-    <xsl:text>    }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>    on_click(evt) {
-</xsl:text>
-    <xsl:text>        //set state and apply if plc is 0
-</xsl:text>
-    <xsl:text>        this.plc_lock = true;
-</xsl:text>
-    <xsl:text>        if(this.state_plc == 0){
-</xsl:text>
-    <xsl:text>            this.apply_hmi_value(0, 1);
-</xsl:text>
-    <xsl:text>        }
-</xsl:text>
-    <xsl:text>        //redraw button
-</xsl:text>
-    <xsl:text>        this.request_animate();
-</xsl:text>
-    <xsl:text>    }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>    on_press(evt) {
-</xsl:text>
-    <xsl:text>        //set graphic
-</xsl:text>
-    <xsl:text>        this.state_hmi = 1;
-</xsl:text>
-    <xsl:text>        //redraw button
-</xsl:text>
-    <xsl:text>        this.request_animate();
-</xsl:text>
-    <xsl:text>    }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>     init() {
-</xsl:text>
-    <xsl:text>        this.active_style = this.active_elt ? this.active_elt.style.cssText : undefined;
-</xsl:text>
-    <xsl:text>        this.inactive_style = this.inactive_elt ? this.inactive_elt.style.cssText : undefined;
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>        if (this.active_style &amp;&amp; this.inactive_style) {
-</xsl:text>
-    <xsl:text>            this.active_elt.setAttribute("style", "display:none");
-</xsl:text>
-    <xsl:text>            this.inactive_elt.setAttribute("style", this.inactive_style);
-</xsl:text>
-    <xsl:text>        }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>        this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)");
-</xsl:text>
-    <xsl:text>        this.element.setAttribute("onmousedown", "hmi_widgets['"+this.element_id+"'].on_press(evt)");
-</xsl:text>
-    <xsl:text>     }
+    <xsl:text>        if (this.active_elt &amp;&amp; this.inactive_elt) {
+</xsl:text>
+    <xsl:for-each select="str:split('active inactive')">
+      <xsl:text>            if(this.display == "</xsl:text>
+      <xsl:value-of select="."/>
+      <xsl:text>")
+</xsl:text>
+      <xsl:text>                this.</xsl:text>
+      <xsl:value-of select="."/>
+      <xsl:text>_elt.style.display = "";
+</xsl:text>
+      <xsl:text>            else
+</xsl:text>
+      <xsl:text>                this.</xsl:text>
+      <xsl:value-of select="."/>
+      <xsl:text>_elt.style.display = "none";
+</xsl:text>
+    </xsl:for-each>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>    init() {
+</xsl:text>
+    <xsl:text>        this.bound_onmouseup = this.onmouseup.bind(this);
+</xsl:text>
+    <xsl:text>        this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
+</xsl:text>
+    <xsl:text>    }
 </xsl:text>
     <xsl:text>}
 </xsl:text>
@@ -6645,12 +6730,16 @@
 </xsl:text>
           <xsl:text>function prepare_svg() {
 </xsl:text>
+          <xsl:text>    // prevents context menu from appearing on right click and long touch
+</xsl:text>
           <xsl:text>    document.body.addEventListener('contextmenu', e =&gt; {
 </xsl:text>
           <xsl:text>        e.preventDefault();
 </xsl:text>
           <xsl:text>    });
 </xsl:text>
+          <xsl:text>
+</xsl:text>
           <xsl:text>    for(let eltid in detachable_elements){
 </xsl:text>
           <xsl:text>        let [element,parent] = detachable_elements[eltid];
--- a/svghmi/widget_button.ysl2	Wed Dec 02 14:33:24 2020 +0100
+++ b/svghmi/widget_button.ysl2	Sat Dec 05 16:59:27 2020 +0100
@@ -1,73 +1,152 @@
 // widget_button.ysl2
 
+// Finite state machine
+decl fsm(name);
+decl state(name);
+decl on_mouse(position);
+decl on_dispatch(value);
+decl jump(state);
+decl show(eltname);
+decl hmi_value(value);
+
+// State machine to drive HMI_BOOL on a potentially laggy connection
+// TODO: make more robust in case other widget or PLC change value on their own
+const "_button_fsm" fsm {
+    state "init" {
+        on_dispatch "false" jump "released";
+        on_dispatch "true" jump "pressed";
+    }
+
+    state "pressing" {
+        // show "waitactive";
+        hmi_value "true";
+        on_dispatch "true" jump "pressed";
+        on_mouse "up" jump "shortpress";
+    }
+    state "pressed" {
+        show "active";
+        on_mouse "up" jump "releasing";
+        on_dispatch "false" jump "released";
+    }
+    state "shortpress" {
+        on_dispatch "true" jump "releasing";
+        on_mouse "down" jump "pressing";
+    }
+
+    state "releasing" {
+        // show "waitinactive";
+        hmi_value "false";
+        on_dispatch "false" jump "released";
+        on_mouse "down" jump "shortrelease";
+    }
+    state "released" {
+        show "inactive";
+        on_mouse "down" jump "pressing";
+        on_dispatch "true" jump "pressed";
+    }
+    state "shortrelease" {
+        on_dispatch "false" jump "pressing";
+        on_mouse "up" jump "releasing";
+    }
+}
+
+template "fsm", mode="dispatch_transition" {
+    |         switch (this.state) {
+    apply "state", mode="dispatch_transition";
+    |         }
+}
+template "state", mode="dispatch_transition" {
+    |           case "«@name»":
+   	apply "on-dispatch";
+    |             break;
+}
+template "on-dispatch" {
+	|             if(value ==  «@value») {
+	apply "jump", mode="transition";
+	|             }
+}
+
+template "fsm", mode="mouse_transition" {
+    param "position";
+    |         switch (this.state) {
+    apply "state", mode="mouse_transition" with "position", "$position";
+    |         }
+}
+template "state", mode="mouse_transition" {
+    param "position";
+    |           case "«@name»":
+    apply "on-mouse[@position = $position]";
+    |             break;
+}
+template "on-mouse" {
+	// up or down state is already assumed because apply statement filters it
+	apply "jump", mode="transition";
+}
+
+template "jump", mode="transition" {
+    |             this.state = "«@state»";
+    |             this.«@state»_action();
+}
+
+template "fsm", mode="actions" {
+    apply "state", mode="actions";
+}
+template "state", mode="actions" {
+	|     «@name»_action(){
+    //| console.log("Entering state «@name»");
+    apply "*", mode="actions";
+	|     }
+}
+template "show", mode="actions" {
+    |         this.display = "«@eltname»";
+    |         this.request_animate();
+}
+template "hmi-value", mode="actions" {
+	|         this.apply_hmi_value(0, «@value»);
+}
+
 template "widget[@type='Button']", mode="widget_class"{
-    ||
-    class ButtonWidget extends Widget{
-        frequency = 5;
-        state_plc = 0;
-        state_hmi = 0;
-        plc_lock = false;
-        active_style = undefined;
-        inactive_style = undefined;
+    const "fsm","exsl:node-set($_button_fsm)";
+    | class ButtonWidget extends Widget{
+    |     frequency = 5;
 
-        dispatch(value) {
-            this.state_plc = value;
-            if(this.plc_lock){
-                if(this.state_plc == 1){
-                    this.apply_hmi_value(0, 0);
-                    this.plc_lock = false;
-                }
-            }
+    |     display = "inactive";
+    |     state = "init";
 
-            //redraw button
-            this.state_hmi = this.state_plc;
-            this.request_animate();
-        }
+    |     dispatch(value) {
+    // |         console.log("dispatch"+value);
+    apply "$fsm", mode="dispatch_transition";
+    |     }
 
-        animate(){
-            if (this.active_style && this.inactive_style) {
-               // redraw button on screen refresh
-               if (this.state_hmi) {
-                   this.active_elt.setAttribute("style", this.active_style);
-                   this.inactive_elt.setAttribute("style", "display:none");
-               } else {
-                   this.inactive_elt.setAttribute("style", this.inactive_style);
-                   this.active_elt.setAttribute("style", "display:none");
-               }
-           }
-        }
+    |     onmouseup(evt) {
+    |         svg_root.removeEventListener("pointerup", this.bound_onmouseup, true);
+    // |         console.log("onmouseup");
+    apply "$fsm", mode="mouse_transition" with "position", "'up'";
+    |     }
+    |     onmousedown(evt) {
+    |         svg_root.addEventListener("pointerup", this.bound_onmouseup, true);
+    // |         console.log("onmousedown");
+    apply "$fsm", mode="mouse_transition" with "position", "'down'";
+    |     }
 
-        on_click(evt) {
-            //set state and apply if plc is 0
-            this.plc_lock = true;
-            if(this.state_plc == 0){
-                this.apply_hmi_value(0, 1);
-            }
-            //redraw button
-            this.request_animate();
-        }
+    apply "$fsm", mode="actions";
 
-        on_press(evt) {
-            //set graphic
-            this.state_hmi = 1;
-            //redraw button
-            this.request_animate();
-        }
+    |     animate(){
+    |         if (this.active_elt && this.inactive_elt) {
+    foreach "str:split('active inactive')" {
+    |             if(this.display == "«.»")
+    |                 this.«.»_elt.style.display = "";
+    |             else
+    |                 this.«.»_elt.style.display = "none";
+    }
+    |         }
+    |     }
 
-         init() {
-            this.active_style = this.active_elt ? this.active_elt.style.cssText : undefined;
-            this.inactive_style = this.inactive_elt ? this.inactive_elt.style.cssText : undefined;
-
-            if (this.active_style && this.inactive_style) {
-                this.active_elt.setAttribute("style", "display:none");
-                this.inactive_elt.setAttribute("style", this.inactive_style);
-            }
-
-            this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)");
-            this.element.setAttribute("onmousedown", "hmi_widgets['"+this.element_id+"'].on_press(evt)");
-         }
-    }
-    ||
+    |     init() {
+    |         this.bound_onmouseup = this.onmouseup.bind(this);
+    |         this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
+    |     }
+    | }
 }
 
 
--- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg	Wed Dec 02 14:33:24 2020 +0100
+++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg	Sat Dec 05 16:59:27 2020 +0100
@@ -197,12 +197,12 @@
      inkscape:pageopacity="0"
      inkscape:pageshadow="2"
      inkscape:document-units="px"
-     inkscape:current-layer="hmi0"
+     inkscape:current-layer="g443"
      showgrid="false"
      units="px"
-     inkscape:zoom="0.27282898"
-     inkscape:cx="646.17826"
-     inkscape:cy="652.93449"
+     inkscape:zoom="0.77167689"
+     inkscape:cx="379.87087"
+     inkscape:cy="462.91635"
      inkscape:window-width="1848"
      inkscape:window-height="1016"
      inkscape:window-x="72"
@@ -2442,19 +2442,19 @@
   <g
      inkscape:label="HMI:Input@/SELECTION"
      id="g446"
-     transform="matrix(0.28590269,0,0,0.28590269,487.38811,348.87609)">
+     transform="matrix(0.28590269,0,0,0.28590269,1047.3881,408.87609)">
     <text
        xml:space="preserve"
-       style="font-style:normal;font-weight:normal;font-size:160px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       x="136.32812"
+       style="font-style:normal;font-weight:normal;font-size:160px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="216.32812"
        y="218.24219"
        id="text432"
        inkscape:label="value"><tspan
          sodipodi:role="line"
          id="tspan430"
-         x="136.32812"
+         x="216.32812"
          y="218.24219"
-         style="stroke-width:1px">8</tspan></text>
+         style="text-align:end;text-anchor:end;stroke-width:1px">8</tspan></text>
     <path
        transform="scale(1,-1)"
        sodipodi:type="star"
@@ -2477,7 +2477,7 @@
        inkscape:label="edit"
        onclick=""
        y="95.40741"
-       x="139.85185"
+       x="-174.94055"
        height="128"
        width="407.7037"
        id="rect438"
@@ -2519,41 +2519,46 @@
        inkscape:transform-center-x="1.0089177e-06" />
   </g>
   <g
-     transform="matrix(0.28590269,0,0,0.28590269,170.16209,215.31977)"
+     transform="matrix(0.57180538,0,0,0.57180538,417.18774,31.574523)"
      id="g443"
      inkscape:label="HMI:Button@/SELECTION"
-     style="stroke-width:2">
-    <g
-       id="g435"
-       inkscape:label="bg"
-       style="stroke-width: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:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#ff6600;stroke-width:10;stroke-linecap:butt;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="rect433"
-         width="245.44583"
-         height="95.723877"
-         x="971.96545"
-         y="594.82263"
-         ry="47.861938"
-         inkscape:label="button"
-         rx="47.861938" />
-    </g>
-    <g
-       id="g441"
+     style="stroke-width: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;vector-effect:none;fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#ff6600;stroke-width:5;stroke-linecap:butt;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="rect5492"
+       width="245.44583"
+       height="95.723877"
+       x="971.96545"
+       y="594.82263"
+       ry="23.930969"
+       inkscape:label="inactive"
+       rx="23.930969" />
+    <rect
+       rx="23.930969"
+       inkscape:label="active"
+       ry="23.930969"
+       y="594.82263"
+       x="971.96545"
+       height="95.723877"
+       width="245.44583"
+       id="rect433"
+       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:#fdfdfd;fill-opacity:1;fill-rule:nonzero;stroke:#ffd0b2;stroke-width:28.60938356;stroke-linecap:butt;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" />
+    <g
+       style="stroke-width:1"
        inkscape:label="text"
-       style="stroke-width:2">
-      <text
-         inkscape:label="setting_jmp"
-         id="text439"
+       id="g952">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;fill:#ff6600;fill-opacity:1;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         x="1090.7626"
          y="656.98151"
-         x="1090.7626"
-         style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;fill:#ff6600;fill-opacity:1;stroke:none;stroke-width:1.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-         xml:space="preserve"><tspan
-           style="text-align:center;text-anchor:middle;fill:#ff6600;stroke-width:1.99999988px"
+         id="text950"
+         inkscape:label="setting_jmp"><tspan
+           sodipodi:role="line"
+           id="tspan948"
+           x="1090.7626"
            y="656.98151"
-           x="1090.7626"
-           id="tspan437"
-           sodipodi:role="line">up</tspan></text>
+           style="text-align:center;text-anchor:middle;fill:#ff6600;stroke-width:0.99999994px">up</tspan></text>
     </g>
   </g>
   <g