102 > "«$widget/@freq»" |
102 > "«$widget/@freq»" |
103 otherwise |
103 otherwise |
104 > undefined |
104 > undefined |
105 } |
105 } |
106 |
106 |
107 | "«@id»": new «$widget/@type»Widget ("«@id»",«$freq»,[«$args»],[«$indexes»],[«$minmaxes»],{ |
107 const "has_enable" choose { |
|
108 when "$widget/@has_enable = 'yes'" |
|
109 > true |
|
110 otherwise |
|
111 > false |
|
112 } |
|
113 |
|
114 | "«@id»": new «$widget/@type»Widget ("«@id»",«$freq»,[«$args»],[«$indexes»],[«$minmaxes»],«$has_enable»,{ |
108 apply "$widget", mode="widget_defs" with "hmi_element","."; |
115 apply "$widget", mode="widget_defs" with "hmi_element","."; |
109 | })`if "position()!=last()" > ,` |
116 | })`if "position()!=last()" > ,` |
110 } |
117 } |
111 |
118 |
112 emit "preamble:local-variable-indexes" { |
119 emit "preamble:local-variable-indexes" { |
216 offset = 0; |
223 offset = 0; |
217 frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */ |
224 frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */ |
218 unsubscribable = false; |
225 unsubscribable = false; |
219 pending_animate = false; |
226 pending_animate = false; |
220 |
227 |
221 constructor(elt_id, freq, args, indexes, minmaxes, members){ |
228 constructor(elt_id, freq, args, indexes, minmaxes, has_enable, members){ |
222 this.element_id = elt_id; |
229 this.element_id = elt_id; |
223 this.element = id(elt_id); |
230 this.element = id(elt_id); |
224 this.args = args; |
231 this.args = args; |
225 this.indexes = indexes; |
232 this.indexes = indexes; |
|
233 this.indexes_length = indexes.length; |
226 this.minmaxes = minmaxes; |
234 this.minmaxes = minmaxes; |
|
235 this.has_enable = has_enable; |
227 Object.keys(members).forEach(prop => this[prop]=members[prop]); |
236 Object.keys(members).forEach(prop => this[prop]=members[prop]); |
228 this.lastapply = indexes.map(() => undefined); |
237 this.lastapply = indexes.map(() => undefined); |
229 this.inhibit = indexes.map(() => undefined); |
238 this.inhibit = indexes.map(() => undefined); |
230 this.pending = indexes.map(() => undefined); |
239 this.pending = indexes.map(() => undefined); |
231 this.bound_uninhibit = this.uninhibit.bind(this); |
240 this.bound_uninhibit = this.uninhibit.bind(this); |
265 init.call(this); |
274 init.call(this); |
266 } catch(err) { |
275 } catch(err) { |
267 console.log(err); |
276 console.log(err); |
268 } |
277 } |
269 } |
278 } |
|
279 |
|
280 if(this.has_enable){ |
|
281 this.disabled_elt = null; |
|
282 this.enabled_elts = []; |
|
283 this.enable_state = false; |
|
284 this.enable_displayed_state = false; |
|
285 for(let child of Array.from(this.element.children)){ |
|
286 if(child.getAttribute("inkscape:label")=="disabled"){ |
|
287 this.disabled_elt = child; |
|
288 }else{ |
|
289 this.enabled_elts.push(child); |
|
290 this.element.removeChild(child); |
|
291 } |
|
292 } |
|
293 } |
270 } |
294 } |
271 |
295 |
272 unsub(){ |
296 unsub(){ |
273 /* remove subsribers */ |
297 /* remove subsribers */ |
274 if(!this.unsubscribable) |
298 if(!this.unsubscribable) |
275 for(let i = 0; i < this.indexes.length; i++) { |
299 for(let i = 0; i < this.indexes_length; i++) { |
276 /* flush updates pending because of inhibition */ |
300 /* flush updates pending because of inhibition */ |
277 let inhibition = this.inhibit[i]; |
301 let inhibition = this.inhibit[i]; |
278 if(inhibition != undefined){ |
302 if(inhibition != undefined){ |
279 clearTimeout(inhibition); |
303 clearTimeout(inhibition); |
280 this.lastapply[i] = undefined; |
304 this.lastapply[i] = undefined; |
299 this.offset = new_offset; |
323 this.offset = new_offset; |
300 this.relativeness = relativeness; |
324 this.relativeness = relativeness; |
301 this.container_id = container_id ; |
325 this.container_id = container_id ; |
302 /* add this's subsribers */ |
326 /* add this's subsribers */ |
303 if(!this.unsubscribable) |
327 if(!this.unsubscribable) |
304 for(let i = 0; i < this.indexes.length; i++) { |
328 for(let i = 0; i < this.indexes_length; i++) { |
305 let index = this.get_variable_index(i); |
329 let index = this.get_variable_index(i); |
306 if(index == undefined) continue; |
330 if(index == undefined) continue; |
307 subscribers(index).add(this); |
331 subscribers(index).add(this); |
308 } |
332 } |
309 need_cache_apply.push(this); |
333 need_cache_apply.push(this); |
400 } |
424 } |
401 } |
425 } |
402 |
426 |
403 new_hmi_value(index, value, oldval) { |
427 new_hmi_value(index, value, oldval) { |
404 // TODO avoid searching, store index at sub() |
428 // TODO avoid searching, store index at sub() |
405 for(let i = 0; i < this.indexes.length; i++) { |
429 for(let i = 0; i < this.indexes_length; i++) { |
406 let refindex = this.get_variable_index(i); |
430 let refindex = this.get_variable_index(i); |
407 if(refindex == undefined) continue; |
431 if(refindex == undefined) continue; |
408 |
432 |
409 if(index == refindex) { |
433 if(index == refindex) { |
410 this._dispatch(value, oldval, i); |
434 this._dispatch(value, oldval, i); |
418 let [new_val, old_val] = this.incoming[index]; |
442 let [new_val, old_val] = this.incoming[index]; |
419 this.incoming[index] = undefined; |
443 this.incoming[index] = undefined; |
420 this.dispatch(new_val, old_val, index); |
444 this.dispatch(new_val, old_val, index); |
421 } |
445 } |
422 |
446 |
|
447 enable(enabled){ |
|
448 if(this.enable_state != enabled){ |
|
449 this.enable_state = enabled; |
|
450 this.request_animate(); |
|
451 } |
|
452 } |
|
453 |
|
454 animate_enable(){ |
|
455 if(this.enable_state && !this.enable_displayed_state){ |
|
456 //show widget |
|
457 for(let child of this.enabled_elts){ |
|
458 this.element.appendChild(child); |
|
459 } |
|
460 |
|
461 //hide disabled content |
|
462 if(this.disabled_elt && this.disabled_elt.parentNode != null) |
|
463 this.element.removeChild(this.disabled_elt); |
|
464 |
|
465 this.enable_displayed_state = true; |
|
466 |
|
467 }else if(!this.enable_state && this.enable_displayed_state){ |
|
468 |
|
469 //hide widget |
|
470 for(let child of this.enabled_elts){ |
|
471 if(child.parentNode != null) |
|
472 this.element.removeChild(child); |
|
473 } |
|
474 |
|
475 //show disabled content |
|
476 if(this.disabled_elt) |
|
477 this.element.appendChild(this.disabled_elt); |
|
478 |
|
479 this.enable_displayed_state = false; |
|
480 } |
|
481 } |
|
482 |
423 _dispatch(value, oldval, varnum) { |
483 _dispatch(value, oldval, varnum) { |
424 let dispatch = this.dispatch; |
484 let dispatch = this.dispatch; |
425 if(dispatch != undefined){ |
485 let has_dispatch = dispatch != undefined; |
|
486 let is_enable_var = this.has_enable && (varnum == (this.indexes_length - 1)); |
|
487 if(has_dispatch || is_enable_var){ |
426 if(this.deafen[varnum] == undefined){ |
488 if(this.deafen[varnum] == undefined){ |
427 let now = Date.now(); |
489 let now = Date.now(); |
428 let min_interval = 1000/this.frequency; |
490 let min_interval = 1000/this.frequency; |
429 let lastdispatch = this.lastdispatch[varnum]; |
491 let lastdispatch = this.lastdispatch[varnum]; |
430 if(lastdispatch == undefined || now > lastdispatch + min_interval){ |
492 if(lastdispatch == undefined || now > lastdispatch + min_interval){ |
431 this.lastdispatch[varnum] = now; |
493 this.lastdispatch[varnum] = now; |
432 try { |
494 if(has_dispatch) try { |
433 dispatch.call(this, value, oldval, varnum); |
495 dispatch.call(this, value, oldval, varnum); |
434 } catch(err) { |
496 } catch(err) { |
435 console.log(err); |
497 console.log(err); |
436 } |
498 } |
|
499 if(is_enable_var) try { |
|
500 this.enable(Boolean(value)); |
|
501 } catch(err) { |
|
502 console.log(err); |
|
503 } |
437 } |
504 } |
438 else { |
505 else { |
439 let elapsed = now - lastdispatch; |
506 let elapsed = now - lastdispatch; |
440 this.incoming[varnum] = [value, oldval]; |
507 this.incoming[varnum] = [value, oldval]; |
441 this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum); |
508 this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum); |