usveticic@3013: // widget_circuralslider.ysl2 usveticic@3013: edouard@3241: widget_desc("CircularSlider") { edouard@3241: longdesc edouard@3241: || edouard@3241: CircularSlider - DEPRECATED, to be replaced by PathSlider edouard@3241: This widget moves "handle" labeled group along "range" labeled edouard@3241: arc, according to value of the single accepted variable. edouard@3241: edouard@3241: If "min" a "max" labeled texts are provided, or if first and second edouard@3241: argument are given, then they are used as respective minimum and maximum edouard@3241: value. Otherwise, value is expected to be in between 0 and 100. edouard@3241: edouard@3241: If "value" labeled text is found, then its content is replaced by value. edouard@3241: During drag, "setpoint" labeled group is moved to position defined by user edouard@3241: while "handle" reflects current value from variable. edouard@3241: || edouard@3241: edouard@3241: shortdesc > CircularSlider - DEPRECATED edouard@3241: edouard@3241: arg name="min" count="optional" accepts="int,real" > minimum value edouard@3241: edouard@3241: arg name="min" count="optional" accepts="int,real" > maximum value edouard@3241: edouard@3241: // TODO: add printf-like format edouard@3241: edouard@3241: path name="value" accepts="HMI_INT,HMI_REAL" > Value to display edouard@3241: edouard@3241: } edouard@3241: edouard@3232: widget_class("CircularSlider") usveticic@3013: || usveticic@3013: frequency = 5; usveticic@3013: range = undefined; usveticic@3013: circle = undefined; usveticic@3013: handle_pos = undefined; usveticic@3062: curr_value = 0; usveticic@3013: drag = false; usveticic@3013: enTimer = false; usveticic@3045: last_drag = false; usveticic@3013: usveticic@3013: dispatch(value) { usveticic@3062: let [min,max,start,totallength] = this.range; usveticic@3062: //save current value inside widget usveticic@3062: this.curr_value = value; usveticic@3062: usveticic@3062: //check if in range usveticic@3062: if (this.curr_value > max){ usveticic@3062: this.curr_value = max; usveticic@3062: this.apply_hmi_value(0, this.curr_value); usveticic@3062: } usveticic@3062: else if (this.curr_value < min){ usveticic@3062: this.curr_value = min; usveticic@3062: this.apply_hmi_value(0, this.curr_value); usveticic@3062: } usveticic@3062: usveticic@3045: if(this.value_elt) usveticic@3045: this.value_elt.textContent = String(value); usveticic@3045: usveticic@3062: //don't update if draging and setpoint ghost doesn't exist usveticic@3062: if(!this.drag || (this.setpoint_elt != undefined)){ usveticic@3062: this.update_DOM(value, this.handle_elt); usveticic@3062: } usveticic@3045: } usveticic@3045: usveticic@3045: update_DOM(value, elt){ usveticic@3013: let [min,max,totalDistance] = this.range; usveticic@3013: let length = Math.max(0,Math.min((totalDistance),(Number(value)-min)/(max-min)*(totalDistance))); usveticic@3013: let tip = this.range_elt.getPointAtLength(length); usveticic@3045: elt.setAttribute('transform',"translate("+(tip.x-this.handle_pos.x)+","+(tip.y-this.handle_pos.y)+")"); usveticic@3045: usveticic@3062: // show or hide ghost if exists usveticic@3045: if(this.setpoint_elt != undefined){ usveticic@3045: if(this.last_drag!= this.drag){ usveticic@3045: if(this.drag){ usveticic@3045: this.setpoint_elt.setAttribute("style", this.setpoint_style); usveticic@3045: }else{ usveticic@3045: this.setpoint_elt.setAttribute("style", "display:none"); usveticic@3045: } usveticic@3045: this.last_drag = this.drag; usveticic@3045: } usveticic@3045: } usveticic@3013: } usveticic@3013: usveticic@3013: on_release(evt) { usveticic@3062: //unbind events usveticic@3045: window.removeEventListener("touchmove", this.on_bound_drag, true); usveticic@3045: window.removeEventListener("mousemove", this.on_bound_drag, true); usveticic@3045: usveticic@3045: window.removeEventListener("mouseup", this.bound_on_release, true) usveticic@3045: window.removeEventListener("touchend", this.bound_on_release, true); usveticic@3045: window.removeEventListener("touchcancel", this.bound_on_release, true); usveticic@3062: usveticic@3062: //reset drag flag usveticic@3013: if(this.drag){ usveticic@3013: this.drag = false; usveticic@3013: } usveticic@3062: usveticic@3062: // get final position usveticic@3045: this.update_position(evt); usveticic@3045: } usveticic@3045: usveticic@3045: on_drag(evt){ usveticic@3062: //ignore drag event for X amount of time and if not selected usveticic@3045: if(this.enTimer && this.drag){ usveticic@3045: this.update_position(evt); usveticic@3062: usveticic@3045: //reset timer usveticic@3045: this.enTimer = false; usveticic@3045: setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); usveticic@3045: } usveticic@3013: } usveticic@3013: usveticic@3013: update_position(evt){ usveticic@3013: if(this.drag && this.enTimer){ usveticic@3013: var svg_dist = 0; usveticic@3013: usveticic@3013: //calculate center of widget in html usveticic@3013: // --TODO maybe it would be better to bind this part to window change size event ??? usveticic@3013: let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; usveticic@3013: let [cX, cY,fiStart,fiEnd,minMax,x1,y1,width,height] = this.circle; usveticic@3013: let htmlCirc = this.range_elt.getBoundingClientRect(); usveticic@3013: let cxHtml = ((htmlCirc.right-htmlCirc.left)/(width)*(cX-x1))+htmlCirc.left; usveticic@3013: let cyHtml = ((htmlCirc.bottom-htmlCirc.top)/(height)*(cY-y1))+htmlCirc.top; usveticic@3013: usveticic@3013: usveticic@3013: //get mouse coordinates usveticic@3013: let mouseX = undefined; usveticic@3013: let mouseY = undefined; usveticic@3013: if (evt.type.startsWith("touch")){ usveticic@3013: mouseX = Math.ceil(evt.touches[0].clientX); usveticic@3013: mouseY = Math.ceil(evt.touches[0].clientY); usveticic@3013: } usveticic@3013: else{ usveticic@3013: mouseX = evt.pageX; usveticic@3013: mouseY = evt.pageY; usveticic@3013: } usveticic@3013: usveticic@3013: //calculate angle usveticic@3013: let fi = Math.atan2(cyHtml-mouseY, mouseX-cxHtml); usveticic@3013: usveticic@3013: // transform from 0 to 2PI usveticic@3013: if (fi > 0){ usveticic@3013: fi = 2*Math.PI-fi; usveticic@3013: } usveticic@3013: else{ usveticic@3013: fi = -fi; usveticic@3013: } usveticic@3013: usveticic@3013: //offset it to 0 usveticic@3013: fi = fi - fiStart; usveticic@3013: if (fi < 0){ usveticic@3013: fi = fi + 2*Math.PI; usveticic@3013: } usveticic@3013: usveticic@3013: //get handle distance from mouse position usveticic@3013: if(fi= 1 ? this.args[0] : 0; usveticic@3013: let max = this.max_elt ? usveticic@3013: Number(this.max_elt.textContent) : usveticic@3013: this.args.length >= 2 ? this.args[1] : 100; usveticic@3013: usveticic@3013: //fiStart ==> offset usveticic@3013: let fiStart = Number(this.range_elt.getAttribute('sodipodi:start')); usveticic@3013: let fiEnd = Number(this.range_elt.getAttribute('sodipodi:end')); usveticic@3013: fiEnd = fiEnd - fiStart; usveticic@3013: usveticic@3013: //fiEnd ==> size of angle usveticic@3013: if (fiEnd < 0){ usveticic@3013: fiEnd = 2*Math.PI + fiEnd; usveticic@3013: } usveticic@3013: usveticic@3013: //min max barrier angle usveticic@3013: let minMax = (2*Math.PI - fiEnd)/2; usveticic@3013: usveticic@3013: //get parameters from svg usveticic@3013: let cX = Number(this.range_elt.getAttribute('sodipodi:cx')); usveticic@3013: let cY = Number(this.range_elt.getAttribute('sodipodi:cy')); usveticic@3013: this.range_elt.style.strokeMiterlimit="0"; //eliminates some weird border around html object usveticic@3013: this.range = [min, max,this.range_elt.getTotalLength()]; usveticic@3013: let cPos = this.range_elt.getBBox(); usveticic@3013: this.handle_pos = this.range_elt.getPointAtLength(0); usveticic@3013: this.circle = [cX, cY,fiStart,fiEnd,minMax,cPos.x,cPos.y,cPos.width,cPos.height]; usveticic@3013: usveticic@3045: //bind functions usveticic@3045: this.bound_on_select = this.on_select.bind(this); usveticic@3045: this.bound_on_release = this.on_release.bind(this); usveticic@3045: this.on_bound_drag = this.on_drag.bind(this); usveticic@3045: usveticic@3062: this.handle_elt.addEventListener("mousedown", this.bound_on_select); usveticic@3045: this.element.addEventListener("mousedown", this.bound_on_select); usveticic@3045: this.element.addEventListener("touchstart", this.bound_on_select); usveticic@3062: //touch recognised as page drag without next command usveticic@3062: document.body.addEventListener("touchstart", function(e){}, false); usveticic@3062: usveticic@3062: //save ghost style usveticic@3062: //save ghost style usveticic@3045: if(this.setpoint_elt != undefined){ usveticic@3045: this.setpoint_style = this.setpoint_elt.getAttribute("style"); usveticic@3045: this.setpoint_elt.setAttribute("style", "display:none"); usveticic@3045: } usveticic@3045: usveticic@3013: } usveticic@3013: || usveticic@3013: edouard@3232: widget_defs("CircularSlider") { usveticic@3013: labels("handle range"); usveticic@3062: optional_labels("value min max setpoint"); usveticic@3013: |, Edouard@3018: }