IDE: allow structures to be located.
// 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);
}
| },
}