// detachable_pages.ysl2 // // compute what elements are required by pages // and decide where to cut when removing/attaching // pages elements on page switch const "hmi_pages_descs", "$parsed_widgets/widget[@type = 'Page']"; const "hmi_pages", "$hmi_elements[@id = $hmi_pages_descs/@id]"; const "default_page" choose { when "count($hmi_pages) > 1" { choose { when "$hmi_pages_descs/arg[1]/@value = 'Home'" > Home otherwise { error "No Home page defined!"; } } } when "count($hmi_pages) = 0" { error "No page defined!"; } otherwise > «func:widget($hmi_pages/@id)/arg[1]/@value» } // 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)]"; const "forEach_widgets_ids", "$parsed_widgets/widget[@type = 'ForEach']/@id"; const "forEach_widgets", "$hmi_elements[@id = $forEach_widgets_ids]"; const "in_forEach_widget_ids", "func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]/@id"; template "svg:*", mode="page_desc" { const "desc", "func:widget(@id)"; const "page", "."; const "p", "$geometry[@Id = $page/@id]"; const "page_all_elements", "func:all_related_elements($page)"; const "all_page_widgets","$hmi_elements[@id = $page_all_elements/@id and @id != $page/@id]"; const "page_managed_widgets","$all_page_widgets[not(@id=$in_forEach_widget_ids)]"; const "page_relative_widgets", "$page_managed_widgets[func:is_descendant_path(func:widget(@id)/path/@value, $desc/path/@value)]"; // Take closest ancestor in detachable_elements // since nested detachable elements are filtered out const "required_detachables", """func:sumarized_elements($page_all_elements)/ ancestor-or-self::*[@id = $detachable_elements/@id]"""; | "«$desc/arg[1]/@value»": { | widget: hmi_widgets["«@id»"], | bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»], 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 "$page_managed_widgets[not(@id = $page_relative_widgets/@id)]" { | hmi_widgets["«@id»"]`if "position()!=last()" > ,` } | ], | jumps: [ foreach "$parsed_widgets/widget[@id = $all_page_widgets/@id and @type='Jump']" { const "_id","@id"; const "opts" call "jump_widget_activity" with "hmi_element", "$hmi_elements[@id=$_id]"; if "string-length($opts)>0" | hmi_widgets["«@id»"]`if "position()!=last()" > ,` } | ], | required_detachables: { foreach "$required_detachables" { | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` } | } /* TODO generate some code for init() instead */ apply "$parsed_widgets/widget[@id = $all_page_widgets/@id]", mode="per_page_widget_template"{ with "page_desc", "$desc"; } | }`if "position()!=last()" > ,` } template "*", mode="per_page_widget_template"; reflect:detachable_pages; template "reflect:detachable-pages", mode="debug" { | DETACHABLES: foreach "$detachable_elements"{ | «@id» } | In Foreach: foreach "$in_forEach_widget_ids"{ | «.» } }