|
1 // detachable_elements.ysl2 |
|
2 // |
|
3 // compute what elements are required by pages |
|
4 // and decide where to cut when removing/attaching |
|
5 // pages elements on page switch |
|
6 |
|
7 const "hmi_pages", "$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"; |
|
8 |
|
9 const "default_page" choose { |
|
10 when "count($hmi_pages) > 1" { |
|
11 const "Home_page", |
|
12 "$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"; |
|
13 choose { |
|
14 when "$Home_page" > Home |
|
15 otherwise { |
|
16 error "No Home page defined!"; |
|
17 } |
|
18 } |
|
19 } |
|
20 when "count($hmi_pages) = 0" { |
|
21 error "No page defined!"; |
|
22 } |
|
23 otherwise > «func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value» |
|
24 } |
|
25 |
|
26 // returns all directly or indirectly refered elements |
|
27 def "func:refered_elements" { |
|
28 param "elems"; |
|
29 const "descend", "$elems/descendant-or-self::svg:*"; |
|
30 const "clones", "$descend[self::svg:use]"; |
|
31 const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]"; |
|
32 choose { |
|
33 when "$originals" |
|
34 result "$descend | func:refered_elements($originals)"; |
|
35 otherwise |
|
36 result "$descend"; |
|
37 } |
|
38 } |
|
39 |
|
40 def "func:all_related_elements" { |
|
41 param "page"; |
|
42 const "page_overlapping_geometry", "func:overlapping_geometry($page)"; |
|
43 const "page_overlapping_elements", "//svg:*[@id = $page_overlapping_geometry/@Id]"; |
|
44 const "page_sub_elements", "func:refered_elements($page | $page_overlapping_elements)"; |
|
45 result "$page_sub_elements"; |
|
46 } |
|
47 |
|
48 def "func:required_elements" { |
|
49 param "pages"; |
|
50 choose{ |
|
51 when "$pages"{ |
|
52 result """func:all_related_elements($pages[1]) |
|
53 | func:required_elements($pages[position()!=1])"""; |
|
54 }otherwise{ |
|
55 result "/.."; |
|
56 } |
|
57 } |
|
58 } |
|
59 |
|
60 const "required_elements", |
|
61 """//svg:defs/descendant-or-self::svg:* |
|
62 | func:required_elements($hmi_pages)/ancestor-or-self::svg:*"""; |
|
63 |
|
64 const "discardable_elements", "//svg:*[not(@id = $required_elements/@id)]"; |
|
65 |
|
66 def "func:sumarized_elements" { |
|
67 param "elements"; |
|
68 const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]"; |
|
69 const "filled_groups", """$short_list/parent::svg:*[ |
|
70 not(descendant::*[ |
|
71 not(self::svg:g) and |
|
72 not(@id = $discardable_elements/@id) and |
|
73 not(@id = $short_list/descendant-or-self::*[not(self::svg:g)]/@id) |
|
74 ])]"""; |
|
75 const "groups_to_add", "$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"; |
|
76 result "$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]"; |
|
77 } |
|
78 |
|
79 def "func:detachable_elements" { |
|
80 param "pages"; |
|
81 choose{ |
|
82 when "$pages"{ |
|
83 result """func:sumarized_elements(func:all_related_elements($pages[1])) |
|
84 | func:detachable_elements($pages[position()!=1])"""; |
|
85 }otherwise{ |
|
86 result "/.."; |
|
87 } |
|
88 } |
|
89 } |
|
90 |
|
91 // Avoid nested detachables |
|
92 const "_detachable_elements", "func:detachable_elements($hmi_pages)"; |
|
93 const "detachable_elements", "$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]"; |
|
94 |
|
95 def "func:is_descendant_path" { |
|
96 param "descend"; |
|
97 param "ancest"; |
|
98 result "string-length($ancest) > 0 and starts-with($descend,$ancest)"; |
|
99 } |
|
100 |
|
101 template "svg:*", mode="page_desc" { |
|
102 const "desc", "func:parselabel(@inkscape:label)/widget"; |
|
103 const "page", "."; |
|
104 const "p", "$geometry[@Id = $page/@id]"; |
|
105 |
|
106 const "page_all_elements", "func:all_related_elements($page)"; |
|
107 |
|
108 const "all_page_widgets","$hmi_elements[@id = $page_all_elements/@id and @id != $page/@id]"; |
|
109 |
|
110 const "page_relative_widgets", |
|
111 "$all_page_widgets[func:is_descendant_path(func:parselabel(@inkscape:label)/widget/path/@value, $desc/path/@value)]"; |
|
112 |
|
113 // Take closest ancestor in detachable_elements |
|
114 // since nested detachable elements are filtered out |
|
115 const "required_detachables", |
|
116 """func:sumarized_elements($page_all_elements)/ |
|
117 ancestor-or-self::*[@id = $detachable_elements/@id]"""; |
|
118 |
|
119 | "«$desc/arg[1]/@value»": { |
|
120 | widget: hmi_widgets["«@id»"], |
|
121 | bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»], |
|
122 if "$desc/path/@value" { |
|
123 if "count($desc/path/@index)=0" |
|
124 warning > Page id="«$page/@id»" : No match for path "«$desc/path/@value»" in HMI tree |
|
125 | page_index: «$desc/path/@index», |
|
126 } |
|
127 | relative_widgets: [ |
|
128 foreach "$page_relative_widgets" { |
|
129 | hmi_widgets["«@id»"]`if "position()!=last()" > ,` |
|
130 } |
|
131 | ], |
|
132 | absolute_widgets: [ |
|
133 foreach "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" { |
|
134 | hmi_widgets["«@id»"]`if "position()!=last()" > ,` |
|
135 } |
|
136 | ], |
|
137 | required_detachables: { |
|
138 foreach "$required_detachables" { |
|
139 | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` |
|
140 } |
|
141 | } |
|
142 | }`if "position()!=last()" > ,` |
|
143 } |
|
144 |
|
145 function "debug_detachables" { |
|
146 foreach "$detachable_elements"{ |
|
147 | «@id» |
|
148 } |
|
149 } |
|
150 !debug_output_calls.append("debug_detachables") |