# HG changeset patch # User Edouard Tisserant <edouard.tisserant@gmail.com> # Date 1603146289 -7200 # Node ID 2263f2ecf9bbd0c8facd4c13caaf7c00afddf225 # Parent 466c3df6783508b4e345b1218718f90ee4b8afe3# Parent d7b9c2ceb3fbd43c3ccd433f19e848eba69b9199 merge diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/gen_index_xhtml.xslt Tue Oct 20 00:24:49 2020 +0200 @@ -1475,6 +1475,180 @@ </xsl:otherwise> </xsl:choose> </func:function> + <xsl:template mode="widget_class" match="widget[@type='Animate']"> + <xsl:text>class AnimateWidget extends Widget{ +</xsl:text> + <xsl:text> frequency = 5; +</xsl:text> + <xsl:text> speed = 0; +</xsl:text> + <xsl:text> start = false; +</xsl:text> + <xsl:text> widget_center = undefined; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> dispatch(value) { +</xsl:text> + <xsl:text> this.speed = value / 5; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //reconfigure animation +</xsl:text> + <xsl:text> this.request_animate(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> animate(){ +</xsl:text> + <xsl:text> // change animation properties +</xsl:text> + <xsl:text> for(let child of this.element.children){ +</xsl:text> + <xsl:text> if(child.nodeName.startsWith("animate")){ +</xsl:text> + <xsl:text> if(this.speed != 0 && !this.start){ +</xsl:text> + <xsl:text> this.start = true; +</xsl:text> + <xsl:text> this.element.beginElement(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> if(this.speed > 0){ +</xsl:text> + <xsl:text> child.setAttribute("dur", this.speed+"s"); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if(this.speed < 0){ +</xsl:text> + <xsl:text> child.setAttribute("dur", (-1)*this.speed+"s"); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> this.start = false; +</xsl:text> + <xsl:text> this.element.endElement(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> init() { +</xsl:text> + <xsl:text> let widget_pos = this.element.getBBox(); +</xsl:text> + <xsl:text> this.widget_center = [(widget_pos.x+widget_pos.width/2), (widget_pos.y+widget_pos.height/2)]; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text>} +</xsl:text> + </xsl:template> + <xsl:template mode="widget_defs" match="widget[@type='Animate']"> + <xsl:param name="hmi_element"/> + <xsl:text> +</xsl:text> + </xsl:template> + <xsl:template mode="widget_class" match="widget[@type='AnimateRotation']"> + <xsl:text>class AnimateRotationWidget extends Widget{ +</xsl:text> + <xsl:text> frequency = 5; +</xsl:text> + <xsl:text> speed = 0; +</xsl:text> + <xsl:text> widget_center = undefined; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> dispatch(value) { +</xsl:text> + <xsl:text> this.speed = value / 5; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //reconfigure animation +</xsl:text> + <xsl:text> this.request_animate(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> animate(){ +</xsl:text> + <xsl:text> // change animation properties +</xsl:text> + <xsl:text> for(let child of this.element.children){ +</xsl:text> + <xsl:text> if(child.nodeName == "animateTransform"){ +</xsl:text> + <xsl:text> if(this.speed > 0){ +</xsl:text> + <xsl:text> child.setAttribute("dur", this.speed+"s"); +</xsl:text> + <xsl:text> child.setAttribute("from", "0 "+this.widget_center[0]+" "+this.widget_center[1]); +</xsl:text> + <xsl:text> child.setAttribute("to", "360 "+this.widget_center[0]+" "+this.widget_center[1]); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if(this.speed < 0){ +</xsl:text> + <xsl:text> child.setAttribute("dur", (-1)*this.speed+"s"); +</xsl:text> + <xsl:text> child.setAttribute("from", "360 "+this.widget_center[0]+" "+this.widget_center[1]); +</xsl:text> + <xsl:text> child.setAttribute("to", "0 "+this.widget_center[0]+" "+this.widget_center[1]); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> child.setAttribute("from", "0 "+this.widget_center[0]+" "+this.widget_center[1]); +</xsl:text> + <xsl:text> child.setAttribute("to", "0 "+this.widget_center[0]+" "+this.widget_center[1]); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> init() { +</xsl:text> + <xsl:text> let widget_pos = this.element.getBBox(); +</xsl:text> + <xsl:text> this.widget_center = [(widget_pos.x+widget_pos.width/2), (widget_pos.y+widget_pos.height/2)]; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text>} +</xsl:text> + </xsl:template> + <xsl:template mode="widget_defs" match="widget[@type='AnimateRotation']"> + <xsl:param name="hmi_element"/> + <xsl:text> +</xsl:text> + </xsl:template> <xsl:template mode="widget_class" match="widget[@type='Back']"> <xsl:text>class BackWidget extends Widget{ </xsl:text> @@ -1506,7 +1680,9 @@ </xsl:text> <xsl:text> frequency = 5; </xsl:text> - <xsl:text> state = 0; + <xsl:text> state_plc = 0; +</xsl:text> + <xsl:text> state_hmi = 0; </xsl:text> <xsl:text> plc_lock = false; </xsl:text> @@ -1518,89 +1694,113 @@ </xsl:text> <xsl:text> dispatch(value) { </xsl:text> - <xsl:text> if(value){ -</xsl:text> - <xsl:text> this.button_release(); + <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> -</xsl:text> - <xsl:text> on_mouse_down(evt) { -</xsl:text> - <xsl:text> if (this.active_style && this.inactive_style) { -</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> } -</xsl:text> - <xsl:text> this.apply_hmi_value(0, 1); -</xsl:text> - <xsl:text> this.plc_lock = false; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> on_mouse_up(evt) { -</xsl:text> - <xsl:text> this.button_release(); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> button_release(){ -</xsl:text> - <xsl:text> if(!this.plc_lock){ -</xsl:text> - <xsl:text> this.plc_lock = true; + <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:text> animate(){ +</xsl:text> + <xsl:text> if (this.active_style && 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> else{ -</xsl:text> - <xsl:text> if (this.active_style && 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> this.apply_hmi_value(0, 0); + <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 && 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> -</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 && 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("onmousedown", "hmi_widgets["+this.element_id+"].on_mouse_down(evt)"); -</xsl:text> - <xsl:text> this.element.setAttribute("onmouseup", "hmi_widgets["+this.element_id+"].on_mouse_up(evt)"); + <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> @@ -1738,7 +1938,7 @@ </xsl:text> <xsl:text> handle_pos = undefined; </xsl:text> - <xsl:text> svg_dist = undefined; + <xsl:text> curr_value = 0; </xsl:text> <xsl:text> drag = false; </xsl:text> @@ -1750,13 +1950,47 @@ </xsl:text> <xsl:text> dispatch(value) { </xsl:text> + <xsl:text> let [min,max,start,totallength] = this.range; +</xsl:text> + <xsl:text> //save current value inside widget +</xsl:text> + <xsl:text> this.curr_value = value; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //check if in range +</xsl:text> + <xsl:text> if (this.curr_value > max){ +</xsl:text> + <xsl:text> this.curr_value = max; +</xsl:text> + <xsl:text> this.apply_hmi_value(0, this.curr_value); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if (this.curr_value < min){ +</xsl:text> + <xsl:text> this.curr_value = min; +</xsl:text> + <xsl:text> this.apply_hmi_value(0, this.curr_value); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> <xsl:text> if(this.value_elt) </xsl:text> <xsl:text> this.value_elt.textContent = String(value); </xsl:text> <xsl:text> </xsl:text> - <xsl:text> this.update_DOM(value, this.handle_elt); + <xsl:text> //don't update if draging and setpoint ghost doesn't exist +</xsl:text> + <xsl:text> if(!this.drag || (this.setpoint_elt != undefined)){ +</xsl:text> + <xsl:text> this.update_DOM(value, this.handle_elt); +</xsl:text> + <xsl:text> } </xsl:text> <xsl:text> } </xsl:text> @@ -1774,6 +2008,8 @@ </xsl:text> <xsl:text> </xsl:text> + <xsl:text> // show or hide ghost if exists +</xsl:text> <xsl:text> if(this.setpoint_elt != undefined){ </xsl:text> <xsl:text> if(this.last_drag!= this.drag){ @@ -1800,6 +2036,8 @@ </xsl:text> <xsl:text> on_release(evt) { </xsl:text> + <xsl:text> //unbind events +</xsl:text> <xsl:text> window.removeEventListener("touchmove", this.on_bound_drag, true); </xsl:text> <xsl:text> window.removeEventListener("mousemove", this.on_bound_drag, true); @@ -1812,12 +2050,20 @@ </xsl:text> <xsl:text> window.removeEventListener("touchcancel", this.bound_on_release, true); </xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //reset drag flag +</xsl:text> <xsl:text> if(this.drag){ </xsl:text> <xsl:text> this.drag = false; </xsl:text> <xsl:text> } </xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> // get final position +</xsl:text> <xsl:text> this.update_position(evt); </xsl:text> <xsl:text> } @@ -1826,10 +2072,14 @@ </xsl:text> <xsl:text> on_drag(evt){ </xsl:text> + <xsl:text> //ignore drag event for X amount of time and if not selected +</xsl:text> <xsl:text> if(this.enTimer && this.drag){ </xsl:text> <xsl:text> this.update_position(evt); </xsl:text> + <xsl:text> +</xsl:text> <xsl:text> //reset timer </xsl:text> <xsl:text> this.enTimer = false; @@ -1930,37 +2180,35 @@ </xsl:text> <xsl:text> if(fi<fiEnd){ </xsl:text> - <xsl:text> this.svg_dist=(fi)/(fiEnd)*(this.range[1]-this.range[0]); + <xsl:text> this.curr_value=(fi)/(fiEnd)*(this.range[1]-this.range[0]); </xsl:text> <xsl:text> } </xsl:text> <xsl:text> else if(fiEnd<fi && fi<fiEnd+minMax){ </xsl:text> - <xsl:text> this.svg_dist = this.range[1]; + <xsl:text> this.curr_value = this.range[1]; </xsl:text> <xsl:text> } </xsl:text> <xsl:text> else{ </xsl:text> - <xsl:text> this.svg_dist = this.range[0]; + <xsl:text> this.curr_value = this.range[0]; </xsl:text> <xsl:text> } </xsl:text> <xsl:text> </xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> this.apply_hmi_value(0, Math.ceil(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> //apply value to hmi +</xsl:text> + <xsl:text> this.apply_hmi_value(0, Math.ceil(this.curr_value)); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //redraw handle +</xsl:text> + <xsl:text> this.request_animate(); +</xsl:text> + <xsl:text> </xsl:text> <xsl:text> } </xsl:text> @@ -1972,7 +2220,21 @@ </xsl:text> <xsl:text> animate(){ </xsl:text> - <xsl:text> this.update_DOM(this.svg_dist, this.setpoint_elt); + <xsl:text> // redraw handle on screen refresh +</xsl:text> + <xsl:text> // check if setpoint(ghost) handle exsist otherwise update main handle +</xsl:text> + <xsl:text> if(this.setpoint_elt != undefined){ +</xsl:text> + <xsl:text> this.update_DOM(this.curr_value, this.setpoint_elt); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> this.update_DOM(this.curr_value, this.handle_elt); +</xsl:text> + <xsl:text> } </xsl:text> <xsl:text> } </xsl:text> @@ -1980,24 +2242,40 @@ </xsl:text> <xsl:text> on_select(evt){ </xsl:text> + <xsl:text> //enable drag flag and timer +</xsl:text> <xsl:text> this.drag = true; </xsl:text> <xsl:text> this.enTimer = true; </xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //bind events +</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> 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> +</xsl:text> + <xsl:text> //update postion on mouse press +</xsl:text> <xsl:text> this.update_position(evt); </xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //prevent next events +</xsl:text> + <xsl:text> evt.stopPropagation(); +</xsl:text> <xsl:text> } </xsl:text> <xsl:text> @@ -2074,13 +2352,21 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> //init events + <xsl:text> this.handle_elt.addEventListener("mousedown", this.bound_on_select); </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> //touch recognised as page drag without next command +</xsl:text> + <xsl:text> document.body.addEventListener("touchstart", function(e){}, false); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //save ghost style +</xsl:text> + <xsl:text> //save ghost style </xsl:text> <xsl:text> if(this.setpoint_elt != undefined){ </xsl:text> @@ -2092,22 +2378,6 @@ </xsl:text> <xsl:text> </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> - <xsl:text> -</xsl:text> <xsl:text> } </xsl:text> <xsl:text>} @@ -2124,13 +2394,66 @@ <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> <xsl:text> </xsl:text> </xsl:template> + <xsl:template mode="widget_class" match="widget[@type='CustomHtml']"> + <xsl:text>class CustomHtmlWidget extends Widget{ +</xsl:text> + <xsl:text> frequency = 5; +</xsl:text> + <xsl:text> widget_size = undefined; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> dispatch(value) { +</xsl:text> + <xsl:text> this.request_animate(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> animate(){ +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> init() { +</xsl:text> + <xsl:text> this.widget_size = this.container_elt.getBBox(); +</xsl:text> + <xsl:text> this.element.innerHTML ='<foreignObject x="'+ +</xsl:text> + <xsl:text> this.widget_size.x+'" y="'+this.widget_size.y+ +</xsl:text> + <xsl:text> '" width="'+this.widget_size.width+'" height="'+this.widget_size.height+'"> '+ +</xsl:text> + <xsl:text> this.code_elt.textContent+ +</xsl:text> + <xsl:text> ' </foreignObject>'; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text>} +</xsl:text> + </xsl:template> + <xsl:template mode="widget_defs" match="widget[@type='CustomHtml']"> + <xsl:param name="hmi_element"/> + <xsl:call-template name="defs_by_labels"> + <xsl:with-param name="hmi_element" select="$hmi_element"/> + <xsl:with-param name="labels"> + <xsl:text>container code</xsl:text> + </xsl:with-param> + </xsl:call-template> + <xsl:text> +</xsl:text> + </xsl:template> <xsl:template mode="widget_class" match="widget[@type='Display']"> <xsl:text>class DisplayWidget extends Widget{ </xsl:text> @@ -2162,7 +2485,9 @@ <xsl:when test="@type='HMI_STRING'"> <xsl:text>""</xsl:text> </xsl:when> - <xsl:otherwise>0</xsl:otherwise> + <xsl:otherwise> + <xsl:text>0</xsl:text> + </xsl:otherwise> </xsl:choose> <xsl:if test="position()!=last()"> <xsl:text>,</xsl:text> @@ -3501,7 +3826,7 @@ <xsl:template mode="widget_class" match="widget[@type='JsonTable']"> <xsl:text>class JsonTableWidget extends Widget{ </xsl:text> - <xsl:text> cache = []; + <xsl:text> cache = [100,50]; </xsl:text> <xsl:text> do_http_request(...opt) { </xsl:text> @@ -3509,7 +3834,9 @@ </xsl:text> <xsl:text> args: this.args, </xsl:text> - <xsl:text> vars: this.cache, + <xsl:text> range: this.cache[1], +</xsl:text> + <xsl:text> position: this.cache[2], </xsl:text> <xsl:text> visible: this.visible, </xsl:text> @@ -3848,6 +4175,8 @@ </xsl:text> <xsl:text> this.apply_hmi_value(2, position); </xsl:text> + <xsl:text> this.apply_hmi_value(3, this.visible); +</xsl:text> <xsl:text> console.log(range,position,jdata); </xsl:text> <xsl:apply-templates mode="json_table_render_except_comments" select="$data_elt"> @@ -4756,7 +5085,11 @@ </xsl:text> <xsl:text> handle_orig = undefined; </xsl:text> - <xsl:text> scroll_size = 10; + <xsl:text> scroll_size = undefined; +</xsl:text> + <xsl:text> scroll_range = 0; +</xsl:text> + <xsl:text> scroll_visible = 7; </xsl:text> <xsl:text> min_size = 0.07; </xsl:text> @@ -4774,17 +5107,59 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> dispatch(value) { -</xsl:text> - <xsl:text> //save current value inside widget -</xsl:text> - <xsl:text> this.curr_value = value; -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> if(this.value_elt) -</xsl:text> - <xsl:text> this.value_elt.textContent = String(value); + <xsl:text> dispatch(value,oldval, index) { +</xsl:text> + <xsl:text> if (index == 0){ +</xsl:text> + <xsl:text> let [min,max,start,totallength] = this.range; +</xsl:text> + <xsl:text> //save current value inside widget +</xsl:text> + <xsl:text> this.curr_value = value; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //check if in range +</xsl:text> + <xsl:text> if (this.curr_value > max){ +</xsl:text> + <xsl:text> this.curr_value = max; +</xsl:text> + <xsl:text> this.apply_hmi_value(0, this.curr_value); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if (this.curr_value < min){ +</xsl:text> + <xsl:text> this.curr_value = min; +</xsl:text> + <xsl:text> this.apply_hmi_value(0, this.curr_value); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> if(this.value_elt) +</xsl:text> + <xsl:text> this.value_elt.textContent = String(value); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if(index == 1){ +</xsl:text> + <xsl:text> this.scroll_range = value; +</xsl:text> + <xsl:text> this.set_scroll(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if(index == 2){ +</xsl:text> + <xsl:text> this.scroll_visible = value; +</xsl:text> + <xsl:text> this.set_scroll(); +</xsl:text> + <xsl:text> } </xsl:text> <xsl:text> </xsl:text> @@ -4792,7 +5167,7 @@ </xsl:text> <xsl:text> if(!this.drag || (this.setpoint_elt != undefined)){ </xsl:text> - <xsl:text> this.update_DOM(value, this.handle_elt); + <xsl:text> this.update_DOM(this.curr_value, this.handle_elt); </xsl:text> <xsl:text> } </xsl:text> @@ -4800,6 +5175,34 @@ </xsl:text> <xsl:text> </xsl:text> + <xsl:text> set_scroll(){ +</xsl:text> + <xsl:text> //check if range is bigger than visible and set scroll size +</xsl:text> + <xsl:text> if(this.scroll_range > this.scroll_visible){ +</xsl:text> + <xsl:text> this.scroll_size = this.scroll_range - this.scroll_visible; +</xsl:text> + <xsl:text> this.range[0] = 0; +</xsl:text> + <xsl:text> this.range[1] = this.scroll_size; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> this.scroll_size = 1; +</xsl:text> + <xsl:text> this.range[0] = 0; +</xsl:text> + <xsl:text> this.range[1] = 1; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> <xsl:text> update_DOM(value, elt){ </xsl:text> <xsl:text> let [min,max,start,totallength] = this.range; @@ -4946,7 +5349,7 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> window.removeEventListener("mouseup", this.bound_on_release, true) + <xsl:text> window.removeEventListener("mouseup", this.bound_on_release, true); </xsl:text> <xsl:text> window.removeEventListener("touchend", this.bound_on_release, true); </xsl:text> @@ -5138,7 +5541,7 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> //check if in range + <xsl:text> //check if in range and apply </xsl:text> <xsl:text> if (this.curr_value > max){ </xsl:text> @@ -5152,8 +5555,6 @@ </xsl:text> <xsl:text> } </xsl:text> - <xsl:text> -</xsl:text> <xsl:text> this.apply_hmi_value(0, this.curr_value); </xsl:text> <xsl:text> @@ -5208,7 +5609,7 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> window.addEventListener("mouseup", this.bound_on_release, true) + <xsl:text> window.addEventListener("mouseup", this.bound_on_release, true); </xsl:text> <xsl:text> window.addEventListener("touchend", this.bound_on_release, true); </xsl:text> @@ -5264,7 +5665,11 @@ </xsl:text> <xsl:text> evt.stopPropagation(); </xsl:text> - <xsl:text> } + <xsl:text> +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> </xsl:text> <xsl:text> </xsl:text> @@ -5286,6 +5691,8 @@ </xsl:text> <xsl:text> </xsl:text> + <xsl:text> +</xsl:text> <xsl:text> // save initial parameters </xsl:text> <xsl:text> this.range_elt.style.strokeMiterlimit="0"; @@ -5318,7 +5725,13 @@ </xsl:text> <xsl:text> this.element.addEventListener("touchstart", this.bound_on_select); </xsl:text> - <xsl:text> + <xsl:text> //touch recognised as page drag without next command +</xsl:text> + <xsl:text> document.body.addEventListener("touchstart", function(e){}, false); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //save ghost style </xsl:text> <xsl:text> if(this.setpoint_elt != undefined){ </xsl:text> @@ -5425,68 +5838,84 @@ </xsl:text> <xsl:text> dispatch(value) { </xsl:text> - <xsl:text> if(this.state != value){ -</xsl:text> - <xsl:text> this.state = value; -</xsl:text> - <xsl:text> if (this.state) { -</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> this.state = value; +</xsl:text> + <xsl:text> //redraw toggle button +</xsl:text> + <xsl:text> this.request_animate(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> on_click(evt) { +</xsl:text> + <xsl:text> //toggle state and apply +</xsl:text> + <xsl:text> if (this.state) { +</xsl:text> + <xsl:text> this.state = 0; +</xsl:text> + <xsl:text> } else { +</xsl:text> + <xsl:text> this.state = 1; </xsl:text> <xsl:text> } </xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> on_click(evt) { -</xsl:text> - <xsl:text> if (this.state) { + <xsl:text> this.apply_hmi_value(0, this.state); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //redraw toggle button +</xsl:text> + <xsl:text> this.request_animate(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> animate(){ +</xsl:text> + <xsl:text> // redraw toggle button on screen refresh +</xsl:text> + <xsl:text> if (this.state) { +</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> 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 && 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> this.active_elt.setAttribute("style", "display:none"); -</xsl:text> - <xsl:text> this.state = 0; -</xsl:text> - <xsl:text> } else { -</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> this.state = 1; -</xsl:text> <xsl:text> } </xsl:text> - <xsl:text> this.apply_hmi_value(0, this.state); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> init() { -</xsl:text> - <xsl:text> this.active_style = this.active_elt.style.cssText; -</xsl:text> - <xsl:text> this.inactive_style = this.inactive_elt.style.cssText; + <xsl:text> </xsl:text> <xsl:text> this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)"); </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>} @@ -5499,6 +5928,7 @@ <xsl:with-param name="labels"> <xsl:text>active inactive</xsl:text> </xsl:with-param> + <xsl:with-param name="mandatory" select="'no'"/> </xsl:call-template> <xsl:text> </xsl:text> diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/hmi_tree.ysl2 --- a/svghmi/hmi_tree.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/hmi_tree.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -73,8 +73,9 @@ // widget type="WidgetType" id="blah456" { // arg value="param1"; // arg value="param2"; -// path value="path1" index="345"; -// path value="path2"; +// path value=".path1" index=".path1" type="PAGE_LOCAL"; +// path value="/path1" index="348" type="HMI_INT"; +// path value="path4" index="path4" type="HMI_LOCAL"; // } // template "*", mode="parselabel" { diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_animate.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_animate.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -0,0 +1,53 @@ +// widget_animate.ysl2 + +template "widget[@type='Animate']", mode="widget_class"{ + || + class AnimateWidget extends Widget{ + frequency = 5; + speed = 0; + start = false; + widget_center = undefined; + + dispatch(value) { + this.speed = value / 5; + + //reconfigure animation + this.request_animate(); + } + + animate(){ + // change animation properties + for(let child of this.element.children){ + if(child.nodeName.startsWith("animate")){ + if(this.speed != 0 && !this.start){ + this.start = true; + this.element.beginElement(); + } + + if(this.speed > 0){ + child.setAttribute("dur", this.speed+"s"); + } + else if(this.speed < 0){ + child.setAttribute("dur", (-1)*this.speed+"s"); + } + else{ + this.start = false; + this.element.endElement(); + } + } + } + } + + init() { + let widget_pos = this.element.getBBox(); + this.widget_center = [(widget_pos.x+widget_pos.width/2), (widget_pos.y+widget_pos.height/2)]; + } + } + || +} + + +template "widget[@type='Animate']", mode="widget_defs" { + param "hmi_element"; + |, +} diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_animaterotation.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_animaterotation.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -0,0 +1,51 @@ +// widget_animaterotation.ysl2 + +template "widget[@type='AnimateRotation']", mode="widget_class"{ + || + class AnimateRotationWidget extends Widget{ + frequency = 5; + speed = 0; + widget_center = undefined; + + dispatch(value) { + this.speed = value / 5; + + //reconfigure animation + this.request_animate(); + } + + animate(){ + // change animation properties + for(let child of this.element.children){ + if(child.nodeName == "animateTransform"){ + if(this.speed > 0){ + child.setAttribute("dur", this.speed+"s"); + child.setAttribute("from", "0 "+this.widget_center[0]+" "+this.widget_center[1]); + child.setAttribute("to", "360 "+this.widget_center[0]+" "+this.widget_center[1]); + } + else if(this.speed < 0){ + child.setAttribute("dur", (-1)*this.speed+"s"); + child.setAttribute("from", "360 "+this.widget_center[0]+" "+this.widget_center[1]); + child.setAttribute("to", "0 "+this.widget_center[0]+" "+this.widget_center[1]); + } + else{ + child.setAttribute("from", "0 "+this.widget_center[0]+" "+this.widget_center[1]); + child.setAttribute("to", "0 "+this.widget_center[0]+" "+this.widget_center[1]); + } + } + } + } + + init() { + let widget_pos = this.element.getBBox(); + this.widget_center = [(widget_pos.x+widget_pos.width/2), (widget_pos.y+widget_pos.height/2)]; + } + } + || +} + + +template "widget[@type='AnimateRotation']", mode="widget_defs" { + param "hmi_element"; + |, +} diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_button.ysl2 --- a/svghmi/widget_button.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/widget_button.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -4,42 +4,55 @@ || class ButtonWidget extends Widget{ frequency = 5; - state = 0; + state_plc = 0; + state_hmi = 0; plc_lock = false; active_style = undefined; inactive_style = undefined; dispatch(value) { - if(value){ - this.button_release(); + this.state_plc = value; + if(this.plc_lock){ + if(this.state_plc == 1){ + this.apply_hmi_value(0, 0); + this.plc_lock = false; + } } + + //redraw button + this.state_hmi = this.state_plc; + this.request_animate(); } - on_mouse_down(evt) { - if (this.active_style && this.inactive_style) { - this.active_elt.setAttribute("style", this.active_style); - this.inactive_elt.setAttribute("style", "display:none"); - } - this.apply_hmi_value(0, 1); - this.plc_lock = false; - } + 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"); + } + } + } - on_mouse_up(evt) { - this.button_release(); - } + 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(); + } - button_release(){ - if(!this.plc_lock){ - this.plc_lock = true; - } - else{ - if (this.active_style && this.inactive_style) { - this.active_elt.setAttribute("style", "display:none"); - this.inactive_elt.setAttribute("style", this.inactive_style); - } - this.apply_hmi_value(0, 0); - } - } + on_press(evt) { + //set graphic + this.state_hmi = 1; + //redraw button + this.request_animate(); + } init() { this.active_style = this.active_elt ? this.active_elt.style.cssText : undefined; @@ -50,8 +63,8 @@ this.inactive_elt.setAttribute("style", this.inactive_style); } - this.element.setAttribute("onmousedown", "hmi_widgets["+this.element_id+"].on_mouse_down(evt)"); - this.element.setAttribute("onmouseup", "hmi_widgets["+this.element_id+"].on_mouse_up(evt)"); + this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)"); + this.element.setAttribute("onmousedown", "hmi_widgets['"+this.element_id+"'].on_press(evt)"); } } || diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_circularslider.ysl2 --- a/svghmi/widget_circularslider.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/widget_circularslider.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -7,16 +7,33 @@ range = undefined; circle = undefined; handle_pos = undefined; - svg_dist = undefined; + curr_value = 0; drag = false; enTimer = false; last_drag = false; dispatch(value) { + let [min,max,start,totallength] = this.range; + //save current value inside widget + this.curr_value = value; + + //check if in range + if (this.curr_value > max){ + this.curr_value = max; + this.apply_hmi_value(0, this.curr_value); + } + else if (this.curr_value < min){ + this.curr_value = min; + this.apply_hmi_value(0, this.curr_value); + } + if(this.value_elt) this.value_elt.textContent = String(value); - this.update_DOM(value, this.handle_elt); + //don't update if draging and setpoint ghost doesn't exist + if(!this.drag || (this.setpoint_elt != undefined)){ + this.update_DOM(value, this.handle_elt); + } } update_DOM(value, elt){ @@ -25,6 +42,7 @@ let tip = this.range_elt.getPointAtLength(length); elt.setAttribute('transform',"translate("+(tip.x-this.handle_pos.x)+","+(tip.y-this.handle_pos.y)+")"); + // show or hide ghost if exists if(this.setpoint_elt != undefined){ if(this.last_drag!= this.drag){ if(this.drag){ @@ -38,21 +56,28 @@ } on_release(evt) { + //unbind events 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); + + //reset drag flag if(this.drag){ this.drag = false; } + + // get final position this.update_position(evt); } on_drag(evt){ + //ignore drag event for X amount of time and if not selected if(this.enTimer && this.drag){ this.update_position(evt); + //reset timer this.enTimer = false; setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); @@ -103,40 +128,54 @@ //get handle distance from mouse position if(fi<fiEnd){ - this.svg_dist=(fi)/(fiEnd)*(this.range[1]-this.range[0]); + this.curr_value=(fi)/(fiEnd)*(this.range[1]-this.range[0]); } else if(fiEnd<fi && fi<fiEnd+minMax){ - this.svg_dist = this.range[1]; + this.curr_value = this.range[1]; } else{ - this.svg_dist = this.range[0]; - } - - - this.apply_hmi_value(0, Math.ceil(this.svg_dist)); - - // update ghost cursor - if(this.setpoint_elt != undefined){ - this.request_animate(); - } + this.curr_value = this.range[0]; + } + + //apply value to hmi + this.apply_hmi_value(0, Math.ceil(this.curr_value)); + + //redraw handle + this.request_animate(); + } } animate(){ - this.update_DOM(this.svg_dist, this.setpoint_elt); + // redraw handle on screen refresh + // check if setpoint(ghost) handle exsist otherwise update main handle + if(this.setpoint_elt != undefined){ + this.update_DOM(this.curr_value, this.setpoint_elt); + } + else{ + this.update_DOM(this.curr_value, this.handle_elt); + } } on_select(evt){ + //enable drag flag and timer this.drag = true; this.enTimer = true; + + //bind events 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("mouseup", this.bound_on_release, true); window.addEventListener("touchend", this.bound_on_release, true); window.addEventListener("touchcancel", this.bound_on_release, true); + + //update postion on mouse press this.update_position(evt); + + //prevent next events + evt.stopPropagation(); } init() { @@ -175,23 +214,19 @@ this.bound_on_release = this.on_release.bind(this); this.on_bound_drag = this.on_drag.bind(this); - //init events + this.handle_elt.addEventListener("mousedown", this.bound_on_select); this.element.addEventListener("mousedown", this.bound_on_select); this.element.addEventListener("touchstart", this.bound_on_select); - + //touch recognised as page drag without next command + document.body.addEventListener("touchstart", function(e){}, false); + + //save ghost style + //save ghost style if(this.setpoint_elt != undefined){ this.setpoint_style = this.setpoint_elt.getAttribute("style"); this.setpoint_elt.setAttribute("style", "display:none"); } - - 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)); - } } || @@ -199,6 +234,6 @@ template "widget[@type='CircularSlider']", mode="widget_defs" { param "hmi_element"; labels("handle range"); - optional_labels("value min max"); + optional_labels("value min max setpoint"); |, } diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_customhtml.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_customhtml.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -0,0 +1,33 @@ +// widget_customhtml.ysl2 + +template "widget[@type='CustomHtml']", mode="widget_class"{ + || + class CustomHtmlWidget extends Widget{ + frequency = 5; + widget_size = undefined; + + dispatch(value) { + this.request_animate(); + } + + animate(){ + } + + init() { + this.widget_size = this.container_elt.getBBox(); + this.element.innerHTML ='<foreignObject x="'+ + this.widget_size.x+'" y="'+this.widget_size.y+ + '" width="'+this.widget_size.width+'" height="'+this.widget_size.height+'"> '+ + this.code_elt.textContent+ + ' </foreignObject>'; + } + } + || +} + + +template "widget[@type='CustomHtml']", mode="widget_defs" { + param "hmi_element"; + labels("container code"); + |, +} diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_display.ysl2 --- a/svghmi/widget_display.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/widget_display.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -20,7 +20,7 @@ const "field_initializer" foreach "path" { choose{ when "@type='HMI_STRING'" > "" - otherwise 0 + otherwise > 0 } if "position()!=last()" > , } diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_jsontable.ysl2 --- a/svghmi/widget_jsontable.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/widget_jsontable.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -3,11 +3,12 @@ template "widget[@type='JsonTable']", mode="widget_class" || class JsonTableWidget extends Widget{ - cache = []; + cache = [100,50]; do_http_request(...opt) { const query = { args: this.args, - vars: this.cache, + range: this.cache[1], + position: this.cache[2], visible: this.visible, options: opt }; @@ -218,6 +219,7 @@ | let [range,position,jdata] = janswer; | this.apply_hmi_value(1, range); | this.apply_hmi_value(2, position); + | this.apply_hmi_value(3, this.visible); | console.log(range,position,jdata); apply "$data_elt", mode="json_table_render_except_comments" { with "expressions","$initexpr_ns"; diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_slider.ysl2 --- a/svghmi/widget_slider.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/widget_slider.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -6,7 +6,9 @@ frequency = 5; range = undefined; handle_orig = undefined; - scroll_size = 10; + scroll_size = undefined; + scroll_range = 0; + scroll_visible = 7; min_size = 0.07; fi = undefined; curr_value = 0; @@ -15,16 +17,51 @@ handle_click = undefined; last_drag = false; - dispatch(value) { - //save current value inside widget - this.curr_value = value; - - if(this.value_elt) - this.value_elt.textContent = String(value); + dispatch(value,oldval, index) { + if (index == 0){ + let [min,max,start,totallength] = this.range; + //save current value inside widget + this.curr_value = value; + + //check if in range + if (this.curr_value > max){ + this.curr_value = max; + this.apply_hmi_value(0, this.curr_value); + } + else if (this.curr_value < min){ + this.curr_value = min; + this.apply_hmi_value(0, this.curr_value); + } + + if(this.value_elt) + this.value_elt.textContent = String(value); + } + else if(index == 1){ + this.scroll_range = value; + this.set_scroll(); + } + else if(index == 2){ + this.scroll_visible = value; + this.set_scroll(); + } //don't update if draging and setpoint ghost doesn't exist if(!this.drag || (this.setpoint_elt != undefined)){ - this.update_DOM(value, this.handle_elt); + this.update_DOM(this.curr_value, this.handle_elt); + } + } + + set_scroll(){ + //check if range is bigger than visible and set scroll size + if(this.scroll_range > this.scroll_visible){ + this.scroll_size = this.scroll_range - this.scroll_visible; + this.range[0] = 0; + this.range[1] = this.scroll_size; + } + else{ + this.scroll_size = 1; + this.range[0] = 0; + this.range[1] = 1; } } @@ -101,7 +138,7 @@ 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("mouseup", this.bound_on_release, true); window.removeEventListener("touchend", this.bound_on_release, true); window.removeEventListener("touchcancel", this.bound_on_release, true); @@ -197,14 +234,13 @@ this.curr_value=Math.ceil((html_dist/range_length)*(this.range[1]-this.range[0])+this.range[0]); } - //check if in range + //check if in range and apply if (this.curr_value > max){ this.curr_value = max; } else if (this.curr_value < min){ this.curr_value = min; } - this.apply_hmi_value(0, this.curr_value); //redraw handle @@ -232,7 +268,7 @@ 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("mouseup", this.bound_on_release, true); window.addEventListener("touchend", this.bound_on_release, true); window.addEventListener("touchcancel", this.bound_on_release, true); @@ -260,7 +296,9 @@ //prevent next events evt.stopPropagation(); - } + + } + init() { //set min max value if not defined @@ -271,6 +309,7 @@ Number(this.max_elt.textContent) : this.args.length >= 2 ? this.args[1] : 100; + // save initial parameters this.range_elt.style.strokeMiterlimit="0"; this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()]; @@ -287,7 +326,10 @@ this.handle_elt.addEventListener("mousedown", this.bound_on_select); this.element.addEventListener("mousedown", this.bound_on_select); this.element.addEventListener("touchstart", this.bound_on_select); - + //touch recognised as page drag without next command + document.body.addEventListener("touchstart", function(e){}, false); + + //save ghost style if(this.setpoint_elt != undefined){ this.setpoint_style = this.setpoint_elt.getAttribute("style"); this.setpoint_elt.setAttribute("style", "display:none"); diff -r 466c3df67835 -r 2263f2ecf9bb svghmi/widget_tooglebutton.ysl2 --- a/svghmi/widget_tooglebutton.ysl2 Tue Oct 20 00:23:52 2020 +0200 +++ b/svghmi/widget_tooglebutton.ysl2 Tue Oct 20 00:24:49 2020 +0200 @@ -10,37 +10,45 @@ inactive_style = undefined; dispatch(value) { - if(this.state != value){ - this.state = value; - if (this.state) { - 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"); - } - } + this.state = value; + //redraw toggle button + this.request_animate(); } on_click(evt) { + //toggle state and apply if (this.state) { - this.inactive_elt.setAttribute("style", this.inactive_style); - this.active_elt.setAttribute("style", "display:none"); this.state = 0; } else { - this.active_elt.setAttribute("style", this.active_style); - this.inactive_elt.setAttribute("style", "display:none"); this.state = 1; } this.apply_hmi_value(0, this.state); + + //redraw toggle button + this.request_animate(); + } + + animate(){ + // redraw toggle button on screen refresh + if (this.state) { + 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"); + } } init() { - this.active_style = this.active_elt.style.cssText; - this.inactive_style = this.inactive_elt.style.cssText; + 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.inactive_elt.setAttribute("style", this.inactive_style); - this.active_elt.setAttribute("style", "display:none"); } } || @@ -48,6 +56,6 @@ template "widget[@type='ToggleButton']", mode="widget_defs" { param "hmi_element"; - labels("active inactive"); + optional_labels("active inactive"); |, } diff -r 466c3df67835 -r 2263f2ecf9bb tests/svghmi/py_ext_0@py_ext/pyfile.xml --- a/tests/svghmi/py_ext_0@py_ext/pyfile.xml Tue Oct 20 00:23:52 2020 +0200 +++ b/tests/svghmi/py_ext_0@py_ext/pyfile.xml Tue Oct 20 00:24:49 2020 +0200 @@ -30,8 +30,9 @@ def render_POST(self, request): newstr = request.content.getvalue() newdata = json.loads(newstr) - vars = newdata[u'vars'] args = newdata[u'args'] + range_feedback = newdata[u'range'] + slider_position = newdata[u'position'] visible = newdata[u'visible'] options = newdata[u'options'] @@ -40,14 +41,11 @@ if action == "onClick[acknowledge]": AlarmIndex[int(alarmid)][2] = "ack" - svars = (vars + [0,0])[:3] - range_feedback = svars[1] - slider_position = svars[2] - answer = self.renderTable(range_feedback, slider_position, visible, *(args+svars[3:])) + answer = self.renderTable(range_feedback, slider_position, visible) janswer = json.dumps(answer) return janswer - def renderTable(self, old_range, old_position, visible, *options): + def renderTable(self, old_range, old_position, visible): new_range = len(Alarms) delta = new_range - visible new_position = 0 if delta <= 0 else delta if old_position > delta else old_position diff -r 466c3df67835 -r 2263f2ecf9bb tests/svghmi/svghmi_0@svghmi/svghmi.svg --- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg Tue Oct 20 00:23:52 2020 +0200 +++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg Tue Oct 20 00:24:49 2020 +0200 @@ -16,7 +16,7 @@ version="1.1" id="hmi0" sodipodi:docname="svghmi.svg" - inkscape:version="0.92.3 (2405546, 2018-03-11)"> + inkscape:version="0.92.5 (0.92.5+68)"> <metadata id="metadata4542"> <rdf:RDF> @@ -197,16 +197,16 @@ inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:document-units="px" - inkscape:current-layer="g1384" + inkscape:current-layer="hmi0" showgrid="false" units="px" - inkscape:zoom="1.0913159" - inkscape:cx="-911.00114" - inkscape:cy="181.96708" - inkscape:window-width="1800" - inkscape:window-height="836" - inkscape:window-x="0" - inkscape:window-y="27" + inkscape:zoom="2.1826317" + inkscape:cx="-408.38959" + inkscape:cy="176.28106" + inkscape:window-width="1863" + inkscape:window-height="1176" + inkscape:window-x="57" + inkscape:window-y="24" inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" /> @@ -5223,6 +5223,9 @@ <g id="g908" inkscape:label="HMI:VarInit:100@.range" /> + <g + inkscape:label="HMI:VarInit:7@.visibleAlarms" + id="g906-3" /> <rect style="color:#000000;fill:#4d4d4d" id="rect2015" @@ -5549,32 +5552,53 @@ sodipodi:type="star" /> </g> <g - id="g1553" - transform="matrix(0.5,0,0,0.5,-774.48108,252.30551)"> + id="g1766" + inkscape:label="HMI:Slider@.position@.range@.alarmVisible"> + <g + transform="matrix(0.620824,0,0,0.5,-963.61047,260.72872)" + id="g1752" + inkscape:label="HMI:Input@.position"> + <path + inkscape:label="+1" + 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:#ff6600;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.55573034px;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" + d="m 1175.2115,143.25263 34.1278,56.73732 h -68.2556 z" + id="path1266" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + inkscape:label="-1" + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" + id="path1268" + d="m 1175.2115,851.99803 34.1278,-54.90445 h -68.2556 z" + 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:#ff6600;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.51411843px;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> + <path + style="opacity:0;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00058591px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M -234.01102,648.56465 V 371.89445" + id="path1772" + inkscape:connector-curvature="0" + inkscape:label="range" /> <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:#bc8f8f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2px;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" + style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.30952382;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.03627348px;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="rect1264-3" + width="42.374725" + height="276.64423" + x="-255.19838" + y="371.91068" + rx="7.6034913" + ry="6.8822322" + inkscape:label="background" /> + <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:#ff6600;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.11429262px;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="rect1264" - width="68.255615" - height="165.68298" - x="1141.0836" - y="420.78394" - rx="12.247418" - ry="14" - inkscape:label="cursor" /> - <path - sodipodi:nodetypes="cccc" - inkscape:connector-curvature="0" - id="path1266" - d="m 1175.2115,371.25263 34.1278,34.74552 h -68.2556 z" - 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:#bc8f8f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2px;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" - inkscape:label="backward" /> - <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;vector-effect:none;fill:#bc8f8f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2px;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" - d="m 1175.2115,635.99803 34.1278,-34.7453 h -68.2556 z" - id="path1268" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" - inkscape:label="forward" /> + width="42.374725" + height="82.841492" + x="-255.19838" + y="565.71338" + rx="7.6034913" + ry="7" + inkscape:label="handle" /> </g> <g id="g893" @@ -6029,16 +6053,6 @@ x="-546.47461" id="tspan2172" sodipodi:role="line">Status</tspan></text> - <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:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - x="-241.25107" - y="513.61072" - id="text2184"><tspan - sodipodi:role="line" - id="tspan2182" - x="-241.25107" - y="513.61072">TODO</tspan></text> <g transform="matrix(0.57180538,0,0,0.57180538,226.35945,-231.48695)" inkscape:label="HMI:Jump:AlarmPage" diff -r 466c3df67835 -r 2263f2ecf9bb tests/svghmi_v2/plc.xml --- a/tests/svghmi_v2/plc.xml Tue Oct 20 00:23:52 2020 +0200 +++ b/tests/svghmi_v2/plc.xml Tue Oct 20 00:24:49 2020 +0200 @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='utf-8'?> <project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201"> <fileHeader companyName="Unknown" productName="Unnamed" productVersion="1" creationDateTime="2019-08-06T14:23:42"/> - <contentHeader name="Unnamed" modificationDateTime="2020-09-15T14:59:06"> + <contentHeader name="Unnamed" modificationDateTime="2020-09-30T13:04:27"> <coordinateInfo> <fbd> <scaling x="5" y="5"/> @@ -75,6 +75,11 @@ <INT/> </type> </variable> + <variable name="Speed"> + <type> + <derived name="HMI_INT"/> + </type> + </variable> </localVars> </interface> <body> diff -r 466c3df67835 -r 2263f2ecf9bb tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg --- a/tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg Tue Oct 20 00:23:52 2020 +0200 +++ b/tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg Tue Oct 20 00:24:49 2020 +0200 @@ -92,10 +92,10 @@ y2="4.0725975" /> <inkscape:perspective sodipodi:type="inkscape:persp3d" - inkscape:vp_x="-173.06414 : 591.30354 : 1" + inkscape:vp_x="-470.06413 : 851.30353 : 1" inkscape:vp_y="0 : 1319.7648 : 0" - inkscape:vp_z="1192.2994 : 402.34211 : 1" - inkscape:persp3d-origin="671.58536 : 432.93175 : 1" + inkscape:vp_z="895.29941 : 662.3421 : 1" + inkscape:persp3d-origin="374.58537 : 692.93174 : 1" id="perspective503-6" /> </defs> <sodipodi:namedview @@ -109,9 +109,9 @@ inkscape:current-layer="hmi0" showgrid="false" units="px" - inkscape:zoom="1.4142136" - inkscape:cx="462.89448" - inkscape:cy="318.79031" + inkscape:zoom="1" + inkscape:cx="379.07861" + inkscape:cy="265.09897" inkscape:window-width="2503" inkscape:window-height="1416" inkscape:window-x="57" @@ -129,8 +129,8 @@ inkscape:label="HMI:Page:Home" sodipodi:insensitive="true" /> <g - inkscape:label="HMI:Slider@/PUMP0/SLOTH" - transform="matrix(7.5590552,0,0,7.5590552,-710.78539,551.61779)" + inkscape:label="HMI:Slider@/SPEED" + transform="matrix(7.5590552,0,0,7.5590552,-780.78539,561.61779)" id="g110-0"> <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.52916664;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" @@ -189,15 +189,15 @@ inkscape:label="HMI:Input@/SOMEPLCGLOBAL"> <text inkscape:label="value" - transform="scale(1.1201068,0.89277203)" + transform="scale(1.1201068,0.89277202)" id="text2398" - y="446.98395" - x="347.5253" + y="479.46704" + x="247.53484" style="font-style:normal;font-weight:normal;font-size:124.08008575px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.10200214px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve"><tspan style="stroke-width:3.10200214px" - y="446.98395" - x="347.5253" + y="479.46704" + x="247.53484" id="tspan2396" sodipodi:role="line">Test</tspan></text> <rect @@ -205,8 +205,8 @@ id="rect4559" width="323.85489" height="132.93608" - x="369.10974" - y="299.97858" + x="257.10974" + y="328.97858" inkscape:label="edit" /> <rect style="opacity:0;fill:#de2cc9;fill-opacity:1;stroke:none;stroke-width:3.45667744" @@ -1366,7 +1366,7 @@ <g id="g1047" inkscape:label="HMI:CircularBar@/PUMP0/SLOTH" - transform="matrix(0.39840034,0,0,0.35920948,224.04409,96.134885)"> + transform="matrix(0.39840034,0,0,0.35920948,-97.955902,106.13488)"> <path inkscape:label="range" sodipodi:open="true" @@ -1410,7 +1410,7 @@ <g id="g1047-6" inkscape:label="HMI:CircularSlider@/PUMP0/SLOTH" - transform="matrix(0.45707797,0,0,0.45707797,330.74411,340.99474)"> + transform="matrix(0.45707797,0,0,0.45707797,33.744118,80.994747)"> <path inkscape:label="range" d="M 970.29569,399.76446 A 184.25998,167.44942 0 0 1 866.26395,284.77467 184.25998,167.44942 0 0 1 904.10823,139.93753" @@ -1438,43 +1438,43 @@ sodipodi:type="inkscape:box3dside" id="path932-9" inkscape:box3dsidetype="6" - d="m 919.8592,371.09874 v 61.75093 l 51.05152,-25.59855 V 348.7668 Z" - points="919.8592,432.84967 970.91072,407.25112 970.91072,348.7668 919.8592,371.09874 " + d="m 919.8592,371.09875 v 61.75093 l 51.05152,-25.59855 v -58.48432 z" + points="919.8592,432.84968 970.91072,407.25113 970.91072,348.76681 919.8592,371.09875 " style="fill:#353564;fill-rule:evenodd;stroke:none;stroke-width:21.82598114px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> <path sodipodi:type="inkscape:box3dside" id="path940-1" inkscape:box3dsidetype="13" - d="m 919.8592,432.84967 49.77111,22.08625 49.54589,-27.39008 -48.26548,-20.29472 z" - points="969.63031,454.93592 1019.1762,427.54584 970.91072,407.25112 919.8592,432.84967 " + d="m 919.8592,432.84968 49.77112,22.08624 49.54588,-27.39007 -48.26548,-20.29472 z" + points="969.63032,454.93592 1019.1762,427.54585 970.91072,407.25113 919.8592,432.84968 " style="fill:#afafde;fill-rule:evenodd;stroke:none;stroke-width:21.82598114px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> <path sodipodi:type="inkscape:box3dside" id="path942-2" inkscape:box3dsidetype="11" - d="m 970.91072,348.7668 48.26548,18.93314 v 59.8459 l -48.26548,-20.29472 z" - points="1019.1762,367.69994 1019.1762,427.54584 970.91072,407.25112 970.91072,348.7668 " + d="m 970.91072,348.76681 48.26548,18.93313 v 59.84591 l -48.26548,-20.29472 z" + points="1019.1762,367.69994 1019.1762,427.54585 970.91072,407.25113 970.91072,348.76681 " style="fill:#e9e9ff;fill-rule:evenodd;stroke:none;stroke-width:21.82598114px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> <path sodipodi:type="inkscape:box3dside" id="path934-7" inkscape:box3dsidetype="5" - d="m 919.8592,371.09874 49.77111,20.56633 49.54589,-23.96513 -48.26548,-18.93314 z" - points="969.63031,391.66507 1019.1762,367.69994 970.91072,348.7668 919.8592,371.09874 " + d="m 919.8592,371.09875 49.77112,20.56633 49.54588,-23.96514 -48.26548,-18.93313 z" + points="969.63032,391.66508 1019.1762,367.69994 970.91072,348.76681 919.8592,371.09875 " style="fill:#4d4d9f;fill-rule:evenodd;stroke:none;stroke-width:21.82598114px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> <path sodipodi:type="inkscape:box3dside" id="path938-0" inkscape:box3dsidetype="14" - d="m 969.63031,391.66507 v 63.27085 l 49.54589,-27.39008 v -59.8459 z" - points="969.63031,454.93592 1019.1762,427.54584 1019.1762,367.69994 969.63031,391.66507 " + d="m 969.63032,391.66508 v 63.27084 l 49.54588,-27.39007 v -59.84591 z" + points="969.63032,454.93592 1019.1762,427.54585 1019.1762,367.69994 969.63032,391.66508 " style="fill:#d7d7ff;fill-rule:evenodd;stroke:none;stroke-width:21.82598114px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> <path sodipodi:type="inkscape:box3dside" id="path936-9" inkscape:box3dsidetype="3" - d="m 919.8592,371.09874 49.77111,20.56633 v 63.27085 L 919.8592,432.84967 Z" - points="969.63031,391.66507 969.63031,454.93592 919.8592,432.84967 919.8592,371.09874 " + d="m 919.8592,371.09875 49.77112,20.56633 v 63.27084 L 919.8592,432.84968 Z" + points="969.63032,391.66508 969.63032,454.93592 919.8592,432.84968 919.8592,371.09875 " style="fill:#8686bf;fill-rule:evenodd;stroke:none;stroke-width:21.82598114px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> </g> <text @@ -1492,27 +1492,7 @@ style="fill:#ff00ca;fill-opacity:1;stroke:none;stroke-width:2.25346255px;stroke-opacity:1">000</tspan></text> </g> <g - id="g4791" - inkscape:label="HMI:ToggleButton@/TOGGLE2"> - <rect - inkscape:label="inactive" - y="46.127251" - x="906.51086" - height="44.547726" - width="45.254833" - id="rect4772" - style="opacity:1;fill:#ff0015;fill-opacity:1;stroke:none" /> - <rect - inkscape:label="active" - y="46.127251" - x="906.51086" - height="44.547726" - width="45.254833" - id="rect4772-3" - style="opacity:1;fill:#00ff03;fill-opacity:1;stroke:none" /> - </g> - <g - transform="translate(-67.175138,-1.0606552)" + transform="translate(-289.17513,-33.060654)" id="g4791-6" inkscape:label="HMI:ToggleButton@/TOGGLE1"> <rect @@ -1533,16 +1513,16 @@ style="opacity:1;fill:#00ff03;fill-opacity:1;stroke:none" /> </g> <g - transform="translate(63.639613)" - id="g4791-3" - inkscape:label="HMI:ToggleButton@/TOGGLE"> + transform="translate(-287.05529,41.033314)" + id="g479hgjk" + inkscape:label="HMI:Button@/TOGGLE"> <rect inkscape:label="active" y="46.127251" x="906.51086" height="44.547726" width="45.254833" - id="rect4772-3-5" + id="rect47fuzkj" style="opacity:1;fill:#00ff03;fill-opacity:1;stroke:none" /> <rect inkscape:label="inactive" @@ -1550,7 +1530,90 @@ x="906.51086" height="44.547726" width="45.254833" - id="rect4772-6" + id="rect477hjoj" style="opacity:1;fill:#ff0015;fill-opacity:1;stroke:none" /> </g> + <g + id="g1112" + inkscape:label="HMI:AnimateRotation@/SPEED"> + <circle + r="32.057827" + cy="436.18585" + cx="747.05347" + id="path1380" + style="fill:#ececec;fill-opacity:1;stroke:#ff0000;stroke-width:2.95733476;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + y="286.18585" + x="597.05353" + height="300" + width="300" + id="rect1382" + style="opacity:0;fill:#ececec;fill-opacity:1;stroke:none;stroke-width:3.69000006;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="sssssss" + inkscape:connector-curvature="0" + id="path1388" + d="m 719.75481,403.83452 c 1.9692,9.54564 9.417,-4.37059 26.6751,-4.06174 27.2477,0.48762 30.0401,21.24497 35.5749,12.81174 6.6594,-10.14673 12.6699,-22.7446 14.75,-33.25 13.5509,-68.43783 -46.4736,-97.18589 -72,-91.49999 -40.88858,9.10778 -49.54078,47.21136 -31.99998,71.75 13.16428,18.41615 23.37448,26.67508 26.99998,44.24999 z" + style="fill:#fd0000;fill-opacity:1;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="sssssss" + inkscape:connector-curvature="0" + id="path1388-9" + d="m 789.45321,432.25975 c -8.9783,-3.79302 -1.7422,10.23457 -11.7862,24.27224 -15.8577,22.16324 -34.5364,12.68834 -30.7308,22.03024 4.5788,11.24 11.5443,23.3361 19.0162,31.0083 48.6752,49.9808 106.3992,16.8549 116.1963,-7.3926 15.6932,-38.84015 -10.7791,-67.57972 -40.9378,-67.05341 -22.634,0.39495 -35.2273,4.11873 -51.7577,-2.86477 z" + style="fill:#fd0000;fill-opacity:1;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="sssssss" + inkscape:connector-curvature="0" + id="path1388-9-8" + d="m 730.85671,475.85643 c 7.5732,-6.1355 -8.2092,-6.3552 -15.8654,-21.82523 -12.0882,-24.42445 5.0646,-36.44319 -4.9688,-37.48364 -12.07218,-1.25186 -26.02318,-0.80116 -36.30958,2.17903 -67.0109,19.41388 -64.9607,85.93594 -48.1806,105.99474 26.8787,32.1304 64.6969,22.3051 78.43058,-4.5502 10.3071,-20.1549 12.9505,-33.0184 26.8938,-44.3147 z" + style="fill:#fd0000;fill-opacity:1;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <animateTransform + attributeName="transform" + attributeType="XML" + type="rotate" + from="0 1049 278" + to="360 1049 278" + dur="1s" + repeatCount="indefinite" /> + </g> + <g + id="g1093" + inkscape:label="HMI:CustomHtml"> + <rect + inkscape:label="container" + y="12" + x="818" + height="323" + width="452" + id="rect1072" + style="opacity:0.29800002;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1.11057007" /> + <text + inkscape:label="code" + transform="scale(0.57360572,1.7433578)" + id="text1076" + y="23.059681" + x="1433.04" + style="font-style:normal;font-weight:normal;font-size:9.29032898px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.87096828px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + style="stroke-width:0.87096828px" + id="tspan1078" + y="23.059681" + x="1433.04" + sodipodi:role="line"> <img xmlns="http://www.w3.org/1999/xhtml" id="img" src="https://thumbs.gfycat.com/ImpoliteSoupyKakapo-size_restricted.gif" width="100%" height="80%" /></tspan><tspan + style="stroke-width:0.87096828px" + id="tspan1080" + y="34.672592" + x="1433.04" + sodipodi:role="line"> <a xmlns="http://www.w3.org/1999/xhtml" href='www.gmail.com'>Gmail</a></tspan><tspan + style="stroke-width:0.87096828px" + id="tspan1082" + y="46.285503" + x="1433.04" + sodipodi:role="line"> <p xmlns="http://www.w3.org/1999/xhtml">Koj kurac to ne dela</p></tspan><tspan + style="stroke-width:0.87096828px" + id="tspan1084" + y="57.898415" + x="1433.04" + sodipodi:role="line" /></text> + </g> </svg>