edouard@3136: // widget_scrollbar.ysl2 edouard@3241: widget_desc("ScrollBar") { edouard@3241: longdesc edouard@3241: || edouard@3357: ScrollBar - svg:rect based scrollbar edouard@3241: || edouard@3241: edouard@3241: shortdesc > ScrollBar edouard@3241: edouard@3241: path name="value" accepts="HMI_INT" > value edouard@3241: path name="range" accepts="HMI_INT" > range edouard@3241: path name="visible" accepts="HMI_INT" > visible edouard@3241: edouard@3241: } edouard@3136: edouard@3232: widget_class("ScrollBar") { edouard@3136: || edouard@3139: frequency = 10; edouard@3136: position = undefined; edouard@3136: range = undefined; edouard@3136: size = undefined; edouard@3136: mincursize = 0.1; edouard@3136: edouard@3136: dispatch(value,oldval, index) { edouard@3136: switch(index) { edouard@3136: case 0: Edouard@3178: this.range = Math.max(1,value); edouard@3136: break; edouard@3136: case 1: Edouard@3178: this.position = value; edouard@3136: break; edouard@3136: case 2: edouard@3136: this.size = value; edouard@3136: break; edouard@3136: } edouard@3136: edouard@3136: this.request_animate(); edouard@3136: } edouard@3136: edouard@3136: get_ratios() { edouard@3136: let range = this.range; edouard@3357: let size = Math.max(range * this.mincursize, Math.min(this.size, range)); edouard@3136: let maxh = this.range_elt.height.baseVal.value; Edouard@3151: let pixels = maxh; edouard@3357: return [size, maxh, range, pixels]; edouard@3136: } edouard@3136: edouard@3136: animate(){ edouard@3136: if(this.position == undefined || this.range == undefined || this.size == undefined) edouard@3136: return; edouard@3357: let [size, maxh, range, pixels] = this.get_ratios(); edouard@3136: edouard@3357: let new_y = this.range_elt.y.baseVal.value + Math.round(Math.min(this.position,range-size) * pixels / range); edouard@3136: let new_height = Math.round(maxh * size/range); edouard@3136: edouard@3136: this.cursor_elt.y.baseVal.value = new_y; edouard@3136: this.cursor_elt.height.baseVal.value = new_height; edouard@3136: } edouard@3136: edouard@3136: init_mandatory() { edouard@3136: this.cursor_elt.onpointerdown = () => this.on_cursor_down(); edouard@3136: edouard@3136: this.bound_drag = this.drag.bind(this); edouard@3136: this.bound_drop = this.drop.bind(this); edouard@3136: } edouard@3136: edouard@3136: apply_position(position){ Edouard@3151: this.position = Math.round(Math.max(Math.min(position, this.range - this.size), 0)); Edouard@3178: this.apply_hmi_value(1, this.position); edouard@3136: } edouard@3136: edouard@3136: on_page_click(is_up){ edouard@3136: this.apply_position(is_up ? this.position-this.size edouard@3136: : this.position+this.size); edouard@3136: } edouard@3136: edouard@3136: on_cursor_down(e){ edouard@3138: // get scrollbar -> root transform edouard@3138: let ctm = this.range_elt.getCTM(); edouard@3138: // relative motion -> discard translation edouard@3138: ctm.e = 0; edouard@3138: ctm.f = 0; edouard@3138: // root -> scrollbar transform edouard@3138: this.invctm = ctm.inverse(); edouard@3136: svg_root.addEventListener("pointerup", this.bound_drop, true); edouard@3136: svg_root.addEventListener("pointermove", this.bound_drag, true); Edouard@3143: this.dragpos = this.position; edouard@3136: } edouard@3136: edouard@3136: drop(e) { edouard@3136: svg_root.removeEventListener("pointerup", this.bound_drop, true); edouard@3136: svg_root.removeEventListener("pointermove", this.bound_drag, true); edouard@3136: } edouard@3136: edouard@3136: drag(e) { edouard@3357: let [size, maxh, range, pixels] = this.get_ratios(); edouard@3136: if(pixels == 0) return; edouard@3136: let point = new DOMPoint(e.movementX, e.movementY); edouard@3138: let movement = point.matrixTransform(this.invctm).y; edouard@3357: this.dragpos += movement * range / pixels; Edouard@3143: this.apply_position(this.dragpos); edouard@3136: } edouard@3136: || edouard@3136: } edouard@3136: edouard@3232: widget_defs("ScrollBar") { edouard@3136: labels("cursor range"); edouard@3136: edouard@3136: const "pagebuttons" optional_labels("pageup pagedown"); edouard@3136: const "have_pagebuttons","string-length($pagebuttons)>0"; edouard@3136: value "$pagebuttons"; edouard@3136: edouard@3136: | init: function() { edouard@3136: | this.init_mandatory(); edouard@3136: edouard@3136: if "$have_pagebuttons" { edouard@3136: | this.pageup_elt.onclick = () => this.on_page_click(true); edouard@3136: | this.pagedown_elt.onclick = () => this.on_page_click(false); edouard@3136: } edouard@3136: | }, edouard@3136: }