# HG changeset patch # User Edouard Tisserant # Date 1584092173 -3600 # Node ID d9eb50c015d1c9e1ab9f10b2b9026d9902909775 # Parent 8d9757191f0533662fc59d99d403554298df9c66 SVGHMI: take care of path given in HMI:Page and HMI:Jump, but do not apply subscription offset for now. Intermediate commit in a "working" state. diff -r 8d9757191f05 -r d9eb50c015d1 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Thu Mar 12 13:16:18 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Fri Mar 13 10:36:13 2020 +0100 @@ -198,6 +198,11 @@ </xsl:with-param> </xsl:apply-templates> </xsl:template> + <func:function name="func:is_descendant_path"> + <xsl:param name="ancest"/> + <xsl:param name="descend"/> + <func:result select="starts-with($descend,$ancest)"/> + </func:function> <xsl:template mode="inline_svg" match="@* | node()"> <xsl:if test="not(@id = $discardable_elements/@id)"> <xsl:copy> @@ -399,11 +404,20 @@ </xsl:for-each> <xsl:variable name="paths" select="substring-after($description,'@')"/> <xsl:for-each select="str:split($paths, '@')"> - <path> - <xsl:attribute name="value"> - <xsl:value-of select="."/> - </xsl:attribute> - </path> + <xsl:if test="string-length(.) > 0"> + <path> + <xsl:attribute name="value"> + <xsl:value-of select="."/> + </xsl:attribute> + <xsl:variable name="path" select="."/> + <xsl:variable name="item" select="$indexed_hmitree/*[@hmipath = $path]"/> + <xsl:if test="count($item) = 1"> + <xsl:attribute name="index"> + <xsl:value-of select="$item/@index"/> + </xsl:attribute> + </xsl:if> + </path> + </xsl:if> </xsl:for-each> </widget> </xsl:if> @@ -453,23 +467,21 @@ <xsl:text> indexes: [ </xsl:text> <xsl:for-each select="$widget/path"> - <xsl:variable name="hmipath" select="@value"/> - <xsl:variable name="hmitree_match" select="$indexed_hmitree/*[@hmipath = $hmipath]"/> <xsl:choose> - <xsl:when test="count($hmitree_match) = 0"> + <xsl:when test="not(@index)"> <xsl:message terminate="no"> <xsl:text>Widget </xsl:text> <xsl:value-of select="$widget/@type"/> <xsl:text> id="</xsl:text> <xsl:value-of select="$eltid"/> <xsl:text>" : No match for path "</xsl:text> - <xsl:value-of select="$hmipath"/> + <xsl:value-of select="@value"/> <xsl:text>" in HMI tree</xsl:text> </xsl:message> </xsl:when> <xsl:otherwise> <xsl:text> </xsl:text> - <xsl:value-of select="$hmitree_match/@index"/> + <xsl:value-of select="@index"/> <xsl:if test="position()!=last()"> <xsl:text>,</xsl:text> </xsl:if> @@ -551,7 +563,8 @@ <xsl:variable name="page" select="."/> <xsl:variable name="p" select="$geometry[@Id = $page/@id]"/> <xsl:variable name="page_all_elements" select="func:all_related_elements($page)"/> - <xsl:variable name="all_page_ids" select="$page_all_elements[@id = $hmi_elements/@id and @id != $page/@id]/@id"/> + <xsl:variable name="all_page_widgets" select="$hmi_elements[@id = $page_all_elements/@id and @id != $page/@id]"/> + <xsl:variable name="page_relative_widgets" select="$all_page_widgets[func:is_descendant_path($desc/path/@value, path/@value)]"/> <xsl:variable name="required_detachables" select="func:sumarized_elements($page_all_elements)/ ancestor-or-self::*[@id = $detachable_elements/@id]"/> <xsl:text> "</xsl:text> <xsl:value-of select="$desc/arg[1]/@value"/> @@ -571,11 +584,40 @@ <xsl:value-of select="$p/@h"/> <xsl:text>], </xsl:text> - <xsl:text> widgets: [ -</xsl:text> - <xsl:for-each select="$all_page_ids"> + <xsl:if test="$desc/path/@value"> + <xsl:if test="count($desc/path/@index)=0"> + <xsl:message terminate="no"> + <xsl:text>Page id="</xsl:text> + <xsl:value-of select="$page/@id"/> + <xsl:text>" : No match for path "</xsl:text> + <xsl:value-of select="$desc/path/@value"/> + <xsl:text>" in HMI tree</xsl:text> + </xsl:message> + </xsl:if> + <xsl:text> page_index: </xsl:text> + <xsl:value-of select="$desc/path/@index"/> + <xsl:text>, +</xsl:text> + </xsl:if> + <xsl:text> relative_widgets: [ +</xsl:text> + <xsl:for-each select="$page_relative_widgets"> <xsl:text> hmi_widgets["</xsl:text> - <xsl:value-of select="."/> + <xsl:value-of select="@id"/> + <xsl:text>"]</xsl:text> + <xsl:if test="position()!=last()"> + <xsl:text>,</xsl:text> + </xsl:if> + <xsl:text> +</xsl:text> + </xsl:for-each> + <xsl:text> ], +</xsl:text> + <xsl:text> absolute_widgets: [ +</xsl:text> + <xsl:for-each select="$all_page_widgets[not(@id = $page_relative_widgets/@id)]"> + <xsl:text> hmi_widgets["</xsl:text> + <xsl:value-of select="@id"/> <xsl:text>"]</xsl:text> <xsl:if test="position()!=last()"> <xsl:text>,</xsl:text> @@ -1138,7 +1180,7 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text>function switch_page(page_name) { + <xsl:text>function switch_page(page_name, root_index) { </xsl:text> <xsl:text> if(current_subscribed_page != current_visible_page){ </xsl:text> @@ -1164,6 +1206,16 @@ </xsl:text> <xsl:text> </xsl:text> + <xsl:text>function* chain(a,b){ +</xsl:text> + <xsl:text> yield* a; +</xsl:text> + <xsl:text> yield* b; +</xsl:text> + <xsl:text>}; +</xsl:text> + <xsl:text> +</xsl:text> <xsl:text>function switch_subscribed_page(page_name) { </xsl:text> <xsl:text> let old_desc = page_desc[current_subscribed_page]; @@ -1184,7 +1236,7 @@ </xsl:text> <xsl:text> if(old_desc){ </xsl:text> - <xsl:text> for(let widget of old_desc.widgets){ + <xsl:text> for(let widget of chain(old_desc.absolute_widgets,old_desc.relative_widgets)){ </xsl:text> <xsl:text> /* remove subsribers */ </xsl:text> @@ -1198,7 +1250,7 @@ </xsl:text> <xsl:text> } </xsl:text> - <xsl:text> for(let widget of new_desc.widgets){ + <xsl:text> for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){ </xsl:text> <xsl:text> /* add widget's subsribers */ </xsl:text> @@ -1276,7 +1328,7 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> for(let widget of new_desc.widgets){ + <xsl:text> for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){ </xsl:text> <xsl:text> for(let index of widget.indexes){ </xsl:text> @@ -1621,7 +1673,7 @@ <xsl:param name="hmi_element"/> <xsl:text> on_click: function(evt) { </xsl:text> - <xsl:text> switch_page(this.args[0]); + <xsl:text> switch_page(this.args[0], this.indexes[0]); </xsl:text> <xsl:text> }, </xsl:text> diff -r 8d9757191f05 -r d9eb50c015d1 svghmi/gen_index_xhtml.ysl2 --- a/svghmi/gen_index_xhtml.ysl2 Thu Mar 12 13:16:18 2020 +0100 +++ b/svghmi/gen_index_xhtml.ysl2 Fri Mar 13 10:36:13 2020 +0100 @@ -305,6 +305,11 @@ } + def "func:is_descendant_path" { + param "ancest"; + param "descend"; + result "starts-with($descend,$ancest)"; + } //////////////// Inline SVG @@ -501,8 +506,12 @@ } const "paths", "substring-after($description,'@')"; foreach "str:split($paths, '@')" { - path { + if "string-length(.) > 0" path { attrib "value" > «.» + const "path", "."; + const "item", "$indexed_hmitree/*[@hmipath = $path]"; + if "count($item) = 1" + attrib "index" > «$item/@index» } } } @@ -548,14 +557,12 @@ | ], | indexes: [ foreach "$widget/path" { - const "hmipath","@value"; - const "hmitree_match","$indexed_hmitree/*[@hmipath = $hmipath]"; choose { - when "count($hmitree_match) = 0" { - warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«$hmipath»" in HMI tree + when "not(@index)" { + warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«@value»" in HMI tree } otherwise { - | «$hmitree_match/@index»`if "position()!=last()" > ,` + | «@index»`if "position()!=last()" > ,` } } } @@ -593,7 +600,10 @@ const "page_all_elements", "func:all_related_elements($page)"; - const "all_page_ids","$page_all_elements[@id = $hmi_elements/@id and @id != $page/@id]/@id"; + const "all_page_widgets","$hmi_elements[@id = $page_all_elements/@id and @id != $page/@id]"; + + const "page_relative_widgets", + "$all_page_widgets[func:is_descendant_path($desc/path/@value, path/@value)]"; // Take closest ancestor in detachable_elements // since nested detachable elements are filtered out @@ -604,9 +614,19 @@ | "«$desc/arg[1]/@value»": { | widget: hmi_widgets["«@id»"], | bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»], - | widgets: [ - foreach "$all_page_ids" { - | hmi_widgets["«.»"]`if "position()!=last()" > ,` + 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 "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" { + | hmi_widgets["«@id»"]`if "position()!=last()" > ,` } | ], | required_detachables: { @@ -824,7 +844,7 @@ template "widget[@type='Jump']", mode="widget_defs" { param "hmi_element"; | on_click: function(evt) { - | switch_page(this.args[0]); + | switch_page(this.args[0], this.indexes[0]); | }, | init: function() { /* registering event this way doies not "click" through svg:use diff -r 8d9757191f05 -r d9eb50c015d1 svghmi/svghmi.js --- a/svghmi/svghmi.js Thu Mar 12 13:16:18 2020 +0100 +++ b/svghmi/svghmi.js Fri Mar 13 10:36:13 2020 +0100 @@ -257,7 +257,7 @@ } }; -function switch_page(page_name) { +function switch_page(page_name, root_index) { if(current_subscribed_page != current_visible_page){ /* page switch already going */ /* TODO LOG ERROR */ @@ -270,6 +270,11 @@ switch_subscribed_page(page_name); }; +function* chain(a,b){ + yield* a; + yield* b; +}; + function switch_subscribed_page(page_name) { let old_desc = page_desc[current_subscribed_page]; let new_desc = page_desc[page_name]; @@ -280,14 +285,14 @@ } if(old_desc){ - for(let widget of old_desc.widgets){ + for(let widget of chain(old_desc.absolute_widgets,old_desc.relative_widgets)){ /* remove subsribers */ for(let index of widget.indexes){ subscribers[index].delete(widget); } } } - for(let widget of new_desc.widgets){ + for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){ /* add widget's subsribers */ for(let index of widget.indexes){ subscribers[index].add(widget); @@ -326,7 +331,7 @@ } } - for(let widget of new_desc.widgets){ + for(let widget of chain(new_desc.absolute_widgets,new_desc.relative_widgets)){ for(let index of widget.indexes){ /* dispatch current cache in newly opened page widgets */ let cached_val = cache[index];