SVGHMI: add a SetPoint to Slider Widget, visible only when operating the slider. svghmi
authorEdouard Tisserant
Mon, 10 Aug 2020 15:25:57 +0200
branchsvghmi
changeset 3021 49799de67540
parent 3020 895bbeced72d
child 3024 0a9f6f29b7dd
SVGHMI: add a SetPoint to Slider Widget, visible only when operating the slider.
svghmi/gen_index_xhtml.xslt
svghmi/widget_slider.ysl2
tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg
--- a/svghmi/gen_index_xhtml.xslt	Mon Aug 10 14:00:20 2020 +0200
+++ b/svghmi/gen_index_xhtml.xslt	Mon Aug 10 15:25:57 2020 +0200
@@ -4119,8 +4119,6 @@
 </xsl:text>
     <xsl:text>    enTimer = false;
 </xsl:text>
-    <xsl:text>    svg_dist = 0
-</xsl:text>
     <xsl:text>
 </xsl:text>
     <xsl:text>    dispatch(value) {
@@ -4131,13 +4129,19 @@
 </xsl:text>
     <xsl:text>
 </xsl:text>
-    <xsl:text>        this.handle_position(value);
-</xsl:text>
-    <xsl:text>    }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>    handle_position(value){
+    <xsl:text>        this.update_DOM(value, this.handle_elt);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>    last_drag = false;
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>    update_DOM(value, elt){
 </xsl:text>
     <xsl:text>        let [min,max,start,totallength] = this.range;
 </xsl:text>
@@ -4145,7 +4149,29 @@
 </xsl:text>
     <xsl:text>        let tip = this.range_elt.getPointAtLength(length);
 </xsl:text>
-    <xsl:text>        this.handle_elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
+    <xsl:text>        elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        if(this.setpoint_elt != undefined){
+</xsl:text>
+    <xsl:text>            if(this.last_drag!= this.drag){
+</xsl:text>
+    <xsl:text>                if(this.drag){
+</xsl:text>
+    <xsl:text>                    this.setpoint_elt.setAttribute("style", this.setpoint_style);
+</xsl:text>
+    <xsl:text>                }else{
+</xsl:text>
+    <xsl:text>                    this.setpoint_elt.setAttribute("style", "display:none");
+</xsl:text>
+    <xsl:text>                }
+</xsl:text>
+    <xsl:text>                this.last_drag = this.drag;
+</xsl:text>
+    <xsl:text>            }
+</xsl:text>
+    <xsl:text>        }
 </xsl:text>
     <xsl:text>    }
 </xsl:text>
@@ -4153,140 +4179,166 @@
 </xsl:text>
     <xsl:text>    on_release(evt) {
 </xsl:text>
+    <xsl:text>        window.removeEventListener("touchmove", this.on_bound_drag, true);
+</xsl:text>
+    <xsl:text>        window.removeEventListener("mousemove", this.on_bound_drag, true);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        window.removeEventListener("mouseup", this.bound_on_release, true)
+</xsl:text>
+    <xsl:text>        window.removeEventListener("touchend", this.bound_on_release, true);
+</xsl:text>
+    <xsl:text>        window.removeEventListener("touchcancel", this.bound_on_release, true);
+</xsl:text>
     <xsl:text>        if(this.drag){
 </xsl:text>
     <xsl:text>            this.drag = false;
 </xsl:text>
     <xsl:text>        }
 </xsl:text>
+    <xsl:text>        this.update_position(evt);
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>    on_drag(evt){
+</xsl:text>
+    <xsl:text>        if(this.enTimer &amp;&amp; this.drag){
+</xsl:text>
+    <xsl:text>            this.update_position(evt);
+</xsl:text>
+    <xsl:text>            //reset timer
+</xsl:text>
+    <xsl:text>            this.enTimer = false;
+</xsl:text>
+    <xsl:text>            setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
     <xsl:text>    }
 </xsl:text>
     <xsl:text>
 </xsl:text>
     <xsl:text>    update_position(evt){
 </xsl:text>
-    <xsl:text>        if(this.drag){
-</xsl:text>
-    <xsl:text>            var html_dist = 0;
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>            //calculate size of widget in html
-</xsl:text>
-    <xsl:text>            var range_borders = this.range_elt.getBoundingClientRect();
-</xsl:text>
-    <xsl:text>            var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
-</xsl:text>
-    <xsl:text>            var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>            //get range and mouse coordinates
-</xsl:text>
-    <xsl:text>            var mouseX = undefined;
-</xsl:text>
-    <xsl:text>            var mouseY = undefined;
-</xsl:text>
-    <xsl:text>            if (evt.type.startsWith("touch")){
-</xsl:text>
-    <xsl:text>                mouseX = Math.ceil(evt.touches[0].clientX);
-</xsl:text>
-    <xsl:text>                mouseY = Math.ceil(evt.touches[0].clientY);
+    <xsl:text>        var html_dist = 0;
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        //calculate size of widget in html
+</xsl:text>
+    <xsl:text>        var range_borders = this.range_elt.getBoundingClientRect();
+</xsl:text>
+    <xsl:text>        var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
+</xsl:text>
+    <xsl:text>        var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        //get range and mouse coordinates
+</xsl:text>
+    <xsl:text>        var mouseX = undefined;
+</xsl:text>
+    <xsl:text>        var mouseY = undefined;
+</xsl:text>
+    <xsl:text>        if (evt.type.startsWith("touch")){
+</xsl:text>
+    <xsl:text>            mouseX = Math.ceil(evt.touches[0].clientX);
+</xsl:text>
+    <xsl:text>            mouseY = Math.ceil(evt.touches[0].clientY);
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>        else{
+</xsl:text>
+    <xsl:text>            mouseX = evt.pageX;
+</xsl:text>
+    <xsl:text>            mouseY = evt.pageY;
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        //get handle distance from mouse position
+</xsl:text>
+    <xsl:text>        if (minX &gt; mouseX &amp;&amp; minY &lt; mouseY){
+</xsl:text>
+    <xsl:text>            html_dist = 0;
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>        else if (maxX &lt; mouseX &amp;&amp; maxY &gt; mouseY){
+</xsl:text>
+    <xsl:text>            html_dist = range_length;
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>        else{
+</xsl:text>
+    <xsl:text>            // calculate distace
+</xsl:text>
+    <xsl:text>            if(this.fi &gt; 0.7){
+</xsl:text>
+    <xsl:text>                html_dist = (minY - mouseY)/Math.sin(this.fi);
 </xsl:text>
     <xsl:text>            }
 </xsl:text>
     <xsl:text>            else{
 </xsl:text>
-    <xsl:text>                mouseX = evt.pageX;
-</xsl:text>
-    <xsl:text>                mouseY = evt.pageY;
+    <xsl:text>                html_dist = (mouseX - minX)/Math.cos(this.fi);
 </xsl:text>
     <xsl:text>            }
 </xsl:text>
     <xsl:text>
 </xsl:text>
-    <xsl:text>            //get handle distance from mouse position
-</xsl:text>
-    <xsl:text>            if (minX &gt; mouseX &amp;&amp; minY &lt; mouseY){
+    <xsl:text>            //check if in range
+</xsl:text>
+    <xsl:text>            if (html_dist &gt; range_length){
+</xsl:text>
+    <xsl:text>                html_dist = range_length;
+</xsl:text>
+    <xsl:text>            }
+</xsl:text>
+    <xsl:text>            else if (html_dist &lt; 0){
 </xsl:text>
     <xsl:text>                html_dist = 0;
 </xsl:text>
     <xsl:text>            }
 </xsl:text>
-    <xsl:text>            else if (maxX &lt; mouseX &amp;&amp; maxY &gt; mouseY){
-</xsl:text>
-    <xsl:text>                html_dist = range_length;
-</xsl:text>
-    <xsl:text>            }
-</xsl:text>
-    <xsl:text>            else{
-</xsl:text>
-    <xsl:text>                // calculate distace
-</xsl:text>
-    <xsl:text>                if(this.fi &gt; 0.7){
-</xsl:text>
-    <xsl:text>                    html_dist = (minY - mouseY)/Math.sin(this.fi);
-</xsl:text>
-    <xsl:text>                }
-</xsl:text>
-    <xsl:text>                else{
-</xsl:text>
-    <xsl:text>                    html_dist = (mouseX - minX)/Math.cos(this.fi);
-</xsl:text>
-    <xsl:text>                }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>                //check if in range
-</xsl:text>
-    <xsl:text>                if (html_dist &gt; range_length){
-</xsl:text>
-    <xsl:text>                    html_dist = range_length;
-</xsl:text>
-    <xsl:text>                }
-</xsl:text>
-    <xsl:text>                else if (html_dist &lt; 0){
-</xsl:text>
-    <xsl:text>                    html_dist = 0;
-</xsl:text>
-    <xsl:text>                }
-</xsl:text>
-    <xsl:text>            }
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>            this.svg_dist=(html_dist/range_length)*this.range[1];
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>            //redraw handle
-</xsl:text>
-    <xsl:text>            //this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]);
-</xsl:text>
-    <xsl:text>            //this.value_elt.textContent = String(Math.ceil(svg_dist));
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>            if(this.enTimer){
-</xsl:text>
-    <xsl:text>                this.apply_hmi_value(0, Math.ceil(this.svg_dist));
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>                // TODO : update ghost cursor and call this.request_animate()
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>                //reset timer
-</xsl:text>
-    <xsl:text>                this.enTimer = false;
-</xsl:text>
-    <xsl:text>                setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
-</xsl:text>
-    <xsl:text>            }
+    <xsl:text>
 </xsl:text>
     <xsl:text>        }
 </xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        this.apply_hmi_value(0, this.svg_dist);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        // update ghost cursor
+</xsl:text>
+    <xsl:text>        if(this.setpoint_elt != undefined){
+</xsl:text>
+    <xsl:text>            this.request_animate();
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>    animate(){
+</xsl:text>
+    <xsl:text>        this.update_DOM(this.svg_dist, this.setpoint_elt);
+</xsl:text>
     <xsl:text>    }
 </xsl:text>
     <xsl:text>
@@ -4297,6 +4349,18 @@
 </xsl:text>
     <xsl:text>        this.enTimer = true;
 </xsl:text>
+    <xsl:text>        window.addEventListener("touchmove", this.on_bound_drag, true);
+</xsl:text>
+    <xsl:text>        window.addEventListener("mousemove", this.on_bound_drag, true);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        window.addEventListener("mouseup", this.bound_on_release, true)
+</xsl:text>
+    <xsl:text>        window.addEventListener("touchend", this.bound_on_release, true);
+</xsl:text>
+    <xsl:text>        window.addEventListener("touchcancel", this.bound_on_release, true);
+</xsl:text>
     <xsl:text>        this.update_position(evt);
 </xsl:text>
     <xsl:text>    }
@@ -4329,27 +4393,27 @@
 </xsl:text>
     <xsl:text>
 </xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>        this.handle_elt.addEventListener("touchstart", hmi_widgets[this.element_id].on_select.bind(this));
-</xsl:text>
-    <xsl:text>        this.handle_elt.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this));
-</xsl:text>
-    <xsl:text>        this.element.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this));
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>        window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this));
-</xsl:text>
-    <xsl:text>        window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this));
-</xsl:text>
-    <xsl:text>
-</xsl:text>
-    <xsl:text>        window.addEventListener("mouseup", hmi_widgets[this.element_id].on_release.bind(this))
-</xsl:text>
-    <xsl:text>        window.addEventListener("touchend", hmi_widgets[this.element_id].on_release.bind(this));
-</xsl:text>
-    <xsl:text>        window.addEventListener("touchcancel", hmi_widgets[this.element_id].on_release.bind(this));
+    <xsl:text>        this.bound_on_select = this.on_select.bind(this);
+</xsl:text>
+    <xsl:text>        this.bound_on_release = this.on_release.bind(this);
+</xsl:text>
+    <xsl:text>        this.on_bound_drag = this.on_drag.bind(this);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        this.element.addEventListener("mousedown", this.bound_on_select);
+</xsl:text>
+    <xsl:text>        this.element.addEventListener("touchstart", this.bound_on_select);
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>        if(this.setpoint_elt != undefined){
+</xsl:text>
+    <xsl:text>            this.setpoint_style = this.setpoint_elt.getAttribute("style");
+</xsl:text>
+    <xsl:text>            this.setpoint_elt.setAttribute("style", "display:none");
+</xsl:text>
+    <xsl:text>        }
 </xsl:text>
     <xsl:text>
 </xsl:text>
@@ -4369,7 +4433,7 @@
     <xsl:call-template name="defs_by_labels">
       <xsl:with-param name="hmi_element" select="$hmi_element"/>
       <xsl:with-param name="labels">
-        <xsl:text>value min max</xsl:text>
+        <xsl:text>value min max setpoint</xsl:text>
       </xsl:with-param>
       <xsl:with-param name="mandatory" select="'no'"/>
     </xsl:call-template>
--- a/svghmi/widget_slider.ysl2	Mon Aug 10 14:00:20 2020 +0200
+++ b/svghmi/widget_slider.ysl2	Mon Aug 10 15:25:57 2020 +0200
@@ -8,95 +8,127 @@
         fi = undefined;
         drag = false;
         enTimer = false;
-        svg_dist = 0
 
         dispatch(value) {
             if(this.value_elt)
                 this.value_elt.textContent = String(value);
 
-            this.handle_position(value);
+            this.update_DOM(value, this.handle_elt);
+
         }
 
-        handle_position(value){
+        last_drag = false;
+
+        update_DOM(value, elt){
             let [min,max,start,totallength] = this.range;
             let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
             let tip = this.range_elt.getPointAtLength(length);
-            this.handle_elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
+            elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")");
+
+            if(this.setpoint_elt != undefined){
+                if(this.last_drag!= this.drag){
+                    if(this.drag){
+                        this.setpoint_elt.setAttribute("style", this.setpoint_style);
+                    }else{
+                        this.setpoint_elt.setAttribute("style", "display:none");
+                    }
+                    this.last_drag = this.drag;
+                }
+            }
         }
 
         on_release(evt) {
+            window.removeEventListener("touchmove", this.on_bound_drag, true);
+            window.removeEventListener("mousemove", this.on_bound_drag, true);
+
+            window.removeEventListener("mouseup", this.bound_on_release, true)
+            window.removeEventListener("touchend", this.bound_on_release, true);
+            window.removeEventListener("touchcancel", this.bound_on_release, true);
             if(this.drag){
                 this.drag = false;
             }
+            this.update_position(evt);
+        }
+
+
+        on_drag(evt){
+            if(this.enTimer && this.drag){
+                this.update_position(evt);
+                //reset timer
+                this.enTimer = false;
+                setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
+            }
         }
 
         update_position(evt){
-            if(this.drag){
-                var html_dist = 0;
+            var html_dist = 0;
 
-                //calculate size of widget in html
-                var range_borders = this.range_elt.getBoundingClientRect();
-                var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
-                var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
+            //calculate size of widget in html
+            var range_borders = this.range_elt.getBoundingClientRect();
+            var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
+            var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
 
-                //get range and mouse coordinates
-                var mouseX = undefined;
-                var mouseY = undefined;
-                if (evt.type.startsWith("touch")){
-                    mouseX = Math.ceil(evt.touches[0].clientX);
-                    mouseY = Math.ceil(evt.touches[0].clientY);
+            //get range and mouse coordinates
+            var mouseX = undefined;
+            var mouseY = undefined;
+            if (evt.type.startsWith("touch")){
+                mouseX = Math.ceil(evt.touches[0].clientX);
+                mouseY = Math.ceil(evt.touches[0].clientY);
+            }
+            else{
+                mouseX = evt.pageX;
+                mouseY = evt.pageY;
+            }
+
+            //get handle distance from mouse position
+            if (minX > mouseX && minY < mouseY){
+                html_dist = 0;
+            }
+            else if (maxX < mouseX && maxY > mouseY){
+                html_dist = range_length;
+            }
+            else{
+                // calculate distace
+                if(this.fi > 0.7){
+                    html_dist = (minY - mouseY)/Math.sin(this.fi);
                 }
                 else{
-                    mouseX = evt.pageX;
-                    mouseY = evt.pageY;
+                    html_dist = (mouseX - minX)/Math.cos(this.fi);
                 }
 
-                //get handle distance from mouse position
-                if (minX > mouseX && minY < mouseY){
+                //check if in range
+                if (html_dist > range_length){
+                    html_dist = range_length;
+                }
+                else if (html_dist < 0){
                     html_dist = 0;
                 }
-                else if (maxX < mouseX && maxY > mouseY){
-                    html_dist = range_length;
-                }
-                else{
-                    // calculate distace
-                    if(this.fi > 0.7){
-                        html_dist = (minY - mouseY)/Math.sin(this.fi);
-                    }
-                    else{
-                        html_dist = (mouseX - minX)/Math.cos(this.fi);
-                    }
 
-                    //check if in range
-                    if (html_dist > range_length){
-                        html_dist = range_length;
-                    }
-                    else if (html_dist < 0){
-                        html_dist = 0;
-                    }
-                }
+            }
 
-                this.svg_dist=(html_dist/range_length)*this.range[1];
+            this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]);
 
-                //redraw handle
-                //this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]);
-                //this.value_elt.textContent = String(Math.ceil(svg_dist));
+            this.apply_hmi_value(0, this.svg_dist);
 
-                if(this.enTimer){
-                    this.apply_hmi_value(0, Math.ceil(this.svg_dist));
+            // update ghost cursor
+            if(this.setpoint_elt != undefined){
+                this.request_animate();
+            }
+        }
 
-                    // TODO : update ghost cursor and call this.request_animate()
-
-                    //reset timer
-                    this.enTimer = false;
-                    setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
-                }
-            }
+        animate(){
+            this.update_DOM(this.svg_dist, this.setpoint_elt);
         }
 
         on_select(evt){
             this.drag = true;
             this.enTimer = true;
+            window.addEventListener("touchmove", this.on_bound_drag, true);
+            window.addEventListener("mousemove", this.on_bound_drag, true);
+
+            window.addEventListener("mouseup", this.bound_on_release, true)
+            window.addEventListener("touchend", this.bound_on_release, true);
+            window.addEventListener("touchcancel", this.bound_on_release, true);
             this.update_position(evt);
         }
 
@@ -113,17 +145,17 @@
             let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength());
             this.fi = Math.atan2(start.y-end.y, end.x-start.x);
 
+            this.bound_on_select = this.on_select.bind(this);
+            this.bound_on_release = this.on_release.bind(this);
+            this.on_bound_drag = this.on_drag.bind(this);
 
-            this.handle_elt.addEventListener("touchstart", hmi_widgets[this.element_id].on_select.bind(this));
-            this.handle_elt.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this));
-            this.element.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this));
+            this.element.addEventListener("mousedown", this.bound_on_select);
+            this.element.addEventListener("touchstart", this.bound_on_select);
 
-            window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this));
-            window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this));
-
-            window.addEventListener("mouseup", hmi_widgets[this.element_id].on_release.bind(this))
-            window.addEventListener("touchend", hmi_widgets[this.element_id].on_release.bind(this));
-            window.addEventListener("touchcancel", hmi_widgets[this.element_id].on_release.bind(this));
+            if(this.setpoint_elt != undefined){
+                this.setpoint_style = this.setpoint_elt.getAttribute("style");
+                this.setpoint_elt.setAttribute("style", "display:none");
+            }
 
         }
     }
@@ -132,6 +164,6 @@
 template "widget[@type='Slider']", mode="widget_defs" {
     param "hmi_element";
     labels("handle range");
-    optional_labels("value min max");
+    optional_labels("value min max setpoint");
     |,
 }
--- a/tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg	Mon Aug 10 14:00:20 2020 +0200
+++ b/tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg	Mon Aug 10 15:25:57 2020 +0200
@@ -16,7 +16,7 @@
    version="1.1"
    id="hmi0"
    sodipodi:docname="svghmi.svg"
-   inkscape:version="0.92.4 (unknown)"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
    inkscape:label="Layer">
   <metadata
      id="metadata4542">
@@ -34,6 +34,13 @@
      id="defs2">
     <inkscape:perspective
        sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-688.56326 : 510.71991 : 1"
+       inkscape:vp_y="0 : 1306.0642 : 0"
+       inkscape:vp_z="662.62627 : 323.72015 : 1"
+       inkscape:persp3d-origin="147.31778 : 353.99223 : 1"
+       id="perspective258" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
        inkscape:vp_x="-457.78124 : 416.79285 : 1"
        inkscape:vp_y="0 : 1000 : 0"
        inkscape:vp_z="576.76945 : 273.61475 : 1"
@@ -130,17 +137,17 @@
      inkscape:pageopacity="0"
      inkscape:pageshadow="2"
      inkscape:document-units="px"
-     inkscape:current-layer="hmi0"
+     inkscape:current-layer="g110-0-9"
      showgrid="false"
      units="px"
-     inkscape:zoom="1"
-     inkscape:cx="900.14626"
-     inkscape:cy="284.87529"
-     inkscape:window-width="1451"
-     inkscape:window-height="1117"
-     inkscape:window-x="1972"
-     inkscape:window-y="127"
-     inkscape:window-maximized="0"
+     inkscape:zoom="1.4142136"
+     inkscape:cx="437.24009"
+     inkscape:cy="177.36896"
+     inkscape:window-width="1800"
+     inkscape:window-height="836"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
      showguides="true"
      inkscape:guide-bbox="true" />
   <rect
@@ -1133,6 +1140,57 @@
      inkscape:label="HMI:Slider@/PUMP0/SLOTH"
      transform="matrix(7.5590552,0,0,7.5590552,-248.554,584.0829)"
      id="g110-0-9">
+    <g
+       inkscape:label="setpoint"
+       style="opacity:0.5;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:0.76565915"
+       inkscape:corner7="-0.15304809 : -0.15652183 : 0.051043755 : 1"
+       inkscape:corner0="-0.13109479 : -0.13697746 : 0 : 1"
+       inkscape:perspectiveID="#perspective258"
+       id="g256"
+       sodipodi:type="inkscape:box3d">
+      <path
+         style="fill:#353564;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         points="69.054145,5.4029493 71.910946,3.7246414 71.910946,0.053890203 69.054145,1.5165601 "
+         d="M 69.054145,1.5165601 V 5.4029493 L 71.910946,3.7246414 V 0.0538902 Z"
+         inkscape:box3dsidetype="6"
+         id="path244"
+         sodipodi:type="inkscape:box3dside" />
+      <path
+         style="fill:#afafde;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         points="72.352867,6.8282124 75.092002,5.0278603 71.910946,3.7246414 69.054145,5.4029493 "
+         d="M 69.054145,5.4029493 72.352867,6.8282124 75.092002,5.0278603 71.910946,3.7246414 Z"
+         inkscape:box3dsidetype="13"
+         id="path246"
+         sodipodi:type="inkscape:box3dside" />
+      <path
+         style="fill:#e9e9ff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         points="75.092002,1.2673703 75.092002,5.0278603 71.910946,3.7246414 71.910946,0.053890203 "
+         d="m 71.910946,0.0538902 3.181056,1.2134801 v 3.76049 L 71.910946,3.7246414 Z"
+         inkscape:box3dsidetype="11"
+         id="path248"
+         sodipodi:type="inkscape:box3dside" />
+      <path
+         style="fill:#4d4d9f;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         points="72.352867,2.8410867 75.092002,1.2673703 71.910946,0.053890203 69.054145,1.5165601 "
+         d="M 69.054145,1.5165601 72.352867,2.8410867 75.092002,1.2673703 71.910946,0.0538902 Z"
+         inkscape:box3dsidetype="5"
+         id="path250"
+         sodipodi:type="inkscape:box3dside" />
+      <path
+         style="fill:#d7d7ff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         points="72.352867,6.8282124 75.092002,5.0278603 75.092002,1.2673703 72.352867,2.8410867 "
+         d="m 72.352867,2.8410867 v 3.9871257 l 2.739135,-1.8003521 v -3.76049 z"
+         inkscape:box3dsidetype="14"
+         id="path252"
+         sodipodi:type="inkscape:box3dside" />
+      <path
+         style="fill:#8686bf;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+         points="72.352867,2.8410867 72.352867,6.8282124 69.054145,5.4029493 69.054145,1.5165601 "
+         d="m 69.054145,1.5165601 3.298722,1.3245266 V 6.8282124 L 69.054145,5.4029493 Z"
+         inkscape:box3dsidetype="3"
+         id="path254"
+         sodipodi:type="inkscape:box3dside" />
+    </g>
     <path
        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:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.52375954;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"
        d="m 71.94894,3.6581855 79.3256,0.040092"