// widget_circularbar.ysl2 widget_desc("CircularBar") { longdesc || CircularBar widget changes the end angle of a "path" labeled arc according to value of the single accepted variable. If "min" a "max" labeled texts are provided, then they are used as respective minimum and maximum value. Otherwise, value is expected to be in between 0 and 100. || shortdesc > Change end angle of Inkscape's arc arg name="min" count="optional" accepts="int,real" > minimum value arg name="max" count="optional" accepts="int,real" > maximum value path name="value" accepts="HMI_INT,HMI_REAL" > Value to display } widget_class("CircularBar") { || frequency = 10; range = undefined; dispatch(value) { this.display_val = value; this.request_animate(); } animate(){ if(this.value_elt) this.value_elt.textContent = String(this.display_val); let [min,max,start,end] = this.range; let [cx,cy] = this.center; let [rx,ry] = this.proportions; let tip = start + (end-start)*Number(this.display_val)/(max-min); let size = 0; if (tip-start > Math.PI) size = 1; else size = 0; this.path_elt.setAttribute('d', "M "+(cx+rx*Math.cos(start))+","+(cy+ry*Math.sin(start))+ " A "+rx+","+ry+ " 0 "+size+ " 1 "+(cx+rx*Math.cos(tip))+","+(cy+ry*Math.sin(tip))); } init() { if(this.args.length >= 2) [this.min, this.max]=this.args; let [start, end, cx, cy, rx, ry] = ["start", "end", "cx", "cy", "rx", "ry"]. map(tag=>Number(this.path_elt.getAttribute('sodipodi:'+tag))) if (ry == 0) ry = rx; if (start > end) end = end + 2*Math.PI; let [min,max] = [[this.min_elt,0],[this.max_elt,100]].map(([elt,def],i)=>elt? Number(elt.textContent) : this.args.length >= i+1 ? this.args[i] : def); this.range = [min, max, start, end]; this.center = [cx, cy]; this.proportions = [rx, ry]; } || } widget_defs("CircularBar") { labels("path"); optional_labels("min max"); }