# HG changeset patch # User Edouard Tisserant # Date 1597051806 -7200 # Node ID 22b969b409b033ab0f6862f865dcfd11f39edfcc # Parent dabad70db1bfec5b4afdeef1ee821d974f1d0163# Parent 085a678715d04247f413d33392aebee63d418279 Merge diff -r dabad70db1bf -r 22b969b409b0 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Thu Aug 06 15:01:01 2020 +0200 +++ b/svghmi/gen_index_xhtml.xslt Mon Aug 10 11:30:06 2020 +0200 @@ -1,5 +1,5 @@ - + @@ -14,7 +14,7 @@ - + @@ -62,7 +62,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -113,14 +113,14 @@ - + - + @@ -184,7 +184,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -235,18 +235,18 @@ Raw HMI tree - + Indexed HMI tree - + Parsed Widgets - + @@ -459,7 +459,7 @@ - + @@ -559,7 +559,7 @@ } - + } @@ -583,13 +583,13 @@ var page_desc = { - + } - + @@ -621,16 +621,16 @@ - + - + - - - + + + none @@ -641,15 +641,15 @@ 100vw - + - + ViewBox settings other than X=0, Y=0 and Scale=1 are not supported - + All units must be set to "px" in Inkscape's document properties @@ -658,7 +658,7 @@ - + @@ -668,7 +668,7 @@ - + @@ -729,7 +729,7 @@ - + @@ -739,14 +739,14 @@ - + - + @@ -754,10 +754,10 @@ - + - + @@ -769,7 +769,7 @@ - + @@ -777,7 +777,7 @@ - + @@ -828,7 +828,7 @@ - + @@ -876,7 +876,7 @@ ],{ - + }) @@ -1107,11 +1107,11 @@ - - - - - + + + + + class Widget extends Widget{ @@ -1137,7 +1137,7 @@ var hmi_widgets = { - + } @@ -1231,7 +1231,7 @@ - + class BackWidget extends Widget{ on_click(evt) { @@ -1257,7 +1257,81 @@ } - + + t{ + + 5; + + 0; + + d; + + d; + + + + { + + { + + ); + + ); + + } + + ); + + } + + + + { + + { + + ); + + ); + + } + + ); + + } + + + + { + + d; + + d; + + + + { + + ); + + ); + + } + + + + ); + + ); + + } + + } + + || + + + @@ -1266,66 +1340,10 @@ - frequency: 5, - - on_mouse_down: function(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); - - }, - - on_mouse_up: function(evt) { - - 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); - - }, - - active_style: undefined, - - inactive_style: undefined, - - init: function() { - - 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("onmousedown", "hmi_widgets[' - - '].on_mouse_down(evt)"); - - this.element.setAttribute("onmouseup", "hmi_widgets[' - - '].on_mouse_up(evt)"); - - }, - - - + + + + frequency: 10, @@ -1421,7 +1439,321 @@ }, - + + class CircularSliderWidget extends Widget{ + + frequency = 5; + + range = undefined; + + circle = undefined; + + handle_pos = undefined; + + drag = false; + + enTimer = false; + + + + dispatch(value) { + + if(!this.drag){ + + if(this.value_elt) + + this.value_elt.textContent = String(value); + + + + this.handle_position(value); + + } + + } + + + + handle_position(value){ + + let [min,max,totalDistance] = this.range; + + let length = Math.max(0,Math.min((totalDistance),(Number(value)-min)/(max-min)*(totalDistance))); + + let tip = this.range_elt.getPointAtLength(length); + + this.handle_elt.setAttribute('transform',"translate("+(tip.x-this.handle_pos.x)+","+(tip.y-this.handle_pos.y)+")"); + + } + + + + on_release(evt) { + + if(this.drag){ + + this.drag = false; + + } + + } + + + + update_position(evt){ + + if(this.drag && this.enTimer){ + + var svg_dist = 0; + + + + //calculate center of widget in html + + // --TODO maybe it would be better to bind this part to window change size event ??? + + let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; + + let [cX, cY,fiStart,fiEnd,minMax,x1,y1,width,height] = this.circle; + + let htmlCirc = this.range_elt.getBoundingClientRect(); + + let cxHtml = ((htmlCirc.right-htmlCirc.left)/(width)*(cX-x1))+htmlCirc.left; + + let cyHtml = ((htmlCirc.bottom-htmlCirc.top)/(height)*(cY-y1))+htmlCirc.top; + + + + + + //get mouse coordinates + + let mouseX = undefined; + + let 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; + + } + + + + //calculate angle + + let fi = Math.atan2(cyHtml-mouseY, mouseX-cxHtml); + + + + // transform from 0 to 2PI + + if (fi > 0){ + + fi = 2*Math.PI-fi; + + } + + else{ + + fi = -fi; + + } + + + + //offset it to 0 + + fi = fi - fiStart; + + if (fi < 0){ + + fi = fi + 2*Math.PI; + + } + + + + //get handle distance from mouse position + + if(fi<fiEnd){ + + svg_dist=(fi)/(fiEnd)*(this.range[1]-this.range[0]); + + } + + else if(fiEnd<fi && fi<fiEnd+minMax){ + + svg_dist = this.range[1]; + + } + + else{ + + svg_dist = this.range[0]; + + } + + + + //redraw handle --TODO is it fast enough if I just call change_hmi_value??? + + this.handle_position(svg_dist); + + if(this.value_elt) + + this.value_elt.textContent = String(Math.ceil(svg_dist)); + + change_hmi_value(this.indexes[0], "="+Math.ceil(svg_dist)); + + + + //reset timer + + this.enTimer = false; + + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); + + } + + + + } + + + + on_select(evt){ + + this.drag = true; + + this.enTimer = true; + + this.update_position(evt); + + } + + + + init() { + + //get min max + + let min = this.min_elt ? + + Number(this.min_elt.textContent) : + + this.args.length >= 1 ? this.args[0] : 0; + + let max = this.max_elt ? + + Number(this.max_elt.textContent) : + + this.args.length >= 2 ? this.args[1] : 100; + + + + //fiStart ==> offset + + let fiStart = Number(this.range_elt.getAttribute('sodipodi:start')); + + let fiEnd = Number(this.range_elt.getAttribute('sodipodi:end')); + + fiEnd = fiEnd - fiStart; + + + + //fiEnd ==> size of angle + + if (fiEnd < 0){ + + fiEnd = 2*Math.PI + fiEnd; + + } + + + + //min max barrier angle + + let minMax = (2*Math.PI - fiEnd)/2; + + + + //get parameters from svg + + let cX = Number(this.range_elt.getAttribute('sodipodi:cx')); + + let cY = Number(this.range_elt.getAttribute('sodipodi:cy')); + + this.range_elt.style.strokeMiterlimit="0"; //eliminates some weird border around html object + + this.range = [min, max,this.range_elt.getTotalLength()]; + + let cPos = this.range_elt.getBBox(); + + this.handle_pos = this.range_elt.getPointAtLength(0); + + this.circle = [cX, cY,fiStart,fiEnd,minMax,cPos.x,cPos.y,cPos.width,cPos.height]; + + + + //init events + + 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)); + + + + 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)); + + + + } + + } + + + + + + + + handle range + + + + + + value min max + + + + + + + class DisplayWidget extends Widget{ frequency = 5; @@ -1439,7 +1771,7 @@ } - + @@ -1930,7 +2262,7 @@ - + @@ -2443,7 +2775,7 @@ }, - + @@ -2557,7 +2889,7 @@ item_offset: 0, - + class ForEachWidget extends Widget{ @@ -2693,8 +3025,15 @@ } - + + + + + key_pos + + + @@ -2753,11 +3092,13 @@ on_edit_click: function(opstr) { + var size = (typeof this.key_pos_elt !== 'undefined') ? this.key_pos_elt.getBBox() : undefined + edit_value(" ", " - ", this, this.last_val); + ", this, this.last_val,size); }, @@ -2768,7 +3109,7 @@ }, - + class JsonTableWidget extends Widget{ do_http_request() { @@ -2828,14 +3169,14 @@ } - + JsonTable Widget can't contain element of type . - + @@ -2846,14 +3187,6 @@ " is not valid. - console.log(" - - ", " - - ", - - ); - id(" ").setAttribute("xlink:href", @@ -2865,16 +3198,8 @@ ]); - + - console.log(" - - ", " - - ", - - ); - id(" ").textContent = String( @@ -2882,16 +3207,16 @@ ); - + - + - + let obj_ @@ -2900,14 +3225,14 @@ ; - + obj_ - + @@ -2925,9 +3250,7 @@ spread_json_data: function(jdata) { - console.log(jdata); - - + } @@ -2953,7 +3276,7 @@ - + @@ -3088,7 +3411,7 @@ }, - + @@ -3190,7 +3513,299 @@ - + + class KeypadWidget extends Widget{ + + moving = undefined; + + enTimer = undefined; + + offset = undefined; + + + + on_position_click(evt) { + + this.moving = true; + + this.enTimer = true; + + + + // get click position offset from widget x,y and save it to variable + + var keypad_borders = this.position_elt.getBoundingClientRect(); + + var clickX = undefined; + + var clickY = undefined; + + if (evt.type == "touchstart"){ + + clickX = Math.ceil(evt.touches[0].clientX); + + clickY = Math.ceil(evt.touches[0].clientY); + + } + + else{ + + clickX = evt.pageX; + + clickY = evt.pageY; + + } + + this.offset=[clickX-keypad_borders.left,clickY-keypad_borders.top] + + } + + + + off_position_click(evt) { + + if(this.moving) + + this.moving = false; + + } + + + + on_move(evt) { + + if(this.moving && this.enTimer){ + + //get keyboard pos in html + + let [eltid, tmpgrp] = current_modal; + + let [xcoord,ycoord] = this.coordinates; + + let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; + + + + //get mouse coordinates + + var clickX = undefined; + + var clickY = undefined; + + if (evt.type == "touchmove"){ + + clickX = Math.ceil(evt.touches[0].clientX); + + clickY = Math.ceil(evt.touches[0].clientY); + + } + + else{ + + clickX = evt.pageX; + + clickY = evt.pageY; + + } + + + + //translate keyboard position + + let mouseX = ((clickX-this.offset[0])/window.innerWidth)*svgWidth; + + let mouseY = ((clickY-this.offset[1])/window.innerHeight)*svgHeight; + + tmpgrp.setAttribute("transform","translate("+String(xdest-xcoord+mouseX)+","+String(ydest-ycoord+mouseY)+")"); + + + + //reset timer + + this.enTimer = false; + + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); + + } + + + + } + + + + on_key_click(symbols) { + + var syms = symbols.split(" "); + + this.shift |= this.caps; + + this.editstr += syms[this.shift?syms.length-1:0]; + + this.shift = false; + + this.update(); + + } + + + + on_Esc_click() { + + end_modal.call(this); + + } + + + + on_Enter_click() { + + end_modal.call(this); + + let callback_obj = this.result_callback_obj; + + callback_obj.edit_callback(this.editstr); + + } + + + + on_BackSpace_click() { + + this.editstr = this.editstr.slice(0,this.editstr.length-1); + + this.update(); + + } + + + + on_Sign_click() { + + if(this.editstr[0] == "-") + + this.editstr = this.editstr.slice(1,this.editstr.length); + + else + + this.editstr = "-" + this.editstr; + + this.update(); + + } + + + + on_NumDot_click() { + + if(this.editstr.indexOf(".") == "-1"){ + + this.editstr += "."; + + this.update(); + + } + + } + + + + on_Space_click() { + + this.editstr += " "; + + this.update(); + + } + + + + caps = false; + + _caps = undefined; + + on_CapsLock_click() { + + this.caps = !this.caps; + + this.update(); + + } + + + + shift = false; + + _shift = undefined; + + on_Shift_click() { + + this.shift = !this.shift; + + this.caps = false; + + this.update(); + + } + + editstr = ""; + + _editstr = undefined; + + result_callback_obj = undefined; + + start_edit(info, valuetype, callback_obj, initial,size) { + + show_modal.call(this,size); + + this.editstr = initial; + + this.result_callback_obj = callback_obj; + + this.Info_elt.textContent = info; + + this.shift = false; + + this.caps = false; + + this.update(); + + } + + + + update() { + + if(this.editstr != this._editstr){ + + this._editstr = this.editstr; + + this.Value_elt.textContent = this.editstr; + + } + + if(this.shift != this._shift){ + + this._shift = this.shift; + + (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); + + } + + if(this.caps != this._caps){ + + this._caps = this.caps; + + (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); + + } + + } + + } + + + @@ -3201,7 +3816,7 @@ - Sign Space NumDot + Sign Space NumDot position @@ -3239,105 +3854,27 @@ _click()"); + if(this.position_elt){ + + this.position_elt.setAttribute("onmousedown", "hmi_widgets['"+this.element_id+"'].on_position_click(evt)"); + + this.position_elt.setAttribute("ontouchstart", "hmi_widgets['"+this.element_id+"'].on_position_click(evt)"); + + window.addEventListener("mouseup", hmi_widgets[this.element_id].off_position_click.bind(this)); + + window.addEventListener("touchend", hmi_widgets[this.element_id].off_position_click.bind(this)); + + window.addEventListener("touchcancel", hmi_widgets[this.element_id].off_position_click.bind(this)); + + window.addEventListener("mousemove", hmi_widgets[this.element_id].on_move.bind(this)); + + window.addEventListener("touchmove", hmi_widgets[this.element_id].on_move.bind(this)); + + } + }, - on_key_click: function(symbols) { - - var syms = symbols.split(" "); - - this.shift |= this.caps; - - this.editstr += syms[this.shift?syms.length-1:0]; - - this.shift = false; - - this.update(); - - }, - - on_Esc_click: function() { - - end_modal.call(this); - - }, - - on_Enter_click: function() { - - end_modal.call(this); - - callback_obj = this.result_callback_obj; - - callback_obj.edit_callback(this.editstr); - - }, - - on_BackSpace_click: function() { - - this.editstr = this.editstr.slice(0,this.editstr.length-1); - - this.update(); - - }, - - on_Sign_click: function() { - - if(this.editstr[0] == "-") - - this.editstr = this.editstr.slice(1,this.editstr.length); - - else - - this.editstr = "-" + this.editstr; - - this.update(); - - }, - - on_NumDot_click: function() { - - if(this.editstr.indexOf(".") == "-1"){ - - this.editstr += "."; - - this.update(); - - } - - }, - - on_Space_click: function() { - - this.editstr += " "; - - this.update(); - - }, - - caps: false, - - _caps: undefined, - - on_CapsLock_click: function() { - - this.caps = !this.caps; - - this.update(); - - }, - - shift: false, - - _shift: undefined, - - on_Shift_click: function() { - - this.shift = !this.shift; - - this.caps = false; - - this.update(); - - }, + coordinates: [ @@ -3346,60 +3883,8 @@ ], - editstr: "", - - _editstr: undefined, - - result_callback_obj: undefined, - - start_edit: function(info, valuetype, callback_obj, initial) { - - show_modal.call(this); - - this.editstr = initial; - - this.result_callback_obj = callback_obj; - - this.Info_elt.textContent = info; - - this.shift = false; - - this.caps = false; - - this.update(); - - }, - - update: function() { - - if(this.editstr != this._editstr){ - - this._editstr = this.editstr; - - this.Value_elt.textContent = this.editstr; - - } - - if(this.shift != this._shift){ - - this._shift = this.shift; - - (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); - - } - - if(this.caps != this._caps){ - - this._caps = this.caps; - - (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); - - } - - }, - - - + + items: { @@ -3414,7 +3899,7 @@ }, - + frequency: 10, @@ -3472,16 +3957,20 @@ }, - - class SwitchWidget extends Widget{ + + class MultiStateWidget extends Widget{ frequency = 5; + state = 0; + dispatch(value) { + this.state = value; + for(let choice of this.choices){ - if(value != choice.value){ + if(this.state != choice.value){ choice.elt.setAttribute("style", "display:none"); @@ -3495,10 +3984,62 @@ } + + + on_click(evt) { + + //get current selected value + + let next_ind; + + for(next_ind=0; next_ind<this.choices.length; next_ind++){ + + if(this.state == this.choices[next_ind].value){ + + next_ind = next_ind + 1; + + break; + + } + + } + + + + //get next selected value + + if(this.choices.length > next_ind){ + + this.state = this.choices[next_ind].value; + + } + + else{ + + this.state = this.choices[0].value; + + } + + + + //post value to plc + + change_hmi_value(this.indexes[0], "="+this.state); + + } + + + + init() { + + this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)"); + + } + } - + choices: [ @@ -3529,7 +4070,382 @@ ], - + + class SliderWidget extends Widget{ + + frequency = 5; + + range = undefined; + + fi = undefined; + + drag = false; + + enTimer = false; + + + + dispatch(value) { + + if(!this.drag){ + + if(this.value_elt) + + this.value_elt.textContent = String(value); + + + + this.handle_position(value); + + } + + } + + + + handle_position(value){ + + 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)+")"); + + } + + + + on_release(evt) { + + if(this.drag){ + + this.drag = false; + + } + + } + + + + update_position(evt){ + + if(this.drag && this.enTimer){ + + var html_dist = 0; + + var svg_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]; + + + + //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{ + + 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; + + } + + } + + //redraw handle + + this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]); + + this.value_elt.textContent = String(Math.ceil(svg_dist)); + + change_hmi_value(this.indexes[0], "="+Math.ceil(svg_dist)); + + //reset timer + + this.enTimer = false; + + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); + + } + + + + } + + + + on_select(evt){ + + this.drag = true; + + this.enTimer = true; + + this.update_position(evt); + + } + + + + init() { + + let min = this.min_elt ? + + Number(this.min_elt.textContent) : + + this.args.length >= 1 ? this.args[0] : 0; + + let max = this.max_elt ? + + Number(this.max_elt.textContent) : + + this.args.length >= 2 ? this.args[1] : 100; + + + + this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()]; + + let start = this.range_elt.getPointAtLength(0); + + 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)); + + + + 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)); + + + + } + + } + + + + + + + + handle range + + + + + + value min max + + + + + + + + class SwitchWidget extends Widget{ + + frequency = 5; + + dispatch(value) { + + for(let choice of this.choices){ + + if(value != choice.value){ + + choice.elt.setAttribute("style", "display:none"); + + } else { + + choice.elt.setAttribute("style", choice.style); + + } + + } + + } + + } + + + + + choices: [ + + + + + { + + elt:id(" + + "), + + style:" + + ", + + value: + + + + } + + , + + + + + ], + + + + class ToggleButtonWidget extends Widget{ + + frequency = 5; + + state = 0; + + active_style = undefined; + + inactive_style = undefined; + + + + dispatch(value) { + + this.state = value; + + if (this.state) { + + this.active_elt.setAttribute("style", this.active_style); + + this.inactive_elt.setAttribute("style", "display:none"); + + this.state = 0; + + } else { + + this.inactive_elt.setAttribute("style", this.inactive_style); + + this.active_elt.setAttribute("style", "display:none"); + + this.state = 1; + + } + + } + + + + on_click(evt) { + + change_hmi_value(this.indexes[0], "="+this.state); + + } + + + + init() { + + this.active_style = this.active_elt.style.cssText; + + this.inactive_style = this.inactive_elt.style.cssText; + + this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)"); + + } + + } + + + @@ -3537,55 +4453,7 @@ active inactive - frequency: 5, - - state: 0, - - dispatch: function(value) { - - this.state = value; - - if (this.state) { - - this.active_elt.setAttribute("style", this.active_style); - - this.inactive_elt.setAttribute("style", "display:none"); - - this.state = 0; - - } else { - - this.inactive_elt.setAttribute("style", this.inactive_style); - - this.active_elt.setAttribute("style", "display:none"); - - this.state = 1; - - } - - }, - - on_click: function(evt) { - - this.apply_hmi_value(0, this.state); - - }, - - active_style: undefined, - - inactive_style: undefined, - - init: function() { - - this.active_style = this.active_elt.style.cssText; - - this.inactive_style = this.inactive_elt.style.cssText; - - this.element.setAttribute("onclick", "hmi_widgets[' - - '].on_click(evt)"); - - }, + @@ -3595,7 +4463,7 @@ - + @@ -4384,7 +5252,7 @@ var edit_callback; - function edit_value(path, valuetype, callback, initial) { + function edit_value(path, valuetype, callback, initial,size) { @@ -4396,7 +5264,7 @@ let widget = hmi_widgets[keypadid]; - widget.start_edit(path, valuetype, callback, initial); + widget.start_edit(path, valuetype, callback, initial,size); }; @@ -4406,7 +5274,7 @@ - function show_modal() { + function show_modal(size) { let [element, parent] = detachable_elements[this.element.id]; @@ -4416,13 +5284,23 @@ tmpgrpattr = document.createAttribute("transform"); - - let [xcoord,ycoord] = this.coordinates; let [xdest,ydest] = page_desc[current_visible_page].bbox; - tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")"; + if (typeof size === 'undefined'){ + + tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")"; + + } + + else{ + + tmpgrpattr.value = "translate("+String(xdest-xcoord+size.x)+","+String(ydest-ycoord+size.y)+")"; + + } + + tmpgrp.setAttributeNode(tmpgrpattr); diff -r dabad70db1bf -r 22b969b409b0 svghmi/svghmi.js --- a/svghmi/svghmi.js Thu Aug 06 15:01:01 2020 +0200 +++ b/svghmi/svghmi.js Mon Aug 10 11:30:06 2020 +0200 @@ -374,26 +374,31 @@ var xmlns = "http://www.w3.org/2000/svg"; var edit_callback; -function edit_value(path, valuetype, callback, initial) { +function edit_value(path, valuetype, callback, initial, size) { let [keypadid, xcoord, ycoord] = keypads[valuetype]; console.log('XXX TODO : Edit value', path, valuetype, callback, initial, keypadid); edit_callback = callback; let widget = hmi_widgets[keypadid]; - widget.start_edit(path, valuetype, callback, initial); + widget.start_edit(path, valuetype, callback, initial, size); }; var current_modal; /* TODO stack ?*/ -function show_modal() { +function show_modal(size) { let [element, parent] = detachable_elements[this.element.id]; tmpgrp = document.createElementNS(xmlns,"g"); tmpgrpattr = document.createAttribute("transform"); - let [xcoord,ycoord] = this.coordinates; let [xdest,ydest] = page_desc[current_visible_page].bbox; - tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")"; + if (typeof size === 'undefined'){ + tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")"; + } + else{ + tmpgrpattr.value = "translate("+String(xdest-xcoord+size.x)+","+String(ydest-ycoord+size.y)+")"; + } + tmpgrp.setAttributeNode(tmpgrpattr); tmpgrp.appendChild(element); diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_button.ysl2 --- a/svghmi/widget_button.ysl2 Thu Aug 06 15:01:01 2020 +0200 +++ b/svghmi/widget_button.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -1,33 +1,47 @@ // widget_button.ysl2 +template "widget[@type='Button']", mode="widget_class" + || + class ButtonWidget extends Widget{ + frequency = 5; + state = 0; + active_style = undefined; + inactive_style = undefined; + + 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); + } + + on_mouse_up(evt) { + 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); + } + + init() { + this.active_style = this.active_elt ? this.active_elt.style.cssText : undefined; + this.inactive_style = this.inactive_elt ? this.inactive_elt.style.cssText : undefined; + + if (this.active_style && this.inactive_style) { + this.active_elt.setAttribute("style", "display:none"); + this.inactive_elt.setAttribute("style", this.inactive_style); + } + + this.element.setAttribute("onmousedown", "hmi_widgets["+this.element_id+"].on_mouse_down(evt)"); + this.element.setAttribute("onmouseup", "hmi_widgets["+this.element_id+"].on_mouse_up(evt)"); + } + } + || + + template "widget[@type='Button']", mode="widget_defs" { param "hmi_element"; optional_labels("active inactive"); - | frequency: 5, - | on_mouse_down: function(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); - | }, - | on_mouse_up: function(evt) { - | 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); - | }, - | active_style: undefined, - | inactive_style: undefined, - | init: function() { - | 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("onmousedown", "hmi_widgets['«$hmi_element/@id»'].on_mouse_down(evt)"); - | this.element.setAttribute("onmouseup", "hmi_widgets['«$hmi_element/@id»'].on_mouse_up(evt)"); - | }, + |, } diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_circularslider.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_circularslider.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,159 @@ +// widget_circuralslider.ysl2 + +template "widget[@type='CircularSlider']", mode="widget_class" + || + class CircularSliderWidget extends Widget{ + frequency = 5; + range = undefined; + circle = undefined; + handle_pos = undefined; + drag = false; + enTimer = false; + + dispatch(value) { + if(!this.drag){ + if(this.value_elt) + this.value_elt.textContent = String(value); + + this.handle_position(value); + } + } + + handle_position(value){ + let [min,max,totalDistance] = this.range; + let length = Math.max(0,Math.min((totalDistance),(Number(value)-min)/(max-min)*(totalDistance))); + let tip = this.range_elt.getPointAtLength(length); + this.handle_elt.setAttribute('transform',"translate("+(tip.x-this.handle_pos.x)+","+(tip.y-this.handle_pos.y)+")"); + } + + on_release(evt) { + if(this.drag){ + this.drag = false; + } + } + + update_position(evt){ + if(this.drag && this.enTimer){ + var svg_dist = 0; + + //calculate center of widget in html + // --TODO maybe it would be better to bind this part to window change size event ??? + let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; + let [cX, cY,fiStart,fiEnd,minMax,x1,y1,width,height] = this.circle; + let htmlCirc = this.range_elt.getBoundingClientRect(); + let cxHtml = ((htmlCirc.right-htmlCirc.left)/(width)*(cX-x1))+htmlCirc.left; + let cyHtml = ((htmlCirc.bottom-htmlCirc.top)/(height)*(cY-y1))+htmlCirc.top; + + + //get mouse coordinates + let mouseX = undefined; + let 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; + } + + //calculate angle + let fi = Math.atan2(cyHtml-mouseY, mouseX-cxHtml); + + // transform from 0 to 2PI + if (fi > 0){ + fi = 2*Math.PI-fi; + } + else{ + fi = -fi; + } + + //offset it to 0 + fi = fi - fiStart; + if (fi < 0){ + fi = fi + 2*Math.PI; + } + + //get handle distance from mouse position + if(fi= 1 ? this.args[0] : 0; + let max = this.max_elt ? + Number(this.max_elt.textContent) : + this.args.length >= 2 ? this.args[1] : 100; + + //fiStart ==> offset + let fiStart = Number(this.range_elt.getAttribute('sodipodi:start')); + let fiEnd = Number(this.range_elt.getAttribute('sodipodi:end')); + fiEnd = fiEnd - fiStart; + + //fiEnd ==> size of angle + if (fiEnd < 0){ + fiEnd = 2*Math.PI + fiEnd; + } + + //min max barrier angle + let minMax = (2*Math.PI - fiEnd)/2; + + //get parameters from svg + let cX = Number(this.range_elt.getAttribute('sodipodi:cx')); + let cY = Number(this.range_elt.getAttribute('sodipodi:cy')); + this.range_elt.style.strokeMiterlimit="0"; //eliminates some weird border around html object + this.range = [min, max,this.range_elt.getTotalLength()]; + let cPos = this.range_elt.getBBox(); + this.handle_pos = this.range_elt.getPointAtLength(0); + this.circle = [cX, cY,fiStart,fiEnd,minMax,cPos.x,cPos.y,cPos.width,cPos.height]; + + //init events + 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)); + + 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)); + + } + } + || + +template "widget[@type='CircularSlider']", mode="widget_defs" { + param "hmi_element"; + labels("handle range"); + optional_labels("value min max"); + |, +} diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_input.ysl2 --- a/svghmi/widget_input.ysl2 Thu Aug 06 15:01:01 2020 +0200 +++ b/svghmi/widget_input.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -2,6 +2,7 @@ template "widget[@type='Input']", mode="widget_defs" { param "hmi_element"; + optional_labels("key_pos"); const "value_elt" { optional_labels("value"); } @@ -33,7 +34,8 @@ // } | }, | on_edit_click: function(opstr) { - | edit_value("«path/@value»", "«path/@type»", this, this.last_val); + | var size = (typeof this.key_pos_elt !== 'undefined') ? this.key_pos_elt.getBBox() : undefined + | edit_value("«path/@value»", "«path/@type»", this, this.last_val,size); | }, | edit_callback: function(new_val) { diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_keypad.ysl2 --- a/svghmi/widget_keypad.ysl2 Thu Aug 06 15:01:01 2020 +0200 +++ b/svghmi/widget_keypad.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -13,10 +13,159 @@ | } } +template "widget[@type='Keypad']", mode="widget_class" + || + class KeypadWidget extends Widget{ + moving = undefined; + enTimer = undefined; + offset = undefined; + + on_position_click(evt) { + this.moving = true; + this.enTimer = true; + + // get click position offset from widget x,y and save it to variable + var keypad_borders = this.position_elt.getBoundingClientRect(); + var clickX = undefined; + var clickY = undefined; + if (evt.type == "touchstart"){ + clickX = Math.ceil(evt.touches[0].clientX); + clickY = Math.ceil(evt.touches[0].clientY); + } + else{ + clickX = evt.pageX; + clickY = evt.pageY; + } + this.offset=[clickX-keypad_borders.left,clickY-keypad_borders.top] + } + + off_position_click(evt) { + if(this.moving) + this.moving = false; + } + + on_move(evt) { + if(this.moving && this.enTimer){ + //get keyboard pos in html + let [eltid, tmpgrp] = current_modal; + let [xcoord,ycoord] = this.coordinates; + let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; + + //get mouse coordinates + var clickX = undefined; + var clickY = undefined; + if (evt.type == "touchmove"){ + clickX = Math.ceil(evt.touches[0].clientX); + clickY = Math.ceil(evt.touches[0].clientY); + } + else{ + clickX = evt.pageX; + clickY = evt.pageY; + } + + //translate keyboard position + let mouseX = ((clickX-this.offset[0])/window.innerWidth)*svgWidth; + let mouseY = ((clickY-this.offset[1])/window.innerHeight)*svgHeight; + tmpgrp.setAttribute("transform","translate("+String(xdest-xcoord+mouseX)+","+String(ydest-ycoord+mouseY)+")"); + + //reset timer + this.enTimer = false; + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); + } + + } + + on_key_click(symbols) { + var syms = symbols.split(" "); + this.shift |= this.caps; + this.editstr += syms[this.shift?syms.length-1:0]; + this.shift = false; + this.update(); + } + + on_Esc_click() { + end_modal.call(this); + } + + on_Enter_click() { + end_modal.call(this); + let callback_obj = this.result_callback_obj; + callback_obj.edit_callback(this.editstr); + } + + on_BackSpace_click() { + this.editstr = this.editstr.slice(0,this.editstr.length-1); + this.update(); + } + + on_Sign_click() { + if(this.editstr[0] == "-") + this.editstr = this.editstr.slice(1,this.editstr.length); + else + this.editstr = "-" + this.editstr; + this.update(); + } + + on_NumDot_click() { + if(this.editstr.indexOf(".") == "-1"){ + this.editstr += "."; + this.update(); + } + } + + on_Space_click() { + this.editstr += " "; + this.update(); + } + + caps = false; + _caps = undefined; + on_CapsLock_click() { + this.caps = !this.caps; + this.update(); + } + + shift = false; + _shift = undefined; + on_Shift_click() { + this.shift = !this.shift; + this.caps = false; + this.update(); + } + editstr = ""; + _editstr = undefined; + result_callback_obj = undefined; + start_edit(info, valuetype, callback_obj, initial,size) { + show_modal.call(this,size); + this.editstr = initial; + this.result_callback_obj = callback_obj; + this.Info_elt.textContent = info; + this.shift = false; + this.caps = false; + this.update(); + } + + update() { + if(this.editstr != this._editstr){ + this._editstr = this.editstr; + this.Value_elt.textContent = this.editstr; + } + if(this.shift != this._shift){ + this._shift = this.shift; + (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); + } + if(this.caps != this._caps){ + this._caps = this.caps; + (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); + } + } + } + || + template "widget[@type='Keypad']", mode="widget_defs" { param "hmi_element"; labels("Esc Enter BackSpace Keys Info Value"); - optional_labels("Sign Space NumDot"); + optional_labels("Sign Space NumDot position"); activable_labels("CapsLock Shift"); | init: function() { foreach "$hmi_element/*[@inkscape:label = 'Keys']/*" { @@ -26,82 +175,19 @@ | if(this.«.»_elt) | this.«.»_elt.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_«.»_click()"); } + | if(this.position_elt){ + | this.position_elt.setAttribute("onmousedown", "hmi_widgets['"+this.element_id+"'].on_position_click(evt)"); + | this.position_elt.setAttribute("ontouchstart", "hmi_widgets['"+this.element_id+"'].on_position_click(evt)"); + + | window.addEventListener("mouseup", hmi_widgets[this.element_id].off_position_click.bind(this)); + | window.addEventListener("touchend", hmi_widgets[this.element_id].off_position_click.bind(this)); + | window.addEventListener("touchcancel", hmi_widgets[this.element_id].off_position_click.bind(this)); + + | window.addEventListener("mousemove", hmi_widgets[this.element_id].on_move.bind(this)); + | window.addEventListener("touchmove", hmi_widgets[this.element_id].on_move.bind(this)); + | } | }, - | on_key_click: function(symbols) { - | var syms = symbols.split(" "); - | this.shift |= this.caps; - | this.editstr += syms[this.shift?syms.length-1:0]; - | this.shift = false; - | this.update(); - | }, - | on_Esc_click: function() { - | end_modal.call(this); - | }, - | on_Enter_click: function() { - | end_modal.call(this); - | callback_obj = this.result_callback_obj; - | callback_obj.edit_callback(this.editstr); - | }, - | on_BackSpace_click: function() { - | this.editstr = this.editstr.slice(0,this.editstr.length-1); - | this.update(); - | }, - | on_Sign_click: function() { - | if(this.editstr[0] == "-") - | this.editstr = this.editstr.slice(1,this.editstr.length); - | else - | this.editstr = "-" + this.editstr; - | this.update(); - | }, - | on_NumDot_click: function() { - | if(this.editstr.indexOf(".") == "-1"){ - | this.editstr += "."; - | this.update(); - | } - | }, - | on_Space_click: function() { - | this.editstr += " "; - | this.update(); - | }, - | caps: false, - | _caps: undefined, - | on_CapsLock_click: function() { - | this.caps = !this.caps; - | this.update(); - | }, - | shift: false, - | _shift: undefined, - | on_Shift_click: function() { - | this.shift = !this.shift; - | this.caps = false; - | this.update(); - | }, + | const "g", "$geometry[@Id = $hmi_element/@id]"; | coordinates: [«$g/@x», «$g/@y»], - | editstr: "", - | _editstr: undefined, - | result_callback_obj: undefined, - | start_edit: function(info, valuetype, callback_obj, initial) { - | show_modal.call(this); - | this.editstr = initial; - | this.result_callback_obj = callback_obj; - | this.Info_elt.textContent = info; - | this.shift = false; - | this.caps = false; - | this.update(); - | }, - | update: function() { - | if(this.editstr != this._editstr){ - | this._editstr = this.editstr; - | this.Value_elt.textContent = this.editstr; - | } - | if(this.shift != this._shift){ - | this._shift = this.shift; - | (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); - | } - | if(this.caps != this._caps){ - | this._caps = this.caps; - | (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); - | } - | }, } diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_multistate.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_multistate.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,60 @@ +// widget_multistate.ysl2 + +template "widget[@type='MultiState']", mode="widget_class" + || + class MultiStateWidget extends Widget{ + frequency = 5; + state = 0; + dispatch(value) { + this.state = value; + for(let choice of this.choices){ + if(this.state != choice.value){ + choice.elt.setAttribute("style", "display:none"); + } else { + choice.elt.setAttribute("style", choice.style); + } + } + } + + on_click(evt) { + //get current selected value + let next_ind; + for(next_ind=0; next_ind next_ind){ + this.state = this.choices[next_ind].value; + } + else{ + this.state = this.choices[0].value; + } + + //post value to plc + this.apply_hmi_value(0, this.state); + } + + init() { + this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)"); + } + } + || + +template "widget[@type='MultiState']", mode="widget_defs" { + param "hmi_element"; + | choices: [ + const "regex",!"'^(\"[^\"].*\"|\-?[0-9]+|false|true)(#.*)?$'"!; + foreach "$result_svg_ns//*[@id = $hmi_element/@id]//*[regexp:test(@inkscape:label,$regex)]" { + const "literal", "regexp:match(@inkscape:label,$regex)[2]"; + | { + | elt:id("«@id»"), + | style:"«@style»", + | value:«$literal» + | }`if "position()!=last()" > ,` + } + | ], +} diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_slider.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/widget_slider.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,131 @@ +// widget_slider.ysl2 + +template "widget[@type='Slider']", mode="widget_class" + || + class SliderWidget extends Widget{ + frequency = 5; + range = undefined; + fi = undefined; + drag = false; + enTimer = false; + + dispatch(value) { + if(!this.drag){ + if(this.value_elt) + this.value_elt.textContent = String(value); + + this.handle_position(value); + } + } + + handle_position(value){ + 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)+")"); + } + + on_release(evt) { + if(this.drag){ + this.drag = false; + } + } + + update_position(evt){ + if(this.drag && this.enTimer){ + var html_dist = 0; + var svg_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]; + + //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{ + 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; + } + } + //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, Math.ceil(svg_dist)); + //reset timer + this.enTimer = false; + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); + } + + } + + on_select(evt){ + this.drag = true; + this.enTimer = true; + this.update_position(evt); + } + + init() { + let min = this.min_elt ? + Number(this.min_elt.textContent) : + this.args.length >= 1 ? this.args[0] : 0; + let max = this.max_elt ? + Number(this.max_elt.textContent) : + this.args.length >= 2 ? this.args[1] : 100; + + this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()]; + let start = this.range_elt.getPointAtLength(0); + 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)); + + 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)); + + } + } + || + +template "widget[@type='Slider']", mode="widget_defs" { + param "hmi_element"; + labels("handle range"); + optional_labels("value min max"); + |, +} diff -r dabad70db1bf -r 22b969b409b0 svghmi/widget_tooglebutton.ysl2 --- a/svghmi/widget_tooglebutton.ysl2 Thu Aug 06 15:01:01 2020 +0200 +++ b/svghmi/widget_tooglebutton.ysl2 Mon Aug 10 11:30:06 2020 +0200 @@ -1,30 +1,41 @@ // widget_tooglebutton.ysl2 + +template "widget[@type='ToggleButton']", mode="widget_class" + || + class ToggleButtonWidget extends Widget{ + frequency = 5; + state = 0; + active_style = undefined; + inactive_style = undefined; + + dispatch(value) { + this.state = value; + if (this.state) { + this.active_elt.setAttribute("style", this.active_style); + this.inactive_elt.setAttribute("style", "display:none"); + this.state = 0; + } else { + this.inactive_elt.setAttribute("style", this.inactive_style); + this.active_elt.setAttribute("style", "display:none"); + this.state = 1; + } + } + + on_click(evt) { + this.apply_hmi_value(0, this.state); + } + + init() { + this.active_style = this.active_elt.style.cssText; + this.inactive_style = this.inactive_elt.style.cssText; + this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)"); + } + } + || + template "widget[@type='ToggleButton']", mode="widget_defs" { param "hmi_element"; labels("active inactive"); - | frequency: 5, - | state: 0, - | dispatch: function(value) { - | this.state = value; - | if (this.state) { - | this.active_elt.setAttribute("style", this.active_style); - | this.inactive_elt.setAttribute("style", "display:none"); - | this.state = 0; - | } else { - | this.inactive_elt.setAttribute("style", this.inactive_style); - | this.active_elt.setAttribute("style", "display:none"); - | this.state = 1; - | } - | }, - | on_click: function(evt) { - | this.apply_hmi_value(0, this.state); - | }, - | active_style: undefined, - | inactive_style: undefined, - | init: function() { - | this.active_style = this.active_elt.style.cssText; - | this.inactive_style = this.inactive_elt.style.cssText; - | this.element.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_click(evt)"); - | }, + |, } diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/beremiz.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/beremiz.xml Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,5 @@ + + + + + diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/plc.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/plc.xml Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,578 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TargetPressure + + + + + + + TestButton + + + + + + + + + + + TestLocal + + + + + + + Multistate + + + + + + + + + + + MultistateExt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TargetPressure + + + + + + + + + + + + + + Sloth + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pressure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sloth + + + + + + + + + + + Pressure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + strout + + + + + + + TargetPressure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + strin + + + + + + + boolin + + + + + + + + + + + boolout + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pressure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/py_ext_0@py_ext/baseconfnode.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/py_ext_0@py_ext/baseconfnode.xml Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,2 @@ + + diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/py_ext_0@py_ext/pyfile.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/py_ext_0@py_ext/pyfile.xml Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/svghmi_0@svghmi/baseconfnode.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/svghmi_0@svghmi/baseconfnode.xml Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,2 @@ + + diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/svghmi_0@svghmi/confnode.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/svghmi_0@svghmi/confnode.xml Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,2 @@ + + diff -r dabad70db1bf -r 22b969b409b0 tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svghmi_v2/svghmi_0@svghmi/svghmi.svg Mon Aug 10 11:30:06 2020 +0200 @@ -0,0 +1,1467 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 100 + 000 + + + Test + + + + + + + + + + Q + + + + W + + + + E + + + + R + + + + T + + + + Y + + + + U + + + + I + + + + O + + + + P + + + + A + + + + S + + + + D + + + + F + + + + G + + + + H + + + + J + + + + K + + + + L + + + + Z + + + + X + + + + C + + + + V + + + + B + + + + N + + + + M + + + + . + : + + + + ; + , + + + + 1 + + + + 2 + + + + 3 + + + + 4 + + + + 5 + + + + 6 + + + + 7 + + + + 8 + + + + 9 + - + + + + 0 + + + + + + + Esc + + + + + + + + + + + + + Caps + Lock + + + + Caps + Lock + + + + text + + + + Shift + + Shift + + + + Shift + + Shift + + + information + + + + + 0 + 100 + 000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 000 + + + + + + + + + + + + + 000 + +