# HG changeset patch # User Edouard Tisserant # Date 1660897336 -7200 # Node ID 122b1094b8e6565bb54ab5d57caf1af82210f627 # Parent b2bdb8b433e0d5ce2391dd18dc5bf3106fc3abd4 SVGHMI: preliminary implementation of a general enable bit for all widgets, using "#" at the end of widget declaration, and a "disabled" element that becomes visible instead of widget when disabled. diff -r b2bdb8b433e0 -r 122b1094b8e6 svghmi/parse_labels.ysl2 --- a/svghmi/parse_labels.ysl2 Fri Aug 12 09:34:24 2022 +0200 +++ b/svghmi/parse_labels.ysl2 Fri Aug 19 10:22:16 2022 +0200 @@ -2,7 +2,7 @@ // Parses: -// "HMI:WidgetType|freq:param1:param2@path1,path1min,path1max@path2" +// "HMI:WidgetType|freq:param1:param2@path1,path1min,path1max@path2#" // // Into: // widget type="WidgetType" id="blah456" { @@ -75,7 +75,18 @@ attrib "value" > «.» } } - const "paths", "substring-after($declaration,'@')"; + const "tail", "substring-after($declaration,'@')"; + const "taillen","string-length($tail)"; + const "has_enable", "substring($tail,$taillen,1)='#'"; + const "paths" choose{ + when "$has_enable" { + value "substring($tail,1,$taillen - 1)"; + } + otherwise value "$tail"; + } + if "$has_enable" { + attrib "has_enable" > yes + } foreach "str:split($paths, '@')" { if "string-length(.) > 0" path { // 1 : global match diff -r b2bdb8b433e0 -r 122b1094b8e6 svghmi/widgets_common.ysl2 --- a/svghmi/widgets_common.ysl2 Fri Aug 12 09:34:24 2022 +0200 +++ b/svghmi/widgets_common.ysl2 Fri Aug 19 10:22:16 2022 +0200 @@ -104,7 +104,14 @@ > undefined } - | "«@id»": new «$widget/@type»Widget ("«@id»",«$freq»,[«$args»],[«$indexes»],[«$minmaxes»],{ + const "has_enable" choose { + when "$widget/@has_enable = 'yes'" + > true + otherwise + > false + } + + | "«@id»": new «$widget/@type»Widget ("«@id»",«$freq»,[«$args»],[«$indexes»],[«$minmaxes»],«$has_enable»,{ apply "$widget", mode="widget_defs" with "hmi_element","."; | })`if "position()!=last()" > ,` } @@ -218,12 +225,14 @@ unsubscribable = false; pending_animate = false; - constructor(elt_id, freq, args, indexes, minmaxes, members){ + constructor(elt_id, freq, args, indexes, minmaxes, has_enable, members){ this.element_id = elt_id; this.element = id(elt_id); this.args = args; this.indexes = indexes; + this.indexes_length = indexes.length; this.minmaxes = minmaxes; + this.has_enable = has_enable; Object.keys(members).forEach(prop => this[prop]=members[prop]); this.lastapply = indexes.map(() => undefined); this.inhibit = indexes.map(() => undefined); @@ -267,12 +276,27 @@ console.log(err); } } + + if(this.has_enable){ + this.disabled_elt = null; + this.enabled_elts = []; + this.enable_state = false; + this.enable_displayed_state = false; + for(let child of Array.from(this.element.children)){ + if(child.getAttribute("inkscape:label")=="disabled"){ + this.disabled_elt = child; + }else{ + this.enabled_elts.push(child); + this.element.removeChild(child); + } + } + } } unsub(){ /* remove subsribers */ if(!this.unsubscribable) - for(let i = 0; i < this.indexes.length; i++) { + for(let i = 0; i < this.indexes_length; i++) { /* flush updates pending because of inhibition */ let inhibition = this.inhibit[i]; if(inhibition != undefined){ @@ -301,7 +325,7 @@ this.container_id = container_id ; /* add this's subsribers */ if(!this.unsubscribable) - for(let i = 0; i < this.indexes.length; i++) { + for(let i = 0; i < this.indexes_length; i++) { let index = this.get_variable_index(i); if(index == undefined) continue; subscribers(index).add(this); @@ -402,7 +426,7 @@ new_hmi_value(index, value, oldval) { // TODO avoid searching, store index at sub() - for(let i = 0; i < this.indexes.length; i++) { + for(let i = 0; i < this.indexes_length; i++) { let refindex = this.get_variable_index(i); if(refindex == undefined) continue; @@ -420,20 +444,63 @@ this.dispatch(new_val, old_val, index); } + enable(enabled){ + if(this.enable_state != enabled){ + this.enable_state = enabled; + this.request_animate(); + } + } + + animate_enable(){ + if(this.enable_state && !this.enable_displayed_state){ + //show widget + for(let child of this.enabled_elts){ + this.element.appendChild(child); + } + + //hide disabled content + if(this.disabled_elt && this.disabled_elt.parentNode != null) + this.element.removeChild(this.disabled_elt); + + this.enable_displayed_state = true; + + }else if(!this.enable_state && this.enable_displayed_state){ + + //hide widget + for(let child of this.enabled_elts){ + if(child.parentNode != null) + this.element.removeChild(child); + } + + //show disabled content + if(this.disabled_elt) + this.element.appendChild(this.disabled_elt); + + this.enable_displayed_state = false; + } + } + _dispatch(value, oldval, varnum) { let dispatch = this.dispatch; - if(dispatch != undefined){ + let has_dispatch = dispatch != undefined; + let is_enable_var = this.has_enable && (varnum == (this.indexes_length - 1)); + if(has_dispatch || is_enable_var){ if(this.deafen[varnum] == undefined){ let now = Date.now(); let min_interval = 1000/this.frequency; let lastdispatch = this.lastdispatch[varnum]; if(lastdispatch == undefined || now > lastdispatch + min_interval){ this.lastdispatch[varnum] = now; - try { + if(has_dispatch) try { dispatch.call(this, value, oldval, varnum); } catch(err) { console.log(err); } + if(is_enable_var) try { + this.enable(Boolean(value)); + } catch(err) { + console.log(err); + } } else { let elapsed = now - lastdispatch; @@ -448,7 +515,10 @@ } _animate(){ - this.animate(); + if(this.has_enable) + this.animate_enable(); + if(this.animate != undefined && (!this.has_enable || this.enable_state)) + this.animate(); this.pending_animate = false; } diff -r b2bdb8b433e0 -r 122b1094b8e6 tests/projects/svghmi_scrollbar/svghmi_0@svghmi/svghmi.svg --- a/tests/projects/svghmi_scrollbar/svghmi_0@svghmi/svghmi.svg Fri Aug 12 09:34:24 2022 +0200 +++ b/tests/projects/svghmi_scrollbar/svghmi_0@svghmi/svghmi.svg Fri Aug 19 10:22:16 2022 +0200 @@ -59,9 +59,9 @@ inkscape:current-layer="hmi0" showgrid="false" units="px" - inkscape:zoom="0.64" - inkscape:cx="476.03774" - inkscape:cy="444.53549" + inkscape:zoom="0.90509668" + inkscape:cx="474.80696" + inkscape:cy="335.41469" inkscape:window-width="1600" inkscape:window-height="836" inkscape:window-x="0" @@ -751,8 +751,15 @@ id="desc150">@.range @.position @.size +# my tailor is rich +