|
1 // detachable_pages.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_descs", "$parsed_widgets/widget[@type = 'Page']"; |
|
8 const "hmi_pages", "$hmi_elements[@id = $hmi_pages_descs/@id]"; |
|
9 |
|
10 const "default_page" choose { |
|
11 when "count($hmi_pages) > 1" { |
|
12 choose { |
|
13 when "$hmi_pages_descs/arg[1]/@value = 'Home'" > Home |
|
14 otherwise { |
|
15 error > No Home page defined! |
|
16 } |
|
17 } |
|
18 } |
|
19 when "count($hmi_pages) = 0" { |
|
20 error > No page defined! |
|
21 } |
|
22 otherwise > «func:widget($hmi_pages/@id)/arg[1]/@value» |
|
23 } |
|
24 |
|
25 emit "preamble:default-page" { |
|
26 | |
|
27 | var default_page = "«$default_page»"; |
|
28 } |
|
29 |
|
30 const "keypads_descs", "$parsed_widgets/widget[@type = 'Keypad']"; |
|
31 const "keypads", "$hmi_elements[@id = $keypads_descs/@id]"; |
|
32 |
|
33 // returns all directly or indirectly refered elements |
|
34 def "func:refered_elements" { |
|
35 param "elems"; |
|
36 const "descend", "$elems/descendant-or-self::svg:*"; |
|
37 const "clones", "$descend[self::svg:use]"; |
|
38 const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]"; |
|
39 choose { |
|
40 when "$originals" |
|
41 result "$descend | func:refered_elements($originals)"; |
|
42 otherwise |
|
43 result "$descend"; |
|
44 } |
|
45 } |
|
46 |
|
47 // variable "overlapping_geometry" was added for optimization. |
|
48 // It avoids calling func:overlapping_geometry 3 times for each page |
|
49 // (apparently libxml doesn't cache exslt function results) |
|
50 // in order to optimize further, func:overlapping_geometry |
|
51 // should be implemented in python or even C, |
|
52 // as this is still the main bottleneck here |
|
53 const "_overlapping_geometry" { |
|
54 foreach "$hmi_pages | $keypads" { |
|
55 const "k", "concat('overlapping:', @id)"; |
|
56 value "ns:ProgressStart($k, concat('collecting membership of ', @inkscape:label))"; |
|
57 elt { |
|
58 attrib "id" > «@id» |
|
59 copy "func:overlapping_geometry(.)"; |
|
60 } |
|
61 value "ns:ProgressEnd($k)"; |
|
62 } |
|
63 } |
|
64 |
|
65 const "overlapping_geometry", "exsl:node-set($_overlapping_geometry)"; |
|
66 |
|
67 def "func:all_related_elements" { |
|
68 param "page"; |
|
69 const "page_overlapping_geometry", "$overlapping_geometry/elt[@id = $page/@id]/*"; |
|
70 const "page_overlapping_elements", "//svg:*[@id = $page_overlapping_geometry/@Id]"; |
|
71 const "page_sub_elements", "func:refered_elements($page | $page_overlapping_elements)"; |
|
72 result "$page_sub_elements"; |
|
73 } |
|
74 |
|
75 |
|
76 def "func:required_elements" { |
|
77 param "pages"; |
|
78 choose{ |
|
79 when "$pages"{ |
|
80 result """func:all_related_elements($pages[1]) |
|
81 | func:required_elements($pages[position()!=1])"""; |
|
82 }otherwise{ |
|
83 result "/.."; |
|
84 } |
|
85 } |
|
86 } |
|
87 |
|
88 const "required_page_elements", |
|
89 "func:required_elements($hmi_pages | $keypads)/ancestor-or-self::svg:*"; |
|
90 |
|
91 const "hmi_lists_descs", "$parsed_widgets/widget[@type = 'List']"; |
|
92 const "hmi_lists", "$hmi_elements[@id = $hmi_lists_descs/@id]"; |
|
93 |
|
94 const "required_list_elements", "func:refered_elements($hmi_lists[@id = $required_page_elements/@id])"; |
|
95 |
|
96 const "required_elements", "$defs | $required_list_elements | $required_page_elements"; |
|
97 |
|
98 const "discardable_elements", "//svg:*[not(@id = $required_elements/@id)]"; |
|
99 |
|
100 def "func:sumarized_elements" { |
|
101 param "elements"; |
|
102 const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]"; |
|
103 const "filled_groups", """$short_list/parent::*[ |
|
104 not(child::*[ |
|
105 not(@id = $discardable_elements/@id) and |
|
106 not(@id = $short_list/@id) |
|
107 ])]"""; |
|
108 const "groups_to_add", "$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"; |
|
109 result "$groups_to_add | $short_list[not(ancestor::*/@id = $filled_groups/@id)]"; |
|
110 } |
|
111 |
|
112 def "func:detachable_elements" { |
|
113 param "pages"; |
|
114 choose{ |
|
115 when "$pages"{ |
|
116 result """func:sumarized_elements(func:all_related_elements($pages[1])) |
|
117 | func:detachable_elements($pages[position()!=1])"""; |
|
118 }otherwise{ |
|
119 result "/.."; |
|
120 } |
|
121 } |
|
122 } |
|
123 |
|
124 // Avoid nested detachables |
|
125 const "_detachable_elements", "func:detachable_elements($hmi_pages | $keypads)"; |
|
126 const "detachable_elements", "$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]"; |
|
127 |
|
128 emit "declarations:detachable-elements" { |
|
129 | |
|
130 | var detachable_elements = { |
|
131 foreach "$detachable_elements"{ |
|
132 | "«@id»":[id("«@id»"), id("«../@id»")]`if "position()!=last()" > ,` |
|
133 } |
|
134 | } |
|
135 } |
|
136 |
|
137 const "forEach_widgets_ids", "$parsed_widgets/widget[@type = 'ForEach']/@id"; |
|
138 const "forEach_widgets", "$hmi_widgets[@id = $forEach_widgets_ids]"; |
|
139 const "in_forEach_widget_ids", "func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]/@id"; |
|
140 |
|
141 template "svg:*", mode="page_desc" { |
|
142 if "ancestor::*[@id = $hmi_pages/@id]" error > HMI:Page «@id» is nested in another HMI:Page |
|
143 |
|
144 |
|
145 const "desc", "func:widget(@id)"; |
|
146 const "pagename", "$desc/arg[1]/@value"; |
|
147 const "msg", "concat('generating page description ', $pagename)"; |
|
148 value "ns:ProgressStart($pagename, $msg)"; |
|
149 const "page", "."; |
|
150 const "p", "$geometry[@Id = $page/@id]"; |
|
151 |
|
152 const "page_all_elements", "func:all_related_elements($page)"; |
|
153 |
|
154 const "all_page_widgets","$hmi_widgets[@id = $page_all_elements/@id and @id != $page/@id]"; |
|
155 const "page_managed_widgets","$all_page_widgets[not(@id=$in_forEach_widget_ids)]"; |
|
156 const "page_relative_widgets", |
|
157 "$page_managed_widgets[func:is_descendant_path(func:widget(@id)/path/@value, $desc/path/@value)]"; |
|
158 |
|
159 // Take closest ancestor in detachable_elements |
|
160 // since nested detachable elements are filtered out |
|
161 const "sumarized_page", |
|
162 """func:sumarized_elements($page_all_elements)"""; |
|
163 |
|
164 const "required_detachables", |
|
165 """$sumarized_page/ |
|
166 ancestor-or-self::*[@id = $detachable_elements/@id]"""; |
|
167 |
|
168 | "«$pagename»": { |
|
169 //| widget: hmi_widgets["«@id»"], |
|
170 | bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»], |
|
171 if "$desc/path/@value" { |
|
172 if "count($desc/path/@index)=0" |
|
173 warning > Page id="«$page/@id»" : No match for path "«$desc/path/@value»" in HMI tree |
|
174 | page_index: «$desc/path/@index», |
|
175 } |
|
176 | widgets: [ |
|
177 foreach "$page_managed_widgets" { |
|
178 const "widget_paths_relativeness" |
|
179 foreach "func:widget(@id)/path" { |
|
180 value "func:is_descendant_path(@value, $desc/path/@value)"; |
|
181 if "position()!=last()" > , |
|
182 } |
|
183 | [hmi_widgets["«@id»"], [«$widget_paths_relativeness»]]`if "position()!=last()" > ,` |
|
184 } |
|
185 | ], |
|
186 | jumps: [ |
|
187 foreach "$parsed_widgets/widget[@id = $all_page_widgets/@id and @type='Jump']" { |
|
188 | hmi_widgets["«@id»"]`if "position()!=last()" > ,` |
|
189 } |
|
190 | ], |
|
191 | required_detachables: { |
|
192 foreach "$required_detachables" { |
|
193 | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` |
|
194 } |
|
195 | } |
|
196 apply "$parsed_widgets/widget[@id = $all_page_widgets/@id]", mode="widget_page"{ |
|
197 with "page_desc", "$desc"; |
|
198 } |
|
199 | }`if "position()!=last()" > ,` |
|
200 value "ns:ProgressEnd($pagename)"; |
|
201 } |
|
202 |
|
203 emit "definitions:page-desc" { |
|
204 | |
|
205 | var page_desc = { |
|
206 apply "$hmi_pages", mode="page_desc"; |
|
207 | } |
|
208 } |
|
209 |
|
210 template "*", mode="widget_page"; |
|
211 |
|
212 |
|
213 emit "debug:detachable-pages" { |
|
214 | |
|
215 | DETACHABLES: |
|
216 foreach "$detachable_elements"{ |
|
217 | «@id» |
|
218 } |
|
219 | In Foreach: |
|
220 foreach "$in_forEach_widget_ids"{ |
|
221 | «.» |
|
222 } |
|
223 | Overlapping |
|
224 apply "$overlapping_geometry", mode="testtree"; |
|
225 } |