SVGHMI: take care of path given in HMI:Page and HMI:Jump, but do not apply subscription offset for now. Intermediate commit in a "working" state. svghmi
authorEdouard Tisserant
Fri, 13 Mar 2020 10:36:13 +0100
branchsvghmi
changeset 2869 d9eb50c015d1
parent 2868 8d9757191f05
child 2870 634b43d69897
SVGHMI: take care of path given in HMI:Page and HMI:Jump, but do not apply subscription offset for now. Intermediate commit in a "working" state.
svghmi/gen_index_xhtml.xslt
svghmi/gen_index_xhtml.ysl2
svghmi/svghmi.js
--- a/svghmi/gen_index_xhtml.xslt	Thu Mar 12 13:16:18 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt	Fri Mar 13 10:36:13 2020 +0100
@@ -198,6 +198,11 @@
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:template>
+  <func:function name="func:is_descendant_path">
+    <xsl:param name="ancest"/>
+    <xsl:param name="descend"/>
+    <func:result select="starts-with($descend,$ancest)"/>
+  </func:function>
   <xsl:template mode="inline_svg" match="@* | node()">
     <xsl:if test="not(@id = $discardable_elements/@id)">
       <xsl:copy>
@@ -399,11 +404,20 @@
           </xsl:for-each>
           <xsl:variable name="paths" select="substring-after($description,'@')"/>
           <xsl:for-each select="str:split($paths, '@')">
-            <path>
-              <xsl:attribute name="value">
-                <xsl:value-of select="."/>
-              </xsl:attribute>
-            </path>
+            <xsl:if test="string-length(.) &gt; 0">
+              <path>
+                <xsl:attribute name="value">
+                  <xsl:value-of select="."/>
+                </xsl:attribute>
+                <xsl:variable name="path" select="."/>
+                <xsl:variable name="item" select="$indexed_hmitree/*[@hmipath = $path]"/>
+                <xsl:if test="count($item) = 1">
+                  <xsl:attribute name="index">
+                    <xsl:value-of select="$item/@index"/>
+                  </xsl:attribute>
+                </xsl:if>
+              </path>
+            </xsl:if>
           </xsl:for-each>
         </widget>
       </xsl:if>
@@ -453,23 +467,21 @@
       <xsl:text>    indexes: [
 </xsl:text>
       <xsl:for-each select="$widget/path">
-        <xsl:variable name="hmipath" select="@value"/>
-        <xsl:variable name="hmitree_match" select="$indexed_hmitree/*[@hmipath = $hmipath]"/>
         <xsl:choose>
-          <xsl:when test="count($hmitree_match) = 0">
+          <xsl:when test="not(@index)">
             <xsl:message terminate="no">
               <xsl:text>Widget </xsl:text>
               <xsl:value-of select="$widget/@type"/>
               <xsl:text> id="</xsl:text>
               <xsl:value-of select="$eltid"/>
               <xsl:text>" : No match for path "</xsl:text>
-              <xsl:value-of select="$hmipath"/>
+              <xsl:value-of select="@value"/>
               <xsl:text>" in HMI tree</xsl:text>
             </xsl:message>
           </xsl:when>
           <xsl:otherwise>
             <xsl:text>            </xsl:text>
-            <xsl:value-of select="$hmitree_match/@index"/>
+            <xsl:value-of select="@index"/>
             <xsl:if test="position()!=last()">
               <xsl:text>,</xsl:text>
             </xsl:if>
@@ -551,7 +563,8 @@
       <xsl:variable name="page" select="."/>
       <xsl:variable name="p" select="$geometry[@Id = $page/@id]"/>
       <xsl:variable name="page_all_elements" select="func:all_related_elements($page)"/>
-      <xsl:variable name="all_page_ids" select="$page_all_elements[@id = $hmi_elements/@id and @id != $page/@id]/@id"/>
+      <xsl:variable name="all_page_widgets" select="$hmi_elements[@id = $page_all_elements/@id and @id != $page/@id]"/>
+      <xsl:variable name="page_relative_widgets" select="$all_page_widgets[func:is_descendant_path($desc/path/@value, path/@value)]"/>
       <xsl:variable name="required_detachables" select="func:sumarized_elements($page_all_elements)/&#10;                   ancestor-or-self::*[@id = $detachable_elements/@id]"/>
       <xsl:text>  "</xsl:text>
       <xsl:value-of select="$desc/arg[1]/@value"/>
@@ -571,11 +584,40 @@
       <xsl:value-of select="$p/@h"/>
       <xsl:text>],
 </xsl:text>
-      <xsl:text>    widgets: [
-</xsl:text>
-      <xsl:for-each select="$all_page_ids">
+      <xsl:if test="$desc/path/@value">
+        <xsl:if test="count($desc/path/@index)=0">
+          <xsl:message terminate="no">
+            <xsl:text>Page id="</xsl:text>
+            <xsl:value-of select="$page/@id"/>
+            <xsl:text>" : No match for path "</xsl:text>
+            <xsl:value-of select="$desc/path/@value"/>
+            <xsl:text>" in HMI tree</xsl:text>
+          </xsl:message>
+        </xsl:if>
+        <xsl:text>    page_index: </xsl:text>
+        <xsl:value-of select="$desc/path/@index"/>
+        <xsl:text>,
+</xsl:text>
+      </xsl:if>
+      <xsl:text>    relative_widgets: [
+</xsl:text>
+      <xsl:for-each select="$page_relative_widgets">
         <xsl:text>        hmi_widgets["</xsl:text>
-        <xsl:value-of select="."/>
+        <xsl:value-of select="@id"/>
+        <xsl:text>"]</xsl:text>
+        <xsl:if test="position()!=last()">
+          <xsl:text>,</xsl:text>
+        </xsl:if>
+        <xsl:text>
+</xsl:text>
+      </xsl:for-each>
+      <xsl:text>    ],
+</xsl:text>
+      <xsl:text>    absolute_widgets: [
+</xsl:text>
+      <xsl:for-each select="$all_page_widgets[not(@id = $page_relative_widgets/@id)]">
+        <xsl:text>        hmi_widgets["</xsl:text>
+        <xsl:value-of select="@id"/>
         <xsl:text>"]</xsl:text>
         <xsl:if test="position()!=last()">
           <xsl:text>,</xsl:text>
@@ -1138,7 +1180,7 @@
 </xsl:text>
     <xsl:text>
 </xsl:text>
-    <xsl:text>function switch_page(page_name) {
+    <xsl:text>function switch_page(page_name, root_index) {
 </xsl:text>
     <xsl:text>    if(current_subscribed_page != current_visible_page){
 </xsl:text>
@@ -1164,6 +1206,16 @@
 </xsl:text>
     <xsl:text>
 </xsl:text>
+    <xsl:text>function* chain(a,b){
+</xsl:text>
+    <xsl:text>    yield* a;
+</xsl:text>
+    <xsl:text>    yield* b;
+</xsl:text>
+    <xsl:text>};
+</xsl:text>
+    <xsl:text>
+</xsl:text>
     <xsl:text>function switch_subscribed_page(page_name) {
 </xsl:text>
     <xsl:text>    let old_desc = page_desc[current_subscribed_page];
@@ -1184,7 +1236,7 @@
 </xsl:text>
     <xsl:text>    if(old_desc){
 </xsl:text>
-    <xsl:text>        for(let widget of old_desc.widgets){
+    <xsl:text>        for(let widget of chain(old_desc.absolute_widgets,old_desc.relative_widgets)){
 </xsl:text>
     <xsl:text>            /* remove subsribers */
 </xsl:text>
@@ -1198,7 +1250,7 @@
 </xsl:text>
     <xsl:text>    }
 </xsl:text>
-    <xsl:text>    for(let widget of new_desc.widgets){
+    <xsl:text>    for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){
 </xsl:text>
     <xsl:text>        /* add widget's subsribers */
 </xsl:text>
@@ -1276,7 +1328,7 @@
 </xsl:text>
     <xsl:text>
 </xsl:text>
-    <xsl:text>    for(let widget of new_desc.widgets){
+    <xsl:text>    for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){
 </xsl:text>
     <xsl:text>        for(let index of widget.indexes){
 </xsl:text>
@@ -1621,7 +1673,7 @@
     <xsl:param name="hmi_element"/>
     <xsl:text>    on_click: function(evt) {
 </xsl:text>
-    <xsl:text>        switch_page(this.args[0]);
+    <xsl:text>        switch_page(this.args[0], this.indexes[0]);
 </xsl:text>
     <xsl:text>    },
 </xsl:text>
--- a/svghmi/gen_index_xhtml.ysl2	Thu Mar 12 13:16:18 2020 +0100
+++ b/svghmi/gen_index_xhtml.ysl2	Fri Mar 13 10:36:13 2020 +0100
@@ -305,6 +305,11 @@
     }
 
 
+    def "func:is_descendant_path" {
+        param "ancest";
+        param "descend";
+        result "starts-with($descend,$ancest)";
+    }
 
     //////////////// Inline SVG
 
@@ -501,8 +506,12 @@
             }
             const "paths", "substring-after($description,'@')";
             foreach "str:split($paths, '@')" {
-                path {
+                if "string-length(.) > 0" path {
                     attrib "value" > «.»
+                    const "path", ".";
+                    const "item", "$indexed_hmitree/*[@hmipath = $path]";
+                    if "count($item) = 1"
+                        attrib "index" > «$item/@index»
                 }
             }
         }
@@ -548,14 +557,12 @@
         |     ],
         |     indexes: [
             foreach "$widget/path" {
-                const "hmipath","@value";
-                const "hmitree_match","$indexed_hmitree/*[@hmipath = $hmipath]";
                 choose {
-                    when "count($hmitree_match) = 0" {
-                        warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«$hmipath»" in HMI tree
+                    when "not(@index)" {
+                        warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«@value»" in HMI tree
                     }
                     otherwise {
-        |             «$hmitree_match/@index»`if "position()!=last()" > ,`
+        |             «@index»`if "position()!=last()" > ,`
                     }
                 }
             }
@@ -593,7 +600,10 @@
 
             const "page_all_elements", "func:all_related_elements($page)";
 
-            const "all_page_ids","$page_all_elements[@id = $hmi_elements/@id and @id != $page/@id]/@id";
+            const "all_page_widgets","$hmi_elements[@id = $page_all_elements/@id and @id != $page/@id]";
+
+            const "page_relative_widgets",
+                "$all_page_widgets[func:is_descendant_path($desc/path/@value, path/@value)]";
 
             // Take closest ancestor in detachable_elements
             // since nested detachable elements are filtered out
@@ -604,9 +614,19 @@
             |   "«$desc/arg[1]/@value»": {
             |     widget: hmi_widgets["«@id»"],
             |     bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»],
-            |     widgets: [
-            foreach "$all_page_ids" {
-            |         hmi_widgets["«.»"]`if "position()!=last()" > ,`
+            if "$desc/path/@value" {
+                if "count($desc/path/@index)=0"
+                    warning > Page id="«$page/@id»" : No match for path "«$desc/path/@value»" in HMI tree
+            |     page_index: «$desc/path/@index»,
+            }
+            |     relative_widgets: [
+            foreach "$page_relative_widgets" {
+            |         hmi_widgets["«@id»"]`if "position()!=last()" > ,`
+            }
+            |     ],
+            |     absolute_widgets: [
+            foreach "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" {
+            |         hmi_widgets["«@id»"]`if "position()!=last()" > ,`
             }
             |     ],
             |     required_detachables: {
@@ -824,7 +844,7 @@
     template "widget[@type='Jump']", mode="widget_defs" {
         param "hmi_element";
         |     on_click: function(evt) {
-        |         switch_page(this.args[0]);
+        |         switch_page(this.args[0], this.indexes[0]);
         |     },
         |     init: function() {
         /* registering event this way doies not "click" through svg:use 
--- a/svghmi/svghmi.js	Thu Mar 12 13:16:18 2020 +0100
+++ b/svghmi/svghmi.js	Fri Mar 13 10:36:13 2020 +0100
@@ -257,7 +257,7 @@
     }
 };
 
-function switch_page(page_name) {
+function switch_page(page_name, root_index) {
     if(current_subscribed_page != current_visible_page){
         /* page switch already going */
         /* TODO LOG ERROR */
@@ -270,6 +270,11 @@
     switch_subscribed_page(page_name);
 };
 
+function* chain(a,b){
+    yield* a;
+    yield* b;
+};
+
 function switch_subscribed_page(page_name) {
     let old_desc = page_desc[current_subscribed_page];
     let new_desc = page_desc[page_name];
@@ -280,14 +285,14 @@
     }
 
     if(old_desc){
-        for(let widget of old_desc.widgets){
+        for(let widget of chain(old_desc.absolute_widgets,old_desc.relative_widgets)){
             /* remove subsribers */
             for(let index of widget.indexes){
                 subscribers[index].delete(widget);
             }
         }
     }
-    for(let widget of new_desc.widgets){
+    for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){
         /* add widget's subsribers */
         for(let index of widget.indexes){
             subscribers[index].add(widget);
@@ -326,7 +331,7 @@
         }
     }
 
-    for(let widget of new_desc.widgets){
+    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 cached_val = cache[index];