svghmi/hmi_tree.ysl2
changeset 3302 c89fc366bebd
parent 3221 3d307ad803ea
child 3381 3a0908b0319d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/hmi_tree.ysl2	Thu Sep 02 21:36:29 2021 +0200
@@ -0,0 +1,129 @@
+// hmi_tree.ysl2
+
+
+// HMI Tree computed from VARIABLES.CSV in svghmi.py
+const "hmitree", "ns:GetHMITree()";
+
+const "_categories" {
+    noindex > HMI_PLC_STATUS
+    noindex > HMI_CURRENT_PAGE
+}
+const "categories", "exsl:node-set($_categories)";
+
+// HMI Tree Index
+const "_indexed_hmitree" apply "$hmitree", mode="index";
+const "indexed_hmitree", "exsl:node-set($_indexed_hmitree)";
+
+emit "preamble:hmi-tree" {
+    | var hmi_hash = [«$hmitree/@hash»];
+    |
+    | var heartbeat_index = «$indexed_hmitree/*[@hmipath = '/HEARTBEAT']/@index»;
+    |
+    | var hmitree_types = [
+
+    foreach "$indexed_hmitree/*" 
+    |     /* «@index» */ "«substring(local-name(), 5)»"`if "position()!=last()" > ,`
+
+    | ];
+    |
+    | var hmitree_paths = [
+
+    foreach "$indexed_hmitree/*" 
+    |     /* «@index» */ "«@hmipath»"`if "position()!=last()" > ,`
+
+    | ];
+    |
+}
+
+template "*", mode="index" {
+    param "index", "0";
+    param "parentpath", "''";
+    const "content" {
+        const "path"
+            choose {
+                when "count(ancestor::*)=0" > /
+                when "count(ancestor::*)=1" > /«@name»
+                otherwise > «$parentpath»/«@name»
+            }
+        choose {
+            when "not(local-name() = $categories/noindex)" {
+                xsl:copy {
+                    attrib "index" > «$index»
+                    attrib "hmipath" > «$path»
+                    foreach "@*" xsl:copy;
+                }
+                apply "*[1]", mode="index"{
+                     with "index", "$index + 1";
+                     with "parentpath" > «$path»
+                }
+            }
+            otherwise {
+                apply "*[1]", mode="index"{
+                    with "index", "$index";
+                    with "parentpath" > «$path»
+                }
+            }
+        }
+    }
+
+    copy "$content";
+    apply "following-sibling::*[1]", mode="index" {
+        with "index", "$index + count(exsl:node-set($content)/*)";
+        with "parentpath" > «$parentpath»
+    }
+}
+
+include parse_labels.ysl2
+
+const "_parsed_widgets" {
+    widget type="VarInitPersistent" {
+        arg value="0";
+        path value="lang";
+    }
+    apply "$hmi_elements", mode="parselabel";
+}
+
+const "parsed_widgets","exsl:node-set($_parsed_widgets)";
+
+def "func:widget" {
+    param "id";
+    result "$parsed_widgets/widget[@id = $id]";
+}
+
+def "func:is_descendant_path" {
+    param "descend";
+    param "ancest";
+    // TODO : use HMI tree to answer more accurately
+    result "string-length($ancest) > 0 and starts-with($descend,$ancest)";
+}
+
+def "func:same_class_paths" {
+    param "a";
+    param "b";
+    const "class_a", "$indexed_hmitree/*[@hmipath = $a]/@class";
+    const "class_b", "$indexed_hmitree/*[@hmipath = $b]/@class";
+    result "$class_a and $class_b and $class_a = $class_b";
+}
+
+// Debug data
+template "*", mode="testtree"{
+    param "indent", "''";
+    > «$indent» «local-name()» 
+    foreach "@*" > «local-name()»="«.»" 
+    > \n
+    apply "*", mode="testtree" {
+        with "indent" value "concat($indent,'>')"
+    };
+}
+
+emit "debug:hmi-tree" {
+    | Raw HMI tree
+    apply "$hmitree", mode="testtree";
+    |
+    | Indexed HMI tree
+    apply "$indexed_hmitree", mode="testtree";
+    |
+    | Parsed Widgets
+    copy "_parsed_widgets";
+    apply "$parsed_widgets", mode="testtree";
+}