1 |
1 |
2 template "widget[@type='ForEach']", mode="widget_defs" { |
2 template "widget[@type='ForEach']", mode="widget_defs" { |
3 param "hmi_element"; |
3 param "hmi_element"; |
|
4 |
|
5 if "count(path) != 1" error > ForEach widget «$hmi_element/@id» must have one HMI path given. |
|
6 if "count(arg) != 1" error > ForEach widget «$hmi_element/@id» must have one argument given : a class name. |
4 |
7 |
5 const "class","arg[1]/@value"; |
8 const "class","arg[1]/@value"; |
6 |
9 |
7 const "base_path","path/@value"; |
10 const "base_path","path/@value"; |
8 const "hmi_index_base", "$indexed_hmitree/*[@hmipath = $base_path]"; |
11 const "hmi_index_base", "$indexed_hmitree/*[@hmipath = $base_path]"; |
47 } |
50 } |
48 |
51 |
49 template "widget[@type='ForEach']", mode="widget_class" |
52 template "widget[@type='ForEach']", mode="widget_class" |
50 || |
53 || |
51 class ForEachWidget extends Widget{ |
54 class ForEachWidget extends Widget{ |
52 unsub(){ |
55 |
|
56 unsub_items(){ |
53 for(let item of this.items){ |
57 for(let item of this.items){ |
54 for(let widget of item) { |
58 for(let widget of item) { |
55 widget.unsub(); |
59 widget.unsub(); |
56 } |
60 } |
57 } |
61 } |
58 this.offset = 0; |
|
59 } |
62 } |
60 |
63 |
61 foreach_widgets_do(todo){ |
64 unsub(){ |
|
65 this.unsub_items(); |
|
66 this.offset = 0; |
|
67 this.relativeness = undefined; |
|
68 } |
|
69 |
|
70 sub_items(){ |
62 for(let i = 0; i < this.items.length; i++) { |
71 for(let i = 0; i < this.items.length; i++) { |
63 let item = this.items[i]; |
72 let item = this.items[i]; |
64 let orig_item_index = this.index_pool[i]; |
73 let orig_item_index = this.index_pool[i]; |
65 let item_index = this.index_pool[i+this.item_offset]; |
74 let item_index = this.index_pool[i+this.item_offset]; |
66 let item_index_offset = item_index - orig_item_index; |
75 let item_index_offset = item_index - orig_item_index; |
|
76 if(this.relativeness[0]) |
|
77 item_index_offset += this.offset; |
67 for(let widget of item) { |
78 for(let widget of item) { |
68 todo(widget).call(widget, this.offset + item_index_offset); |
79 /* all variables of all widgets in a ForEach are all relative. |
|
80 Really. |
|
81 |
|
82 TODO: allow absolute variables in ForEach widgets |
|
83 */ |
|
84 widget.sub(item_index_offset, widget.indexes.map(_=>true)); |
69 } |
85 } |
70 } |
86 } |
71 } |
87 } |
72 |
88 |
73 sub(new_offset=0){ |
89 sub(new_offset=0, relativeness=[]){ |
74 this.offset = new_offset; |
90 this.offset = new_offset; |
75 this.foreach_widgets_do(w=>w.sub); |
91 this.relativeness = relativeness; |
|
92 this.sub_items(); |
76 } |
93 } |
77 |
94 |
78 apply_cache() { |
95 apply_cache() { |
79 this.foreach_widgets_do(w=>w.apply_cache); |
96 this.items.forEach(item=>item.forEach(widget=>widget.apply_cache())); |
80 } |
97 } |
81 |
98 |
82 on_click(opstr, evt) { |
99 on_click(opstr, evt) { |
83 let new_item_offset = eval(String(this.item_offset)+opstr); |
100 let new_item_offset = eval(String(this.item_offset)+opstr); |
84 if(new_item_offset + this.items.length > this.index_pool.length) { |
101 if(new_item_offset + this.items.length > this.index_pool.length) { |
91 new_item_offset = this.index_pool.length - this.items.length; |
108 new_item_offset = this.index_pool.length - this.items.length; |
92 else |
109 else |
93 new_item_offset = 0; |
110 new_item_offset = 0; |
94 } |
111 } |
95 this.item_offset = new_item_offset; |
112 this.item_offset = new_item_offset; |
96 this.unsub(); |
113 this.unsub_items(); |
97 this.sub(this.offset); |
114 this.sub_items(); |
98 update_subscriptions(); |
115 update_subscriptions(); |
99 need_cache_apply.push(this); |
116 need_cache_apply.push(this); |
100 jumps_need_update = true; |
117 jumps_need_update = true; |
101 requestHMIAnimation(); |
118 requestHMIAnimation(); |
102 } |
119 } |