svghmi/widget_circularbar.ysl2
author Edouard Tisserant
Thu, 10 Jun 2021 09:40:05 +0200
branchsvghmi
changeset 3254 b1bc6099d4e5
parent 3241 fe945f1f48b7
child 3330 c3b1a4bfdf0a
permissions -rw-r--r--
Copy description when DnD variables from CodeFile CTN to POUs
// 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.

    If "value" labeled text is found, then its content is replaced by value.
    ||

    shortdesc > Change end angle of Inkscape's arc

    // TODO: add min/max arguments
    // TODO: add printf-like format

    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() {
            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("value min max");
}