--- a/svghmi/gen_index_xhtml.xslt Tue Mar 24 23:07:54 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Wed Mar 25 13:36:04 2020 +0100
@@ -635,6 +635,8 @@
<xsl:text> unsub: unsubscribe,
+ <xsl:text> apply_cache: widget_apply_cache, <xsl:template mode="widget_subscribe" match="widget[@type='Page']"/>
<xsl:template name="defs_by_labels">
@@ -798,27 +800,17 @@
- <xsl:text> on_click: function(opstr, evt) {
- <xsl:text> console.log(opstr);
<xsl:text> item_offset: 0,
+ <xsl:text> on_click: foreach_onclick, <xsl:template mode="widget_subscribe" match="widget[@type='ForEach']">
- <xsl:text> sub: function(off){
- <xsl:text> foreach_subscribe.call(this,off);
- <xsl:text> unsub: function(){
- <xsl:text> foreach_unsubscribe.call(this);
+ <xsl:text> sub: foreach_subscribe, + <xsl:text> unsub: foreach_unsubscribe, + <xsl:text> apply_cache: foreach_apply_cache, <xsl:template mode="widget_defs" match="widget[@type='Input']">
@@ -1149,6 +1141,8 @@
<xsl:text>var updates = {};
+ <xsl:text>var need_cache_apply = []; <xsl:text>function dispatch_value_to_widget(widget, index, value, oldval) {
@@ -1319,12 +1313,14 @@
- <xsl:text> if(current_subscribed_page_index != current_visible_page_index){
- <xsl:text> apply_cache();
+ <xsl:text> while(widget = need_cache_apply.pop()){ + <xsl:text> widget.apply_cache(); <xsl:text> apply_updates();
<xsl:text> requestAnimationFrameID = null;
@@ -1659,10 +1655,6 @@
<xsl:text>var current_subscribed_page;
- <xsl:text>var current_visible_page_index;
- <xsl:text>var current_subscribed_page_index;
<xsl:text>function prepare_svg() {
@@ -1747,6 +1739,8 @@
+ <xsl:text> need_cache_apply.push(this); @@ -1763,11 +1757,15 @@
+ <xsl:text> this.offset = 0; - <xsl:text>function foreach_subscribe(new_offset=0){
+ <xsl:text>function foreach_widgets_do(new_offset, todo){ + <xsl:text> this.offset = new_offset; <xsl:text> for(let i = 0; i < this.items.length; i++) {
@@ -1781,7 +1779,7 @@
<xsl:text> for(let widget of item) {
- <xsl:text> subscribe.call(widget,new_offset + item_index_offset);
+ <xsl:text> todo.call(widget, new_offset + item_index_offset); @@ -1791,6 +1789,76 @@
+ <xsl:text>function foreach_subscribe(new_offset=0){ + <xsl:text> foreach_widgets_do.call(this, new_offset, subscribe); + <xsl:text>function widget_apply_cache() { + <xsl:text> for(let index of this.indexes){ + <xsl:text> /* dispatch current cache in newly opened page widgets */ + <xsl:text> let realindex = index+this.offset; + <xsl:text> let cached_val = cache[realindex]; + <xsl:text> if(cached_val != undefined) + <xsl:text> dispatch_value_to_widget(this, realindex, cached_val, cached_val); + <xsl:text>function foreach_apply_cache() { + <xsl:text> foreach_widgets_do.call(this, this.offset, widget_apply_cache); + <xsl:text>function foreach_onclick(opstr, evt) { + <xsl:text> new_item_offset = eval(String(this.item_offset)+opstr) + <xsl:text> if(new_item_offset + this.items.length > this.index_pool.length) { + <xsl:text> new_item_offset = 0; + <xsl:text> } else if(new_item_offset < 0) { + <xsl:text> new_item_offset = this.index_pool.length - this.items.length; + <xsl:text> this.item_offset = new_item_offset; + <xsl:text> off = this.offset; + <xsl:text> foreach_unsubscribe.call(this); + <xsl:text> foreach_subscribe.call(this,off); + <xsl:text> update_subscriptions(); + <xsl:text> need_cache_apply.push(this); + <xsl:text> requestHMIAnimation(); + <xsl:text> console.log(opstr, new_item_offset); <xsl:text>function switch_subscribed_page(page_name, page_index) {
<xsl:text> let old_desc = page_desc[current_subscribed_page];
@@ -1839,8 +1907,6 @@
<xsl:text> current_subscribed_page = page_name;
- <xsl:text> current_subscribed_page_index = page_index;
<xsl:text> requestHMIAnimation();
@@ -1905,38 +1971,6 @@
- <xsl:text>function apply_cache() {
- <xsl:text> let new_desc = page_desc[current_visible_page];
- <xsl:text> for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){
- <xsl:text> for(let index of widget.indexes){
- <xsl:text> /* dispatch current cache in newly opened page widgets */
- <xsl:text> let realindex = index+widget.offset;
- <xsl:text> let cached_val = cache[realindex];
- <xsl:text> if(cached_val != undefined)
- <xsl:text> dispatch_value_to_widget(widget, realindex, cached_val, cached_val);
- <xsl:text> current_visible_page_index = current_subscribed_page_index;
<xsl:text>// Once connection established
--- a/svghmi/svghmi.js Tue Mar 24 23:07:54 2020 +0100
+++ b/svghmi/svghmi.js Wed Mar 25 13:36:04 2020 +0100
@@ -2,6 +2,7 @@
var cache = hmitree_types.map(_ignored => undefined);
+var need_cache_apply = []; function dispatch_value_to_widget(widget, index, value, oldval) {
@@ -87,9 +88,10 @@
switch_visible_page(current_subscribed_page);
- if(current_subscribed_page_index != current_visible_page_index){
+ while(widget = need_cache_apply.pop()){ requestAnimationFrameID = null;
@@ -257,8 +259,6 @@
var current_visible_page;
var current_subscribed_page;
-var current_visible_page_index;
-var current_subscribed_page_index;
for(let eltid in detachable_elements){
@@ -301,6 +301,7 @@
for(let index of this.indexes){
subscribers[index + new_offset].add(this);
+ need_cache_apply.push(this); function foreach_unsubscribe(){
@@ -309,20 +310,57 @@
unsubscribe.call(widget);
-function foreach_subscribe(new_offset=0){
+function foreach_widgets_do(new_offset, todo){ + this.offset = new_offset; for(let i = 0; i < this.items.length; i++) {
let item = this.items[i];
let orig_item_index = this.index_pool[i];
let item_index = this.index_pool[i+this.item_offset];
let item_index_offset = item_index - orig_item_index;
for(let widget of item) {
- subscribe.call(widget,new_offset + item_index_offset);
+ todo.call(widget, new_offset + item_index_offset); +function foreach_subscribe(new_offset=0){ + foreach_widgets_do.call(this, new_offset, subscribe); +function widget_apply_cache() { + for(let index of this.indexes){ + /* dispatch current cache in newly opened page widgets */ + let realindex = index+this.offset; + let cached_val = cache[realindex]; + if(cached_val != undefined) + dispatch_value_to_widget(this, realindex, cached_val, cached_val); +function foreach_apply_cache() { + foreach_widgets_do.call(this, this.offset, widget_apply_cache); +function foreach_onclick(opstr, evt) { + new_item_offset = eval(String(this.item_offset)+opstr) + if(new_item_offset + this.items.length > this.index_pool.length) { + } else if(new_item_offset < 0) { + new_item_offset = this.index_pool.length - this.items.length; + this.item_offset = new_item_offset; + foreach_unsubscribe.call(this); + foreach_subscribe.call(this,off); + update_subscriptions(); + need_cache_apply.push(this); + console.log(opstr, new_item_offset); function switch_subscribed_page(page_name, page_index) {
let old_desc = page_desc[current_subscribed_page];
let new_desc = page_desc[page_name];
@@ -347,7 +385,6 @@
current_subscribed_page = page_name;
- current_subscribed_page_index = page_index;
@@ -380,22 +417,6 @@
svg_root.setAttribute('viewBox',new_desc.bbox.join(" "));
current_visible_page = page_name;
-function apply_cache() {
- let new_desc = page_desc[current_visible_page];
- for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){
- for(let index of widget.indexes){
- /* dispatch current cache in newly opened page widgets */
- let realindex = index+widget.offset;
- let cached_val = cache[realindex];
- if(cached_val != undefined)
- dispatch_value_to_widget(widget, realindex, cached_val, cached_val);
- current_visible_page_index = current_subscribed_page_index;
// Once connection established
ws.onopen = function (evt) {
--- a/svghmi/widget_foreach.ysl2 Tue Mar 24 23:07:54 2020 +0100
+++ b/svghmi/widget_foreach.ysl2 Wed Mar 25 13:36:04 2020 +0100
@@ -44,19 +44,14 @@
- | on_click: function(opstr, evt) {
+ | on_click: foreach_onclick, template "widget[@type='ForEach']", mode="widget_subscribe"{
- | foreach_subscribe.call(this,off);
+ | sub: foreach_subscribe, + | unsub: foreach_unsubscribe, + | apply_cache: foreach_apply_cache,
- | foreach_unsubscribe.call(this);
--- a/svghmi/widgets_common.ysl2 Tue Mar 24 23:07:54 2020 +0100
+++ b/svghmi/widgets_common.ysl2 Wed Mar 25 13:36:04 2020 +0100
@@ -43,6 +43,7 @@
template "widget", mode="widget_subscribe" {
+ | apply_cache: widget_apply_cache, // page aren't subscribers
template "widget[@type='Page']", mode="widget_subscribe";