1 // svghmi.js |
1 // svghmi.js |
2 |
2 |
3 var cache = hmitree_types.map(_ignored => undefined); |
3 var cache = hmitree_types.map(_ignored => undefined); |
4 var updates = {}; |
4 var updates = {}; |
5 var page_switch = null; |
|
6 |
5 |
7 function dispatch_value_to_widget(widget, index, value, oldval) { |
6 function dispatch_value_to_widget(widget, index, value, oldval) { |
8 try { |
7 try { |
9 let idxidx = widget.indexes.indexOf(index); |
8 let idxidx = widget.indexes.indexOf(index); |
10 let d = widget.dispatch; |
9 let d = widget.dispatch; |
68 |
67 |
69 // Apply updates recieved through ws.onmessage to subscribed widgets |
68 // Apply updates recieved through ws.onmessage to subscribed widgets |
70 // Do the page swith if any one pending |
69 // Do the page swith if any one pending |
71 // Called on requestAnimationFrame, modifies DOM |
70 // Called on requestAnimationFrame, modifies DOM |
72 function animate() { |
71 function animate() { |
73 if(page_switch != null){ |
72 if(current_subscribed_page != current_visible_page){ |
74 do_switch_page(page_switch); |
73 switch_visible_page(current_subscribed_page); |
75 page_switch=null; |
|
76 } |
74 } |
77 |
75 |
78 for(let index in updates){ |
76 for(let index in updates){ |
79 // serving as a key, index becomes a string |
77 // serving as a key, index becomes a string |
80 // -> pass Number(index) instead |
78 // -> pass Number(index) instead |
81 dispatch_value(Number(index), updates[index]); |
79 dispatch_value(Number(index), updates[index]); |
82 delete updates[index]; |
80 delete updates[index]; |
83 } |
81 } |
|
82 requestAnimationFrameID = null; |
84 } |
83 } |
85 |
84 |
86 var requestAnimationFrameID = null; |
85 var requestAnimationFrameID = null; |
87 function requestHMIAnimation() { |
86 function requestHMIAnimation() { |
88 if(requestAnimationFrameID != null){ |
87 if(requestAnimationFrameID == null){ |
89 window.cancelAnimationFrame(requestAnimationFrameID); |
88 requestAnimationFrameID = window.requestAnimationFrame(animate); |
90 requestAnimationFrameID = null; |
89 } |
91 } |
|
92 requestAnimationFrameID = window.requestAnimationFrame(animate); |
|
93 } |
90 } |
94 |
91 |
95 // Message reception handler |
92 // Message reception handler |
96 // Hash is verified and HMI values updates resulting from binary parsing |
93 // Hash is verified and HMI values updates resulting from binary parsing |
97 // are stored until browser can compute next frame, DOM is left untouched |
94 // are stored until browser can compute next frame, DOM is left untouched |
120 } else { |
117 } else { |
121 throw new Error("Unknown index "+index); |
118 throw new Error("Unknown index "+index); |
122 } |
119 } |
123 }; |
120 }; |
124 // register for rendering on next frame, since there are updates |
121 // register for rendering on next frame, since there are updates |
125 window.requestAnimationFrame(animate); |
122 requestHMIAnimation(); |
126 } catch(err) { |
123 } catch(err) { |
127 // 1003 is for "Unsupported Data" |
124 // 1003 is for "Unsupported Data" |
128 // ws.close(1003, err.message); |
125 // ws.close(1003, err.message); |
129 |
126 |
130 // TODO : remove debug alert ? |
127 // TODO : remove debug alert ? |
245 if(new_val != undefined && old_val != new_val) |
242 if(new_val != undefined && old_val != new_val) |
246 send_hmi_value(index, new_val); |
243 send_hmi_value(index, new_val); |
247 return new_val; |
244 return new_val; |
248 } |
245 } |
249 |
246 |
250 var current_page; |
247 var current_visible_page; |
|
248 var current_subscribed_page; |
251 |
249 |
252 function prepare_svg() { |
250 function prepare_svg() { |
253 for(let eltid in detachable_elements){ |
251 for(let eltid in detachable_elements){ |
254 let [element,parent] = detachable_elements[eltid]; |
252 let [element,parent] = detachable_elements[eltid]; |
255 parent.removeChild(element); |
253 parent.removeChild(element); |
256 } |
254 } |
257 }; |
255 }; |
258 |
256 |
259 function switch_page(page_name) { |
257 function switch_page(page_name) { |
260 page_switch = page_name; |
258 if(current_subscribed_page != current_visible_page){ |
261 window.requestAnimationFrame(animate); |
259 /* page switch already going */ |
262 } |
260 /* TODO LOG ERROR */ |
263 |
261 return; |
264 function do_switch_page(page_name) { |
262 } else if(page_name == current_visible_page){ |
265 let old_desc = page_desc[current_page]; |
263 /* already in that page */ |
|
264 /* TODO LOG ERROR */ |
|
265 return; |
|
266 } |
|
267 switch_subscribed_page(page_name); |
|
268 }; |
|
269 |
|
270 function switch_subscribed_page(page_name) { |
|
271 let old_desc = page_desc[current_subscribed_page]; |
266 let new_desc = page_desc[page_name]; |
272 let new_desc = page_desc[page_name]; |
267 |
273 |
268 if(new_desc == undefined){ |
274 if(new_desc == undefined){ |
269 /* TODO LOG ERROR */ |
275 /* TODO LOG ERROR */ |
270 return; |
276 return; |
275 /* remove subsribers */ |
281 /* remove subsribers */ |
276 for(let index of widget.indexes){ |
282 for(let index of widget.indexes){ |
277 subscribers[index].delete(widget); |
283 subscribers[index].delete(widget); |
278 } |
284 } |
279 } |
285 } |
|
286 } |
|
287 for(let widget of new_desc.widgets){ |
|
288 /* add widget's subsribers */ |
|
289 for(let index of widget.indexes){ |
|
290 subscribers[index].add(widget); |
|
291 } |
|
292 } |
|
293 |
|
294 update_subscriptions(); |
|
295 |
|
296 current_subscribed_page = page_name; |
|
297 |
|
298 requestHMIAnimation(); |
|
299 } |
|
300 |
|
301 function switch_visible_page(page_name) { |
|
302 |
|
303 let old_desc = page_desc[current_visible_page]; |
|
304 let new_desc = page_desc[page_name]; |
|
305 |
|
306 if(old_desc){ |
280 for(let eltid in old_desc.required_detachables){ |
307 for(let eltid in old_desc.required_detachables){ |
281 if(!(eltid in new_desc.required_detachables)){ |
308 if(!(eltid in new_desc.required_detachables)){ |
282 let [element, parent] = old_desc.required_detachables[eltid]; |
309 let [element, parent] = old_desc.required_detachables[eltid]; |
283 parent.removeChild(element); |
310 parent.removeChild(element); |
284 } |
311 } |
295 parent.appendChild(element); |
322 parent.appendChild(element); |
296 } |
323 } |
297 } |
324 } |
298 |
325 |
299 for(let widget of new_desc.widgets){ |
326 for(let widget of new_desc.widgets){ |
300 /* add widget's subsribers */ |
|
301 for(let index of widget.indexes){ |
327 for(let index of widget.indexes){ |
302 subscribers[index].add(widget); |
|
303 /* dispatch current cache in newly opened page widgets */ |
328 /* dispatch current cache in newly opened page widgets */ |
304 let cached_val = cache[index]; |
329 let cached_val = cache[index]; |
305 if(cached_val != undefined) |
330 if(cached_val != undefined) |
306 dispatch_value_to_widget(widget, index, cached_val, cached_val); |
331 dispatch_value_to_widget(widget, index, cached_val, cached_val); |
307 } |
332 } |
308 } |
333 } |
309 |
334 |
310 svg_root.setAttribute('viewBox',new_desc.bbox.join(" ")); |
335 svg_root.setAttribute('viewBox',new_desc.bbox.join(" ")); |
311 current_page = page_name; |
336 current_visible_page = page_name; |
312 |
|
313 window.setTimeout(update_subscriptions,0); |
|
314 }; |
337 }; |
315 |
338 |
316 |
339 |
317 // Once connection established |
340 // Once connection established |
318 ws.onopen = function (evt) { |
341 ws.onopen = function (evt) { |