svghmi/detachable_elements.ysl2
branchsvghmi
changeset 2875 6a12e1084deb
parent 2874 b67af0b8dc72
child 2876 d2adbc273125
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/detachable_elements.ysl2	Tue Mar 17 09:29:04 2020 +0100
@@ -0,0 +1,75 @@
+// detachable_elements.ysl2
+//
+// compute what elements are required by pages
+// and decide where to cut when removing/attaching 
+// pages elements on page switch
+
+// returns all directly or indirectly refered elements
+def "func:refered_elements" {
+    param "elems";
+    const "descend", "$elems/descendant-or-self::svg:*";
+    const "clones", "$descend[self::svg:use]";
+    const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]";
+    choose {
+        when "$originals"
+            result "$descend | func:refered_elements($originals)";
+        otherwise
+            result "$descend";
+    }
+}
+
+def "func:all_related_elements" {
+    param "page";
+    const "page_overlapping_geometry", "func:overlapping_geometry($page)";
+    const "page_overlapping_elements", "//svg:*[@id = $page_overlapping_geometry/@Id]";
+    const "page_sub_elements", "func:refered_elements($page | $page_overlapping_elements)";
+    result "$page_sub_elements";
+}
+
+def "func:required_elements" {
+    param "pages"; 
+    choose{
+        when "$pages"{
+            result """func:all_related_elements($pages[1])
+                      | func:required_elements($pages[position()!=1])""";
+        }otherwise{
+            result "/..";
+        }
+    }
+}
+
+const "required_elements",
+    """//svg:defs/descendant-or-self::svg:*
+       | func:required_elements($hmi_pages)/ancestor-or-self::svg:*""";
+
+const "discardable_elements", "//svg:*[not(@id = $required_elements/@id)]";
+
+def "func:sumarized_elements" {
+    param "elements";
+    const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]";
+    const "filled_groups", """$short_list/parent::svg:*[
+        not(descendant::*[
+            not(self::svg:g) and
+            not(@id = $discardable_elements/@id) and
+            not(@id = $short_list/descendant-or-self::*[not(self::svg:g)]/@id)
+        ])]""";
+    const "groups_to_add", "$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]";
+    result "$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]";
+}
+
+def "func:detachable_elements" {
+    param "pages";
+    choose{
+        when "$pages"{
+            result """func:sumarized_elements(func:all_related_elements($pages[1]))
+                      | func:detachable_elements($pages[position()!=1])""";
+        }otherwise{
+            result "/..";
+        }
+    }
+}
+
+// Avoid nested detachables
+const "_detachable_elements", "func:detachable_elements($hmi_pages)";
+const "detachable_elements", "$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]";
+