svghmi/widget_scrollbar.ysl2
branchsvghmi
changeset 3136 784c839d4259
child 3137 ac3ec66e9c6d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_scrollbar.ysl2	Fri Feb 12 22:00:07 2021 +0100
@@ -0,0 +1,106 @@
+// widget_scrollbar.ysl2
+
+template "widget[@type='ScrollBar']", mode="widget_class"{
+    ||
+    class ScrollBarWidget extends Widget{
+        frequency = 5;
+        position = undefined;
+        range = undefined;
+        size = undefined;
+        mincursize = 0.1;
+
+        dispatch(value,oldval, index) {
+            switch(index) {
+                case 0:
+                    if (Math.round(this.position) != value)
+                        this.position = value;
+                    break;
+                case 1:
+                    this.range = value;
+                    break;
+                case 2:
+                    this.size = value;
+                    break;
+            }
+
+            this.request_animate();
+        }
+
+        get_ratios() {
+            let range = this.range;
+            let size = Math.max(this.range * this.mincursize, Math.min(this.size, range));
+            let maxh = this.range_elt.height.baseVal.value;
+            let pixels = (range - size) * maxh;
+            let units = range*range;
+            return [size, maxh, range, pixels, units];
+        }
+
+        animate(){
+            if(this.position == undefined || this.range == undefined || this.size == undefined)
+                return;
+            let [size, maxh, range, pixels, units] = this.get_ratios();
+
+            let new_y = this.range_elt.y.baseVal.value + Math.round(Math.min(this.position,range) * pixels / units);
+            let new_height = Math.round(maxh * size/range);
+            console.log(new_y, new_height);
+
+            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.max(Math.min(position, this.range), 0);
+            this.apply_hmi_value(0, Math.round(this.position));
+        }
+
+        on_page_click(is_up){
+            this.apply_position(is_up ? this.position-this.size
+                                      : this.position+this.size);
+        }
+
+        on_cursor_down(e){
+            svg_root.addEventListener("pointerup", this.bound_drop, true);
+            svg_root.addEventListener("pointermove", this.bound_drag, true);
+        }
+
+        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, units] = this.get_ratios();
+            if(pixels == 0) return;
+            let matrix = this.range_elt.getCTM().inverse();
+            let point = new DOMPoint(e.movementX, e.movementY);
+            let movement = point.matrixTransform(matrix).y;
+            this.apply_position(this.position + movement * units / pixels);
+        }
+    }
+    ||
+}
+
+template "widget[@type='ScrollBar']", mode="widget_defs" {
+    param "hmi_element";
+    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);
+    }
+    |     },
+}