# HG changeset patch # User Edouard Tisserant # Date 1583845049 -3600 # Node ID 36f78f6cfabd2973a5579cd43c78e276a28eba0e # Parent e120d6985a2f905233a7e6891b6ab2c62d65f26d SVGHMI: split page switch into switching subscription and switching elements in the DOM, to ensure that subscriptions have been send before changing DOM, and avoid some flicker. diff -r e120d6985a2f -r 36f78f6cfabd svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Mon Mar 09 13:43:34 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Tue Mar 10 13:57:29 2020 +0100 @@ -625,8 +625,6 @@ var updates = {}; - var page_switch = null; - function dispatch_value_to_widget(widget, index, value, oldval) { @@ -761,11 +759,9 @@ function animate() { - if(page_switch != null){ - - do_switch_page(page_switch); - - page_switch=null; + if(current_subscribed_page != current_visible_page){ + + switch_visible_page(current_subscribed_page); } @@ -783,6 +779,8 @@ } + requestAnimationFrameID = null; + } @@ -791,15 +789,11 @@ function requestHMIAnimation() { - if(requestAnimationFrameID != null){ - - window.cancelAnimationFrame(requestAnimationFrameID); - - requestAnimationFrameID = null; - - } - - requestAnimationFrameID = window.requestAnimationFrame(animate); + if(requestAnimationFrameID == null){ + + requestAnimationFrameID = window.requestAnimationFrame(animate); + + } } @@ -865,7 +859,7 @@ // register for rendering on next frame, since there are updates - window.requestAnimationFrame(animate); + requestHMIAnimation(); } catch(err) { @@ -1115,7 +1109,9 @@ - var current_page; + var current_visible_page; + + var current_subscribed_page; @@ -1135,77 +1131,153 @@ function switch_page(page_name) { - page_switch = page_name; - - window.requestAnimationFrame(animate); + if(current_subscribed_page != current_visible_page){ + + /* page switch already going */ + + /* TODO LOG ERROR */ + + return; + + } else if(page_name == current_visible_page){ + + /* already in that page */ + + /* TODO LOG ERROR */ + + return; + + } + + switch_subscribed_page(page_name); + + }; + + + + function switch_subscribed_page(page_name) { + + let old_desc = page_desc[current_subscribed_page]; + + let new_desc = page_desc[page_name]; + + + + if(new_desc == undefined){ + + /* TODO LOG ERROR */ + + return; + + } + + + + if(old_desc){ + + for(let widget of old_desc.widgets){ + + /* remove subsribers */ + + for(let index of widget.indexes){ + + subscribers[index].delete(widget); + + } + + } + + } + + for(let widget of new_desc.widgets){ + + /* add widget's subsribers */ + + for(let index of widget.indexes){ + + subscribers[index].add(widget); + + } + + } + + + + update_subscriptions(); + + + + current_subscribed_page = page_name; + + + + requestHMIAnimation(); } - function do_switch_page(page_name) { - - let old_desc = page_desc[current_page]; + function switch_visible_page(page_name) { + + + + let old_desc = page_desc[current_visible_page]; let new_desc = page_desc[page_name]; - if(new_desc == undefined){ - - /* TODO LOG ERROR */ - - return; - - } - - - if(old_desc){ - for(let widget of old_desc.widgets){ - - /* remove subsribers */ - - for(let index of widget.indexes){ - - subscribers[index].delete(widget); + for(let eltid in old_desc.required_detachables){ + + if(!(eltid in new_desc.required_detachables)){ + + let [element, parent] = old_desc.required_detachables[eltid]; + + parent.removeChild(element); } } - for(let eltid in old_desc.required_detachables){ - - if(!(eltid in new_desc.required_detachables)){ - - let [element, parent] = old_desc.required_detachables[eltid]; - - parent.removeChild(element); + for(let eltid in new_desc.required_detachables){ + + if(!(eltid in old_desc.required_detachables)){ + + let [element, parent] = new_desc.required_detachables[eltid]; + + parent.appendChild(element); } } + }else{ + for(let eltid in new_desc.required_detachables){ - if(!(eltid in old_desc.required_detachables)){ - - let [element, parent] = new_desc.required_detachables[eltid]; - - parent.appendChild(element); - - } + let [element, parent] = new_desc.required_detachables[eltid]; + + parent.appendChild(element); } - }else{ - - for(let eltid in new_desc.required_detachables){ - - let [element, parent] = new_desc.required_detachables[eltid]; - - parent.appendChild(element); + } + + + + for(let widget of new_desc.widgets){ + + for(let index of widget.indexes){ + + /* dispatch current cache in newly opened page widgets */ + + let cached_val = cache[index]; + + if(cached_val != undefined) + + dispatch_value_to_widget(widget, index, cached_val, cached_val); } @@ -1213,35 +1285,9 @@ - for(let widget of new_desc.widgets){ - - /* add widget's subsribers */ - - for(let index of widget.indexes){ - - subscribers[index].add(widget); - - /* dispatch current cache in newly opened page widgets */ - - let cached_val = cache[index]; - - if(cached_val != undefined) - - dispatch_value_to_widget(widget, index, cached_val, cached_val); - - } - - } - - - svg_root.setAttribute('viewBox',new_desc.bbox.join(" ")); - current_page = page_name; - - - - window.setTimeout(update_subscriptions,0); + current_visible_page = page_name; }; diff -r e120d6985a2f -r 36f78f6cfabd svghmi/svghmi.js --- a/svghmi/svghmi.js Mon Mar 09 13:43:34 2020 +0100 +++ b/svghmi/svghmi.js Tue Mar 10 13:57:29 2020 +0100 @@ -2,7 +2,6 @@ var cache = hmitree_types.map(_ignored => undefined); var updates = {}; -var page_switch = null; function dispatch_value_to_widget(widget, index, value, oldval) { try { @@ -70,9 +69,8 @@ // Do the page swith if any one pending // Called on requestAnimationFrame, modifies DOM function animate() { - if(page_switch != null){ - do_switch_page(page_switch); - page_switch=null; + if(current_subscribed_page != current_visible_page){ + switch_visible_page(current_subscribed_page); } for(let index in updates){ @@ -81,15 +79,14 @@ dispatch_value(Number(index), updates[index]); delete updates[index]; } + requestAnimationFrameID = null; } var requestAnimationFrameID = null; function requestHMIAnimation() { - if(requestAnimationFrameID != null){ - window.cancelAnimationFrame(requestAnimationFrameID); - requestAnimationFrameID = null; - } - requestAnimationFrameID = window.requestAnimationFrame(animate); + if(requestAnimationFrameID == null){ + requestAnimationFrameID = window.requestAnimationFrame(animate); + } } // Message reception handler @@ -122,7 +119,7 @@ } }; // register for rendering on next frame, since there are updates - window.requestAnimationFrame(animate); + requestHMIAnimation(); } catch(err) { // 1003 is for "Unsupported Data" // ws.close(1003, err.message); @@ -247,7 +244,8 @@ return new_val; } -var current_page; +var current_visible_page; +var current_subscribed_page; function prepare_svg() { for(let eltid in detachable_elements){ @@ -257,12 +255,20 @@ }; function switch_page(page_name) { - page_switch = page_name; - window.requestAnimationFrame(animate); -} - -function do_switch_page(page_name) { - let old_desc = page_desc[current_page]; + if(current_subscribed_page != current_visible_page){ + /* page switch already going */ + /* TODO LOG ERROR */ + return; + } else if(page_name == current_visible_page){ + /* already in that page */ + /* TODO LOG ERROR */ + return; + } + switch_subscribed_page(page_name); +}; + +function switch_subscribed_page(page_name) { + let old_desc = page_desc[current_subscribed_page]; let new_desc = page_desc[page_name]; if(new_desc == undefined){ @@ -277,6 +283,27 @@ subscribers[index].delete(widget); } } + } + for(let widget of new_desc.widgets){ + /* add widget's subsribers */ + for(let index of widget.indexes){ + subscribers[index].add(widget); + } + } + + update_subscriptions(); + + current_subscribed_page = page_name; + + requestHMIAnimation(); +} + +function switch_visible_page(page_name) { + + let old_desc = page_desc[current_visible_page]; + let new_desc = page_desc[page_name]; + + if(old_desc){ for(let eltid in old_desc.required_detachables){ if(!(eltid in new_desc.required_detachables)){ let [element, parent] = old_desc.required_detachables[eltid]; @@ -297,9 +324,7 @@ } for(let widget of new_desc.widgets){ - /* add widget's subsribers */ for(let index of widget.indexes){ - subscribers[index].add(widget); /* dispatch current cache in newly opened page widgets */ let cached_val = cache[index]; if(cached_val != undefined) @@ -308,9 +333,7 @@ } svg_root.setAttribute('viewBox',new_desc.bbox.join(" ")); - current_page = page_name; - - window.setTimeout(update_subscriptions,0); + current_visible_page = page_name; };