svghmi/widget_scrollbar.ysl2
author Edouard Tisserant <edouard.tisserant@gmail.com>
Tue, 15 Nov 2022 20:43:39 +0100
branchwxPython4
changeset 3677 6d9040e07c32
parent 3325 3930916a2e0d
permissions -rw-r--r--
OPC-UA: only support the encryption policy selected in config.

By default open62541 client accepts all supported policies, but in makes problem
when negociating with some servers while most clients seems to only support
one policy at a time.
// widget_scrollbar.ysl2
widget_desc("ScrollBar") {
    longdesc
    || 
    ScrollBar - svg:rect based scrollbar
    ||

    shortdesc > ScrollBar

    path name="value" accepts="HMI_INT" > value
    path name="range" accepts="HMI_INT" > range
    path name="visible" accepts="HMI_INT" > visible
    
}

widget_class("ScrollBar") {
    ||
        frequency = 10;
        position = undefined;
        range = undefined;
        size = undefined;
        mincursize = 0.1;

        dispatch(value,oldval, index) {
            switch(index) {
                case 0:
                    this.range = Math.max(1,value);
                    break;
                case 1:
                    this.position = value;
                    break;
                case 2:
                    this.size = value;
                    break;
            }

            this.request_animate();
        }

        get_ratios() {
            let range = this.range;
            let size = Math.max(range * this.mincursize, Math.min(this.size, range));
            let maxh = this.range_elt.height.baseVal.value;
            let pixels = maxh;
            return [size, maxh, range, pixels];
        }

        animate(){
            if(this.position == undefined || this.range == undefined || this.size == undefined)
                return;
            let [size, maxh, range, pixels] = this.get_ratios();

            let new_y = this.range_elt.y.baseVal.value + Math.round(Math.min(this.position,range-size) * pixels / range);
            let new_height = Math.round(maxh * size/range);

            this.cursor_elt.y.baseVal.value = new_y;
            this.cursor_elt.height.baseVal.value = new_height;
        }

        init_mandatory() {
            this.cursor_elt.onpointerdown = () => this.on_cursor_down();

            this.bound_drag = this.drag.bind(this);
            this.bound_drop = this.drop.bind(this);
        }

        apply_position(position){
            this.position = Math.round(Math.max(Math.min(position, this.range - this.size), 0));
            this.apply_hmi_value(1, this.position);
        }

        on_page_click(is_up){
            this.apply_position(is_up ? this.position-this.size
                                      : this.position+this.size);
        }

        on_cursor_down(e){
            // get scrollbar -> root transform
            let ctm = this.range_elt.getCTM();
            // relative motion -> discard translation
            ctm.e = 0;
            ctm.f = 0;
            // root -> scrollbar transform
            this.invctm = ctm.inverse();
            svg_root.addEventListener("pointerup", this.bound_drop, true);
            svg_root.addEventListener("pointermove", this.bound_drag, true);
            this.dragpos = this.position;
        }

        drop(e) {
            svg_root.removeEventListener("pointerup", this.bound_drop, true);
            svg_root.removeEventListener("pointermove", this.bound_drag, true);
        }

        drag(e) {
            let [size, maxh, range, pixels] = this.get_ratios();
            if(pixels == 0) return;
            let point = new DOMPoint(e.movementX, e.movementY);
            let movement = point.matrixTransform(this.invctm).y;
            this.dragpos += movement * range / pixels;
            this.apply_position(this.dragpos);
        }
    ||
}

widget_defs("ScrollBar") {
    labels("cursor range");

    const "pagebuttons" optional_labels("pageup pagedown");
    const "have_pagebuttons","string-length($pagebuttons)>0";
    value "$pagebuttons";

    |     init: function() {
    |         this.init_mandatory();

    if "$have_pagebuttons" {
    |         this.pageup_elt.onclick = () => this.on_page_click(true);
    |         this.pagedown_elt.onclick = () => this.on_page_click(false);
    }
    |     },
}