SVGHMI: continue rework of Jump widget to cope with Enable Expressions.
authorEdouard Tisserant
Fri, 02 Sep 2022 10:46:05 +0200
changeset 3596 9c725829d8f0
parent 3595 375626e60b63
child 3597 f69c68cffec3
SVGHMI: continue rework of Jump widget to cope with Enable Expressions.

Questioning widget's activity and disability all together.
Now active/inactive/disable masquarade is all managed in widgets_common.
Propagated changes to widget already using activity (buttons)
svghmi/widget_button.ysl2
svghmi/widget_jump.ysl2
svghmi/widget_keypad.ysl2
svghmi/widget_tooglebutton.ysl2
svghmi/widgets_common.ysl2
tests/projects/svghmi_scrollbar/plc.xml
--- a/svghmi/widget_button.ysl2	Wed Aug 31 12:16:09 2022 +0200
+++ b/svghmi/widget_button.ysl2	Fri Sep 02 10:46:05 2022 +0200
@@ -151,7 +151,7 @@
     |     }
 }
 template "show", mode="actions" {
-    |         this.display = "«@eltname»";
+    |         this.activity_state = «@eltname = 'active'»;
     |         this.request_animate();
 }
 template "hmi-value", mode="actions" {
@@ -164,7 +164,6 @@
 function "generated_button_class" {
     param "fsm";
 
-    |     display = "inactive";
     |     state = "init";
 
     |     dispatch(value) {
@@ -182,14 +181,10 @@
 
     apply "$fsm", mode="actions";
 
-    |     animate(){
-    |         this.set_activation_state(this.display == "active");
-    |     }
-
     |     init() {
     |         this.bound_onmouseup = this.onmouseup.bind(this);
     |         this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
-    |         this.set_activation_state(undefined);
+    |         this.activity_state = undefined;
     |     }
 }
 
--- a/svghmi/widget_jump.ysl2	Wed Aug 31 12:16:09 2022 +0200
+++ b/svghmi/widget_jump.ysl2	Fri Sep 02 10:46:05 2022 +0200
@@ -6,7 +6,7 @@
     Jump widget brings focus to a different page. Mandatory first argument
     gives name of the page.
 
-    If first path is pointint to HMI_NODE variable is used as new reference 
+    If first path is pointint to HMI_NODE variable is used as new reference
     when jumping to a relative page.
 
     Additional arguments are unordered options:
@@ -14,12 +14,12 @@
     - Absolute: force page jump to be not relative even if first path is of type HMI_NODE
 
     - name=value: Notify jump by setting variable with path having same name assigned
-        
+
     "active"+"inactive" labeled elements can be provided and reflect current
     page being shown.
 
     Exemples:
-    
+
     Relative jump:
 
     HMI:Jump:RelativePage@/PUMP9
@@ -47,46 +47,38 @@
 widget_class("Jump") {
 ||
         activable = false;
-        active = false;
         frequency = 2;
 
-        update_activity() {
-            this.set_activation_state(this.active);
-        }
-
-        update_disability() {
-            this.animate_enable();
-            if(this.enable_state) {
-                this.update_activity();
-            }
-        }
-
         make_on_click() {
             let that = this;
             const name = this.args[0];
             return function(evt){
-                /* TODO: in order to allow jumps to page selected through for exemple a dropdown,
-                   support path pointing to local variable whom value 
-                   would be an HMI_TREE index and then jump to a relative page not hard-coded in advance */
+                /* TODO: in order to allow jumps to page selected through
+                   for exemple a dropdown, support path pointing to local
+                   variable whom value would be an HMI_TREE index and then
+                   jump to a relative page not hard-coded in advance
+                */
                 if(that.enable_state) {
-                    const index = (that.is_relative && that.indexes.length > 0) ? that.indexes[0] + that.offset : undefined;
+                    const index =
+                        (that.is_relative && that.indexes.length > 0) ?
+                        that.indexes[0] + that.offset : undefined;
                     fading_page_switch(name, index);
                 }
             }
         }
 
         notify_page_change(page_name, index) {
+            // called from animate()
             if(this.activable) {
                 const ref_index = this.indexes.length > 0 ? this.indexes[0] + this.offset : undefined;
                 const ref_name = this.args[0];
-                this.active = ((ref_name == undefined || ref_name == page_name) && index == ref_index);
-                this.update_state();
+                this.activity_state = ((ref_name == undefined || ref_name == page_name) && index == ref_index);
+                // Since called from animate, update activity directly
+                if(this.enable_displayed_state && this.has_activity) {
+                    this.animate_activity();
+                }
             }
         }
-
-        animate() {
-            this.update_state();
-        }
 ||
 }
 
@@ -105,17 +97,6 @@
     if "$has_activity" {
     |         this.activable = true;
     }
-    >         this.update_state = 
-    choose {
-        when "$jump_disability" {
-            > this.update_disability
-        }
-        when "$has_activity" {
-            > this.update_activity
-        }
-        otherwise > function(){}
-    }
-    > ;\n
 
     >         this.is_relative = 
     choose{
@@ -172,6 +153,7 @@
 var jump_history = [[default_page, undefined]];
 
 function update_jumps() {
+    // called from animate()
     page_desc[current_visible_page].jumps.map(w=>w.notify_page_change(current_visible_page,current_page_index));
     jumps_need_update = false;
 };
--- a/svghmi/widget_keypad.ysl2	Wed Aug 31 12:16:09 2022 +0200
+++ b/svghmi/widget_keypad.ysl2	Fri Sep 02 10:46:05 2022 +0200
@@ -118,11 +118,11 @@
              }
              if(this.Shift_sub && this.shift != this._shift){
                  this._shift = this.shift;
-                 set_activation_state(this.Shift_sub, this.shift);
+                 set_activity_state(this.Shift_sub, this.shift);
              }
              if(this.CapsLock_sub && this.caps != this._caps){
                  this._caps = this.caps;
-                 set_activation_state(this.CapsLock_sub, this.caps);
+                 set_activity_state(this.CapsLock_sub, this.caps);
              }
          }
     ||
--- a/svghmi/widget_tooglebutton.ysl2	Wed Aug 31 12:16:09 2022 +0200
+++ b/svghmi/widget_tooglebutton.ysl2	Fri Sep 02 10:46:05 2022 +0200
@@ -18,33 +18,27 @@
 widget_class("ToggleButton") {
     ||
         frequency = 5;
-        state = 0;
         active_style = undefined;
         inactive_style = undefined;
 
         dispatch(value) {
-            this.state = value;
+            this.actvity_state = Boolean(value);
             //redraw toggle button
             this.request_animate();
         }
 
         on_click(evt) {
             //toggle state and apply
-            this.state = this.state ? false : true;
-            this.apply_hmi_value(0, this.state);
+            this.activity_state = this.activity_state ? false : true;
+            this.apply_hmi_value(0, this.activity_state);
 
             //redraw toggle button
             this.request_animate();
         }
 
-        animate(){
-            // redraw toggle button on screen refresh
-            this.set_activation_state(this.state);
-        }
-
         init() {
             this.element.onclick = (evt) => this.on_click(evt);
-            this.set_activation_state(undefined);
+            this.activity_state = undefined;
         }
     ||
 }
--- a/svghmi/widgets_common.ysl2	Wed Aug 31 12:16:09 2022 +0200
+++ b/svghmi/widgets_common.ysl2	Fri Sep 02 10:46:05 2022 +0200
@@ -30,6 +30,7 @@
     value "$activity";
     const "has_activity","string-length($activity)>0";
     |     },
+    |     has_activity: «$has_activity»,
 };
 
 decl activable() alias - {
@@ -233,7 +234,7 @@
         placeholder.parentNode.insertBefore(elt, placeholder);
     }
 
-    function set_activation_state(eltsub, state){
+    function set_activity_state(eltsub, state){
         if(eltsub.active_elt != undefined){
             if(eltsub.active_elt_placeholder == undefined){
                 eltsub.active_elt_placeholder = document.createComment("");
@@ -250,14 +251,6 @@
         }
     }
 
-    function activate_activable(eltsub) {
-        set_activation_state(eltsub, true);
-    }
-
-    function inactivate_activable(eltsub) {
-        set_activation_state(eltsub, false);
-    }
-
     class Widget {
         offset = 0;
         frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */
@@ -268,8 +261,10 @@
             this.element_id = elt_id;
             this.element = id(elt_id);
             this.args = args;
+            
             [this.indexes, this.variables_options] = (variables.length>0) ? zip(...variables) : [[],[]];
             this.indexes_length = this.indexes.length;
+
             this.enable_expr = enable_expr;
             this.enable_state = true;
             this.enable_displayed_state = true;
@@ -478,7 +473,8 @@
             this.deafen[index] = undefined;
             let [new_val, old_val] = this.incoming[index];
             this.incoming[index] = undefined;
-            this.dispatch(new_val, old_val, index);
+            if(this.dispatch)
+                this.dispatch(new_val, old_val, index);
         }
 
         enable(enabled){
@@ -514,6 +510,9 @@
                     this.element.appendChild(this.disabled_elt);
 
                 this.enable_displayed_state = false;
+
+                // once disabled activity display is lost
+                this.activity_displayed_state = undefined;
             }
         }
 
@@ -553,8 +552,13 @@
         _animate(){
             if(this.enable_expr)
                 this.animate_enable();
-            if(this.animate != undefined && (!this.enable_expr || this.enable_state))
-                this.animate();
+            // inhibit widget animation when disabled
+            if(!this.enable_expr || this.enable_state){
+                if(this.has_activity)
+                    this.animate_activity();
+                if(this.animate != undefined)
+                    this.animate();
+            }
             this.pending_animate = false;
         }
 
@@ -566,8 +570,11 @@
             }
         }
 
-        set_activation_state(state){
-            set_activation_state(this.activable_sub, state);
+        animate_activity(){
+            if(this.activity_displayed_state != this.activity_state){
+                set_activity_state(this.activable_sub, this.activity_state);
+                this.activity_displayed_state = this.activity_state;
+            }
         }
     }
     ||
--- a/tests/projects/svghmi_scrollbar/plc.xml	Wed Aug 31 12:16:09 2022 +0200
+++ b/tests/projects/svghmi_scrollbar/plc.xml	Fri Sep 02 10:46:05 2022 +0200
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='utf-8'?>
 <project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201">
   <fileHeader companyName="Unknown" productName="Unnamed" productVersion="1" creationDateTime="2019-08-06T14:23:42"/>
-  <contentHeader name="Unnamed" modificationDateTime="2021-09-10T14:17:04">
+  <contentHeader name="Unnamed" modificationDateTime="2022-08-23T09:33:50">
     <coordinateInfo>
       <fbd>
         <scaling x="5" y="5"/>