--- 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> enTimer = false;
- <xsl:text> svg_dist = 0
<xsl:text> dispatch(value) {
@@ -4131,13 +4129,19 @@
- <xsl:text> this.handle_position(value);
+ <xsl:text> this.update_DOM(value, this.handle_elt); - <xsl:text> handle_position(value){
+ <xsl:text> last_drag = false; + <xsl:text> update_DOM(value, elt){ <xsl:text> let [min,max,start,totallength] = this.range;
@@ -4145,7 +4149,29 @@
<xsl:text> let tip = this.range_elt.getPointAtLength(length);
- <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> if(this.setpoint_elt != undefined){ + <xsl:text> if(this.last_drag!= this.drag){ + <xsl:text> if(this.drag){ + <xsl:text> this.setpoint_elt.setAttribute("style", this.setpoint_style); + <xsl:text> this.setpoint_elt.setAttribute("style", "display:none"); + <xsl:text> this.last_drag = this.drag; @@ -4153,137 +4179,155 @@
<xsl:text> on_release(evt) {
+ <xsl:text> window.removeEventListener("touchmove", this.on_bound_drag, true); + <xsl:text> window.removeEventListener("mousemove", this.on_bound_drag, true); + <xsl:text> window.removeEventListener("mouseup", this.bound_on_release, true) + <xsl:text> window.removeEventListener("touchend", this.bound_on_release, true); + <xsl:text> window.removeEventListener("touchcancel", this.bound_on_release, true); <xsl:text> if(this.drag){
<xsl:text> this.drag = false;
+ <xsl:text> this.update_position(evt); + <xsl:text> on_drag(evt){ + <xsl:text> if(this.enTimer && this.drag){ + <xsl:text> this.update_position(evt); + <xsl:text> //reset timer + <xsl:text> this.enTimer = false; + <xsl:text> setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); <xsl:text> update_position(evt){
- <xsl:text> if(this.drag){
- <xsl:text> var html_dist = 0;
- <xsl:text> //calculate size of widget in html
- <xsl:text> var range_borders = this.range_elt.getBoundingClientRect();
- <xsl:text> var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width );
- <xsl:text> var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top];
- <xsl:text> //get range and mouse coordinates
- <xsl:text> var mouseX = undefined;
- <xsl:text> var mouseY = undefined;
- <xsl:text> if (evt.type.startsWith("touch")){
- <xsl:text> mouseX = Math.ceil(evt.touches[0].clientX);
- <xsl:text> mouseY = Math.ceil(evt.touches[0].clientY);
- <xsl:text> mouseX = evt.pageX;
- <xsl:text> mouseY = evt.pageY;
- <xsl:text> //get handle distance from mouse position
- <xsl:text> if (minX > mouseX && minY < mouseY){
- <xsl:text> html_dist = 0;
- <xsl:text> else if (maxX < mouseX && maxY > mouseY){
- <xsl:text> html_dist = range_length;
+ <xsl:text> var html_dist = 0; + <xsl:text> //calculate size of widget in html + <xsl:text> var range_borders = this.range_elt.getBoundingClientRect(); + <xsl:text> var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width ); + <xsl:text> var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top]; + <xsl:text> //get range and mouse coordinates + <xsl:text> var mouseX = undefined; + <xsl:text> var mouseY = undefined; + <xsl:text> if (evt.type.startsWith("touch")){ + <xsl:text> mouseX = Math.ceil(evt.touches[0].clientX); + <xsl:text> mouseY = Math.ceil(evt.touches[0].clientY); + <xsl:text> mouseX = evt.pageX; + <xsl:text> mouseY = evt.pageY; + <xsl:text> //get handle distance from mouse position + <xsl:text> if (minX > mouseX && minY < mouseY){ + <xsl:text> html_dist = 0; + <xsl:text> else if (maxX < mouseX && maxY > mouseY){ + <xsl:text> html_dist = range_length; + <xsl:text> // calculate distace + <xsl:text> if(this.fi > 0.7){ + <xsl:text> html_dist = (minY - mouseY)/Math.sin(this.fi); - <xsl:text> // calculate distace
- <xsl:text> if(this.fi > 0.7){
- <xsl:text> html_dist = (minY - mouseY)/Math.sin(this.fi);
- <xsl:text> html_dist = (mouseX - minX)/Math.cos(this.fi);
- <xsl:text> //check if in range
- <xsl:text> if (html_dist > range_length){
- <xsl:text> html_dist = range_length;
- <xsl:text> else if (html_dist < 0){
- <xsl:text> html_dist = 0;
+ <xsl:text> html_dist = (mouseX - minX)/Math.cos(this.fi); + <xsl:text> //check if in range + <xsl:text> if (html_dist > range_length){ + <xsl:text> html_dist = range_length; + <xsl:text> else if (html_dist < 0){ + <xsl:text> html_dist = 0; - <xsl:text> this.svg_dist=(html_dist/range_length)*this.range[1];
- <xsl:text> //redraw handle
- <xsl:text> //this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]);
- <xsl:text> //this.value_elt.textContent = String(Math.ceil(svg_dist));
- <xsl:text> if(this.enTimer){
- <xsl:text> this.apply_hmi_value(0, Math.ceil(this.svg_dist));
- <xsl:text> // TODO : update ghost cursor and call this.request_animate()
- <xsl:text> //reset timer
- <xsl:text> this.enTimer = false;
- <xsl:text> setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
+ <xsl:text> this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]); + <xsl:text> this.apply_hmi_value(0, this.svg_dist); + <xsl:text> // update ghost cursor + <xsl:text> if(this.setpoint_elt != undefined){ + <xsl:text> this.request_animate(); @@ -4291,12 +4335,32 @@
+ <xsl:text> this.update_DOM(this.svg_dist, this.setpoint_elt); <xsl:text> on_select(evt){
<xsl:text> this.drag = true;
<xsl:text> this.enTimer = true;
+ <xsl:text> window.addEventListener("touchmove", this.on_bound_drag, true); + <xsl:text> window.addEventListener("mousemove", this.on_bound_drag, true); + <xsl:text> window.addEventListener("mouseup", this.bound_on_release, true) + <xsl:text> window.addEventListener("touchend", this.bound_on_release, true); + <xsl:text> window.addEventListener("touchcancel", this.bound_on_release, true); <xsl:text> this.update_position(evt);
@@ -4329,27 +4393,27 @@
- <xsl:text> this.handle_elt.addEventListener("touchstart", hmi_widgets[this.element_id].on_select.bind(this));
- <xsl:text> this.handle_elt.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this));
- <xsl:text> this.element.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this));
- <xsl:text> window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this));
- <xsl:text> window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this));
- <xsl:text> window.addEventListener("mouseup", hmi_widgets[this.element_id].on_release.bind(this))
- <xsl:text> window.addEventListener("touchend", hmi_widgets[this.element_id].on_release.bind(this));
- <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> this.bound_on_release = this.on_release.bind(this); + <xsl:text> this.on_bound_drag = this.on_drag.bind(this); + <xsl:text> this.element.addEventListener("mousedown", this.bound_on_select); + <xsl:text> this.element.addEventListener("touchstart", this.bound_on_select); + <xsl:text> if(this.setpoint_elt != undefined){ + <xsl:text> this.setpoint_style = this.setpoint_elt.getAttribute("style"); + <xsl:text> this.setpoint_elt.setAttribute("style", "display:none"); @@ -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 name="mandatory" select="'no'"/>
--- 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 @@
this.value_elt.textContent = String(value);
- this.handle_position(value);
+ this.update_DOM(value, this.handle_elt); - handle_position(value){
+ 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){ + this.setpoint_elt.setAttribute("style", this.setpoint_style); + this.setpoint_elt.setAttribute("style", "display:none"); + this.last_drag = this.drag; + 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); + this.update_position(evt); + if(this.enTimer && this.drag){ + this.update_position(evt); + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
- //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); - //get handle distance from mouse position
- if (minX > mouseX && minY < mouseY){
- else if (maxX < mouseX && maxY > mouseY){
- html_dist = range_length;
+ //get handle distance from mouse position + if (minX > mouseX && minY < mouseY){ + else if (maxX < mouseX && maxY > mouseY){ + html_dist = range_length; + html_dist = (minY - mouseY)/Math.sin(this.fi);
- html_dist = (minY - mouseY)/Math.sin(this.fi);
- html_dist = (mouseX - minX)/Math.cos(this.fi);
+ html_dist = (mouseX - minX)/Math.cos(this.fi);
- if (html_dist > range_length){
- html_dist = range_length;
- else if (html_dist < 0){
+ if (html_dist > range_length){ + html_dist = range_length; + else if (html_dist < 0){ - this.svg_dist=(html_dist/range_length)*this.range[1];
- //this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]);
- //this.value_elt.textContent = String(Math.ceil(svg_dist));
+ this.svg_dist=Math.ceil((html_dist/range_length)*this.range[1]); + this.apply_hmi_value(0, this.svg_dist);
- this.apply_hmi_value(0, Math.ceil(this.svg_dist));
- // TODO : update ghost cursor and call this.request_animate()
+ if(this.setpoint_elt != undefined){ + this.request_animate();
- setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100);
+ this.update_DOM(this.svg_dist, this.setpoint_elt); + 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.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.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); - window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this));
- window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this));
+ this.element.addEventListener("mousedown", this.bound_on_select); + this.element.addEventListener("touchstart", this.bound_on_select); - 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" {
- 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 @@
sodipodi:docname="svghmi.svg"
- inkscape:version="0.92.4 (unknown)"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)" @@ -34,6 +34,13 @@
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" + 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:document-units="px"
- inkscape:current-layer="hmi0"
+ inkscape:current-layer="g110-0-9"
- 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-maximized="1" inkscape:guide-bbox="true" />
@@ -1133,6 +1140,57 @@
inkscape:label="HMI:Slider@/PUMP0/SLOTH"
transform="matrix(7.5590552,0,0,7.5590552,-248.554,584.0829)"
+ 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" + sodipodi:type="inkscape:box3d"> + 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" + sodipodi:type="inkscape:box3dside" /> + 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" + sodipodi:type="inkscape:box3dside" /> + 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" + sodipodi:type="inkscape:box3dside" /> + 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" + sodipodi:type="inkscape:box3dside" /> + 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" + sodipodi:type="inkscape:box3dside" /> + 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" + sodipodi:type="inkscape:box3dside" /> 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"