diff -r cae53fe54cf2 -r 6d4c1e6560ac svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Sun Feb 14 05:29:51 2021 +0100 +++ b/svghmi/gen_index_xhtml.xslt Sun Feb 14 05:30:29 2021 +0100 @@ -1244,6 +1244,8 @@ cache[new_index] = defaultval; + updates[new_index] = defaultval; + if(persistent_locals.has(varname)) persistent_indexes.set(new_index, varname); @@ -1305,6 +1307,14 @@ Object.keys(members).forEach(prop => this[prop]=members[prop]); + this.lastapply = indexes.map(() => undefined); + + this.inhibit = indexes.map(() => undefined); + + this.pending = indexes.map(() => undefined); + + this.bound_unhinibit = this.unhinibit.bind(this); + } @@ -1317,6 +1327,20 @@ for(let i = 0; i < this.indexes.length; i++) { + /* flush updates pending because of inhibition */ + + let inhibition = this.inhibit[index]; + + if(inhibition != undefined){ + + clearTimeout(inhibition); + + this.lastapply[index] = undefined; + + this.unhinibit(index); + + } + let index = this.indexes[i]; if(this.relativeness[i]) @@ -1471,15 +1495,71 @@ + _apply_hmi_value(index, new_val) { + + let realindex = this.get_variable_index(index); + + if(realindex == undefined) return undefined; + + new_val = this.clip_min_max(index, new_val); + + return apply_hmi_value(realindex, new_val); + + } + + + + unhinibit(index){ + + this.inhibit[index] = undefined; + + let new_val = this.pending[index]; + + this.pending[index] = undefined; + + return this.apply_hmi_value(index, new_val); + + } + + + apply_hmi_value(index, new_val) { - let realindex = this.get_variable_index(index); - - if(realindex == undefined) return undefined; - - new_val = this.clip_min_max(index, new_val); - - return apply_hmi_value(realindex, new_val); + if(this.inhibit[index] == undefined){ + + let now = Date.now(); + + let min_interval = 1000/this.frequency; + + let lastapply = this.lastapply[index]; + + if(lastapply == undefined || now > lastapply + min_interval){ + + this.lastapply[index] = now; + + return this._apply_hmi_value(index, new_val); + + } + + else { + + let elapsed = now - lastapply; + + this.pending[index] = new_val; + + this.inhibit[index] = setTimeout(this.bound_unhinibit, min_interval - elapsed, index); + + } + + } + + else { + + this.pending[index] = new_val; + + return new_val; + + } } @@ -5501,6 +5581,214 @@ ], + + class ScrollBarWidget extends Widget{ + + frequency = 10; + + 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); + + + + 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){ + + // 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); + + } + + + + 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 point = new DOMPoint(e.movementX, e.movementY); + + let movement = point.matrixTransform(this.invctm).y; + + this.apply_position(this.position + movement * units / pixels); + + } + + } + + + + + + + + cursor range + + + + + + + pageup pagedown + + + + + + + init: function() { + + this.init_mandatory(); + + + this.pageup_elt.onclick = () => this.on_page_click(true); + + this.pagedown_elt.onclick = () => this.on_page_click(false); + + + }, + + class SliderWidget extends Widget{ @@ -6964,8 +7252,6 @@ let varname = persistent_indexes.get(index); - console.log(varname+"="+value+"; max-age=3153600000"); - document.cookie = varname+"="+value+"; max-age=3153600000"; }