# HG changeset patch # User Edouard Tisserant # Date 1584440647 -3600 # Node ID 682bce95379598f67df85b861c1da940e3271b09 # Parent d2adbc273125bb4437130448cd58e1112cdb1cee SVGHMI: detachable_elements.ysl2 becomes detachable_pages.ysl2, and includes logic to process pages elements. Other minor code moves. diff -r d2adbc273125 -r 682bce953795 svghmi/detachable_elements.ysl2 --- a/svghmi/detachable_elements.ysl2 Tue Mar 17 10:34:26 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -// 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)]"; - -function "debug_detachables" { - foreach "$detachable_elements"{ - | «@id» - } -} -!debug_output_calls.append("debug_detachables") diff -r d2adbc273125 -r 682bce953795 svghmi/detachable_pages.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/detachable_pages.ysl2 Tue Mar 17 11:24:07 2020 +0100 @@ -0,0 +1,150 @@ +// detachable_elements.ysl2 +// +// compute what elements are required by pages +// and decide where to cut when removing/attaching +// pages elements on page switch + +const "hmi_pages", "$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"; + +const "default_page" choose { + when "count($hmi_pages) > 1" { + const "Home_page", + "$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"; + choose { + when "$Home_page" > Home + otherwise { + error "No Home page defined!"; + } + } + } + when "count($hmi_pages) = 0" { + error "No page defined!"; + } + otherwise > «func:parselabel($hmi_pages/@inkscape:label)/widget/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)]"; + +def "func:is_descendant_path" { + param "descend"; + param "ancest"; + result "string-length($ancest) > 0 and starts-with($descend,$ancest)"; +} + +template "svg:*", mode="page_desc" { + const "desc", "func:parselabel(@inkscape:label)/widget"; + 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_relative_widgets", + "$all_page_widgets[func:is_descendant_path(func:parselabel(@inkscape:label)/widget/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 "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" { + | hmi_widgets["«@id»"]`if "position()!=last()" > ,` + } + | ], + | required_detachables: { + foreach "$required_detachables" { + | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` + } + | } + | }`if "position()!=last()" > ,` +} + +function "debug_detachables" { + foreach "$detachable_elements"{ + | «@id» + } +} +!debug_output_calls.append("debug_detachables") diff -r d2adbc273125 -r 682bce953795 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Tue Mar 17 10:34:26 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Tue Mar 17 11:24:07 2020 +0100 @@ -1,30 +1,7 @@ <?xml version="1.0"?> <xsl:stylesheet xmlns:func="http://exslt.org/functions" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:str="http://exslt.org/strings" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:exsl="http://exslt.org/common" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ns="beremiz" xmlns:cc="http://creativecommons.org/ns#" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/elements/1.1/" extension-element-prefixes="ns func exsl regexp str dyn" version="1.0" exclude-result-prefixes="ns str regexp exsl func dyn"> <xsl:output method="xml" cdata-section-elements="xhtml:script"/> - <xsl:variable name="svg_root_id" select="/svg:svg/@id"/> - <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/> - <xsl:variable name="hmi_pages" select="$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"/> - <xsl:variable name="default_page"> - <xsl:choose> - <xsl:when test="count($hmi_pages) > 1"> - <xsl:variable name="Home_page" select="$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"/> - <xsl:choose> - <xsl:when test="$Home_page"> - <xsl:text>Home</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:message terminate="yes">No Home page defined!</xsl:message> - </xsl:otherwise> - </xsl:choose> - </xsl:when> - <xsl:when test="count($hmi_pages) = 0"> - <xsl:message terminate="yes">No page defined!</xsl:message> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> + <xsl:variable name="hmitree" select="ns:GetHMITree()"/> <xsl:variable name="_categories"> <noindex> <xsl:text>HMI_ROOT</xsl:text> @@ -37,134 +14,6 @@ </noindex> </xsl:variable> <xsl:variable name="categories" select="exsl:node-set($_categories)"/> - <xsl:variable name="geometry" select="ns:GetSVGGeometry()"/> - <xsl:template name="debug_geometry"> - <xsl:text>ID, x, y, w, h -</xsl:text> - <xsl:for-each select="$geometry[@Id = $hmi_elements/@id]"> - <xsl:text> </xsl:text> - <xsl:value-of select="@Id"/> - <xsl:text> </xsl:text> - <xsl:value-of select="@x"/> - <xsl:text> </xsl:text> - <xsl:value-of select="@y"/> - <xsl:text> </xsl:text> - <xsl:value-of select="@w"/> - <xsl:text> </xsl:text> - <xsl:value-of select="@h"/> - <xsl:text> -</xsl:text> - </xsl:for-each> - </xsl:template> - <func:function name="func:intersect_1d"> - <xsl:param name="a0"/> - <xsl:param name="a1"/> - <xsl:param name="b0"/> - <xsl:param name="b1"/> - <xsl:variable name="d0" select="$a0 >= $b0"/> - <xsl:variable name="d1" select="$a1 >= $b1"/> - <xsl:choose> - <xsl:when test="not($d0) and $d1"> - <func:result select="3"/> - </xsl:when> - <xsl:when test="$d0 and not($d1)"> - <func:result select="2"/> - </xsl:when> - <xsl:when test="$d0 and $d1 and $a0 < $b1"> - <func:result select="1"/> - </xsl:when> - <xsl:when test="not($d0) and not($d1) and $b0 < $a1"> - <func:result select="1"/> - </xsl:when> - <xsl:otherwise> - <func:result select="0"/> - </xsl:otherwise> - </xsl:choose> - </func:function> - <func:function name="func:intersect"> - <xsl:param name="a"/> - <xsl:param name="b"/> - <xsl:variable name="x_intersect" select="func:intersect_1d($a/@x, $a/@x+$a/@w, $b/@x, $b/@x+$b/@w)"/> - <xsl:choose> - <xsl:when test="$x_intersect != 0"> - <xsl:variable name="y_intersect" select="func:intersect_1d($a/@y, $a/@y+$a/@h, $b/@y, $b/@y+$b/@h)"/> - <func:result select="$x_intersect * $y_intersect"/> - </xsl:when> - <xsl:otherwise> - <func:result select="0"/> - </xsl:otherwise> - </xsl:choose> - </func:function> - <func:function name="func:overlapping_geometry"> - <xsl:param name="elt"/> - <xsl:variable name="groups" select="/svg:svg | //svg:g"/> - <xsl:variable name="g" select="$geometry[@Id = $elt/@id]"/> - <xsl:variable name="candidates" select="$geometry[@Id != $elt/@id]"/> - <func:result select="$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or (not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]"/> - </func:function> - <func:function name="func:refered_elements"> - <xsl:param name="elems"/> - <xsl:variable name="descend" select="$elems/descendant-or-self::svg:*"/> - <xsl:variable name="clones" select="$descend[self::svg:use]"/> - <xsl:variable name="originals" select="//svg:*[concat('#',@id) = $clones/@xlink:href]"/> - <xsl:choose> - <xsl:when test="$originals"> - <func:result select="$descend | func:refered_elements($originals)"/> - </xsl:when> - <xsl:otherwise> - <func:result select="$descend"/> - </xsl:otherwise> - </xsl:choose> - </func:function> - <func:function name="func:all_related_elements"> - <xsl:param name="page"/> - <xsl:variable name="page_overlapping_geometry" select="func:overlapping_geometry($page)"/> - <xsl:variable name="page_overlapping_elements" select="//svg:*[@id = $page_overlapping_geometry/@Id]"/> - <xsl:variable name="page_sub_elements" select="func:refered_elements($page | $page_overlapping_elements)"/> - <func:result select="$page_sub_elements"/> - </func:function> - <func:function name="func:required_elements"> - <xsl:param name="pages"/> - <xsl:choose> - <xsl:when test="$pages"> - <func:result select="func:all_related_elements($pages[1]) | func:required_elements($pages[position()!=1])"/> - </xsl:when> - <xsl:otherwise> - <func:result select="/.."/> - </xsl:otherwise> - </xsl:choose> - </func:function> - <xsl:variable name="required_elements" select="//svg:defs/descendant-or-self::svg:* | func:required_elements($hmi_pages)/ancestor-or-self::svg:*"/> - <xsl:variable name="discardable_elements" select="//svg:*[not(@id = $required_elements/@id)]"/> - <func:function name="func:sumarized_elements"> - <xsl:param name="elements"/> - <xsl:variable name="short_list" select="$elements[not(ancestor::*/@id = $elements/@id)]"/> - <xsl:variable name="filled_groups" select="$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) ])]"/> - <xsl:variable name="groups_to_add" select="$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"/> - <func:result select="$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]"/> - </func:function> - <func:function name="func:detachable_elements"> - <xsl:param name="pages"/> - <xsl:choose> - <xsl:when test="$pages"> - <func:result select="func:sumarized_elements(func:all_related_elements($pages[1])) | func:detachable_elements($pages[position()!=1])"/> - </xsl:when> - <xsl:otherwise> - <func:result select="/.."/> - </xsl:otherwise> - </xsl:choose> - </func:function> - <xsl:variable name="_detachable_elements" select="func:detachable_elements($hmi_pages)"/> - <xsl:variable name="detachable_elements" select="$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]"/> - <xsl:template name="debug_detachables"> - <xsl:for-each select="$detachable_elements"> - <xsl:text> </xsl:text> - <xsl:value-of select="@id"/> - <xsl:text> -</xsl:text> - </xsl:for-each> - </xsl:template> - <xsl:variable name="hmitree" select="ns:GetHMITree()"/> <xsl:variable name="_indexed_hmitree"> <xsl:apply-templates mode="index" select="$hmitree"/> </xsl:variable> @@ -223,202 +72,6 @@ </xsl:with-param> </xsl:apply-templates> </xsl:template> - <xsl:template mode="testtree" match="*"> - <xsl:param name="indent" select="''"/> - <xsl:value-of select="$indent"/> - <xsl:text> </xsl:text> - <xsl:value-of select="local-name()"/> - <xsl:text> </xsl:text> - <xsl:for-each select="@*"> - <xsl:value-of select="local-name()"/> - <xsl:text>="</xsl:text> - <xsl:value-of select="."/> - <xsl:text>" </xsl:text> - </xsl:for-each> - <xsl:text> -</xsl:text> - <xsl:apply-templates mode="testtree" select="*"> - <xsl:with-param name="indent"> - <xsl:value-of select="concat($indent,'>')"/> - </xsl:with-param> - </xsl:apply-templates> - </xsl:template> - <xsl:template name="debug_hmitree"> - <xsl:text>Raw HMI tree -</xsl:text> - <xsl:apply-templates mode="testtree" select="$hmitree"/> - <xsl:text> -</xsl:text> - <xsl:text>Indexed HMI tree -</xsl:text> - <xsl:apply-templates mode="testtree" select="$indexed_hmitree"/> - </xsl:template> - <func:function name="func:is_descendant_path"> - <xsl:param name="descend"/> - <xsl:param name="ancest"/> - <func:result select="string-length($ancest) > 0 and starts-with($descend,$ancest)"/> - </func:function> - <xsl:template mode="inline_svg" match="@* | node()"> - <xsl:if test="not(@id = $discardable_elements/@id)"> - <xsl:copy> - <xsl:apply-templates mode="inline_svg" select="@* | node()"/> - </xsl:copy> - </xsl:if> - </xsl:template> - <xsl:template mode="inline_svg" match="svg:svg/@width"/> - <xsl:template mode="inline_svg" match="svg:svg/@height"/> - <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:svg"> - <svg> - <xsl:attribute name="preserveAspectRatio"> - <xsl:text>none</xsl:text> - </xsl:attribute> - <xsl:attribute name="height"> - <xsl:text>100vh</xsl:text> - </xsl:attribute> - <xsl:attribute name="width"> - <xsl:text>100vw</xsl:text> - </xsl:attribute> - <xsl:apply-templates mode="inline_svg" select="@* | node()"/> - </svg> - </xsl:template> - <xsl:template mode="inline_svg" match="svg:svg[@viewBox!=concat('0 0 ', @width, ' ', @height)]"> - <xsl:message terminate="yes"> - <xsl:text>ViewBox settings other than X=0, Y=0 and Scale=1 are not supported</xsl:text> - </xsl:message> - </xsl:template> - <xsl:template mode="inline_svg" match="sodipodi:namedview[@units!='px' or @inkscape:document-units!='px']"> - <xsl:message terminate="yes"> - <xsl:text>All units must be set to "px" in Inkscape's document properties</xsl:text> - </xsl:message> - </xsl:template> - <xsl:variable name="to_unlink" select="$hmi_elements[not(@id = $hmi_pages)]//svg:use"/> - <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:use"> - <xsl:choose> - <xsl:when test="@id = $to_unlink/@id"> - <xsl:call-template name="unlink_clone"/> - </xsl:when> - <xsl:otherwise> - <xsl:copy> - <xsl:apply-templates mode="inline_svg" select="@* | node()"/> - </xsl:copy> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - <xsl:variable name="_excluded_use_attrs"> - <name> - <xsl:text>href</xsl:text> - </name> - <name> - <xsl:text>width</xsl:text> - </name> - <name> - <xsl:text>height</xsl:text> - </name> - <name> - <xsl:text>x</xsl:text> - </name> - <name> - <xsl:text>y</xsl:text> - </name> - </xsl:variable> - <xsl:variable name="excluded_use_attrs" select="exsl:node-set($_excluded_use_attrs)"/> - <xsl:template xmlns="http://www.w3.org/2000/svg" name="unlink_clone"> - <g> - <xsl:for-each select="@*[not(local-name() = $excluded_use_attrs/name)]"> - <xsl:attribute name="{name()}"> - <xsl:value-of select="."/> - </xsl:attribute> - </xsl:for-each> - <xsl:variable name="targetid" select="substring-after(@xlink:href,'#')"/> - <xsl:apply-templates mode="unlink_clone" select="//svg:*[@id = $targetid]"> - <xsl:with-param name="seed" select="@id"/> - </xsl:apply-templates> - </g> - </xsl:template> - <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@id"> - <xsl:param name="seed"/> - <xsl:attribute name="id"> - <xsl:value-of select="$seed"/> - <xsl:text>_</xsl:text> - <xsl:value-of select="."/> - </xsl:attribute> - </xsl:template> - <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@*"> - <xsl:copy/> - </xsl:template> - <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="svg:*"> - <xsl:param name="seed"/> - <xsl:choose> - <xsl:when test="@id = $hmi_elements/@id"> - <use> - <xsl:attribute name="xlink:href"> - <xsl:value-of select="concat('#',@id)"/> - </xsl:attribute> - </use> - </xsl:when> - <xsl:otherwise> - <xsl:copy> - <xsl:apply-templates mode="unlink_clone" select="@* | node()"> - <xsl:with-param name="seed" select="$seed"/> - </xsl:apply-templates> - </xsl:copy> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - <xsl:variable name="result_svg"> - <xsl:apply-templates mode="inline_svg" select="/"/> - </xsl:variable> - <xsl:variable name="result_svg_ns" select="exsl:node-set($result_svg)"/> - <xsl:template match="/"> - <xsl:comment> - <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text> - </xsl:comment> - <xsl:comment> - <xsl:text> -</xsl:text> - <xsl:text>debug_geometry: -</xsl:text> - <xsl:call-template name="debug_geometry"/> - <xsl:text> -</xsl:text> - </xsl:comment> - <xsl:comment> - <xsl:text> -</xsl:text> - <xsl:text>debug_detachables: -</xsl:text> - <xsl:call-template name="debug_detachables"/> - <xsl:text> -</xsl:text> - </xsl:comment> - <xsl:comment> - <xsl:text> -</xsl:text> - <xsl:text>debug_hmitree: -</xsl:text> - <xsl:call-template name="debug_hmitree"/> - <xsl:text> -</xsl:text> - </xsl:comment> - <xsl:comment> - <xsl:text>Unlinked : -</xsl:text> - <xsl:for-each select="$to_unlink"> - <xsl:value-of select="@id"/> - <xsl:text> -</xsl:text> - </xsl:for-each> - </xsl:comment> - <html xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/1999/xhtml"> - <head/> - <body style="margin:0;overflow:hidden;"> - <xsl:copy-of select="$result_svg"/> - <script> - <xsl:call-template name="scripts"/> - </script> - </body> - </html> - </xsl:template> <func:function name="func:parselabel"> <xsl:param name="label"/> <xsl:variable name="description" select="substring-after($label,'HMI:')"/> @@ -479,6 +132,445 @@ </xsl:variable> <func:result select="exsl:node-set($ast)"/> </func:function> + <xsl:template mode="testtree" match="*"> + <xsl:param name="indent" select="''"/> + <xsl:value-of select="$indent"/> + <xsl:text> </xsl:text> + <xsl:value-of select="local-name()"/> + <xsl:text> </xsl:text> + <xsl:for-each select="@*"> + <xsl:value-of select="local-name()"/> + <xsl:text>="</xsl:text> + <xsl:value-of select="."/> + <xsl:text>" </xsl:text> + </xsl:for-each> + <xsl:text> +</xsl:text> + <xsl:apply-templates mode="testtree" select="*"> + <xsl:with-param name="indent"> + <xsl:value-of select="concat($indent,'>')"/> + </xsl:with-param> + </xsl:apply-templates> + </xsl:template> + <xsl:template name="debug_hmitree"> + <xsl:text>Raw HMI tree +</xsl:text> + <xsl:apply-templates mode="testtree" select="$hmitree"/> + <xsl:text> +</xsl:text> + <xsl:text>Indexed HMI tree +</xsl:text> + <xsl:apply-templates mode="testtree" select="$indexed_hmitree"/> + </xsl:template> + <xsl:variable name="geometry" select="ns:GetSVGGeometry()"/> + <xsl:template name="debug_geometry"> + <xsl:text>ID, x, y, w, h +</xsl:text> + <xsl:for-each select="$geometry[@Id = $hmi_elements/@id]"> + <xsl:text> </xsl:text> + <xsl:value-of select="@Id"/> + <xsl:text> </xsl:text> + <xsl:value-of select="@x"/> + <xsl:text> </xsl:text> + <xsl:value-of select="@y"/> + <xsl:text> </xsl:text> + <xsl:value-of select="@w"/> + <xsl:text> </xsl:text> + <xsl:value-of select="@h"/> + <xsl:text> +</xsl:text> + </xsl:for-each> + </xsl:template> + <func:function name="func:intersect_1d"> + <xsl:param name="a0"/> + <xsl:param name="a1"/> + <xsl:param name="b0"/> + <xsl:param name="b1"/> + <xsl:variable name="d0" select="$a0 >= $b0"/> + <xsl:variable name="d1" select="$a1 >= $b1"/> + <xsl:choose> + <xsl:when test="not($d0) and $d1"> + <func:result select="3"/> + </xsl:when> + <xsl:when test="$d0 and not($d1)"> + <func:result select="2"/> + </xsl:when> + <xsl:when test="$d0 and $d1 and $a0 < $b1"> + <func:result select="1"/> + </xsl:when> + <xsl:when test="not($d0) and not($d1) and $b0 < $a1"> + <func:result select="1"/> + </xsl:when> + <xsl:otherwise> + <func:result select="0"/> + </xsl:otherwise> + </xsl:choose> + </func:function> + <func:function name="func:intersect"> + <xsl:param name="a"/> + <xsl:param name="b"/> + <xsl:variable name="x_intersect" select="func:intersect_1d($a/@x, $a/@x+$a/@w, $b/@x, $b/@x+$b/@w)"/> + <xsl:choose> + <xsl:when test="$x_intersect != 0"> + <xsl:variable name="y_intersect" select="func:intersect_1d($a/@y, $a/@y+$a/@h, $b/@y, $b/@y+$b/@h)"/> + <func:result select="$x_intersect * $y_intersect"/> + </xsl:when> + <xsl:otherwise> + <func:result select="0"/> + </xsl:otherwise> + </xsl:choose> + </func:function> + <func:function name="func:overlapping_geometry"> + <xsl:param name="elt"/> + <xsl:variable name="groups" select="/svg:svg | //svg:g"/> + <xsl:variable name="g" select="$geometry[@Id = $elt/@id]"/> + <xsl:variable name="candidates" select="$geometry[@Id != $elt/@id]"/> + <func:result select="$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or (not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]"/> + </func:function> + <xsl:variable name="svg_root_id" select="/svg:svg/@id"/> + <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/> + <xsl:variable name="hmi_pages" select="$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"/> + <xsl:variable name="default_page"> + <xsl:choose> + <xsl:when test="count($hmi_pages) > 1"> + <xsl:variable name="Home_page" select="$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"/> + <xsl:choose> + <xsl:when test="$Home_page"> + <xsl:text>Home</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">No Home page defined!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="count($hmi_pages) = 0"> + <xsl:message terminate="yes">No page defined!</xsl:message> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <func:function name="func:refered_elements"> + <xsl:param name="elems"/> + <xsl:variable name="descend" select="$elems/descendant-or-self::svg:*"/> + <xsl:variable name="clones" select="$descend[self::svg:use]"/> + <xsl:variable name="originals" select="//svg:*[concat('#',@id) = $clones/@xlink:href]"/> + <xsl:choose> + <xsl:when test="$originals"> + <func:result select="$descend | func:refered_elements($originals)"/> + </xsl:when> + <xsl:otherwise> + <func:result select="$descend"/> + </xsl:otherwise> + </xsl:choose> + </func:function> + <func:function name="func:all_related_elements"> + <xsl:param name="page"/> + <xsl:variable name="page_overlapping_geometry" select="func:overlapping_geometry($page)"/> + <xsl:variable name="page_overlapping_elements" select="//svg:*[@id = $page_overlapping_geometry/@Id]"/> + <xsl:variable name="page_sub_elements" select="func:refered_elements($page | $page_overlapping_elements)"/> + <func:result select="$page_sub_elements"/> + </func:function> + <func:function name="func:required_elements"> + <xsl:param name="pages"/> + <xsl:choose> + <xsl:when test="$pages"> + <func:result select="func:all_related_elements($pages[1]) | func:required_elements($pages[position()!=1])"/> + </xsl:when> + <xsl:otherwise> + <func:result select="/.."/> + </xsl:otherwise> + </xsl:choose> + </func:function> + <xsl:variable name="required_elements" select="//svg:defs/descendant-or-self::svg:* | func:required_elements($hmi_pages)/ancestor-or-self::svg:*"/> + <xsl:variable name="discardable_elements" select="//svg:*[not(@id = $required_elements/@id)]"/> + <func:function name="func:sumarized_elements"> + <xsl:param name="elements"/> + <xsl:variable name="short_list" select="$elements[not(ancestor::*/@id = $elements/@id)]"/> + <xsl:variable name="filled_groups" select="$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) ])]"/> + <xsl:variable name="groups_to_add" select="$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"/> + <func:result select="$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]"/> + </func:function> + <func:function name="func:detachable_elements"> + <xsl:param name="pages"/> + <xsl:choose> + <xsl:when test="$pages"> + <func:result select="func:sumarized_elements(func:all_related_elements($pages[1])) | func:detachable_elements($pages[position()!=1])"/> + </xsl:when> + <xsl:otherwise> + <func:result select="/.."/> + </xsl:otherwise> + </xsl:choose> + </func:function> + <xsl:variable name="_detachable_elements" select="func:detachable_elements($hmi_pages)"/> + <xsl:variable name="detachable_elements" select="$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]"/> + <func:function name="func:is_descendant_path"> + <xsl:param name="descend"/> + <xsl:param name="ancest"/> + <func:result select="string-length($ancest) > 0 and starts-with($descend,$ancest)"/> + </func:function> + <xsl:template mode="page_desc" match="svg:*"> + <xsl:variable name="desc" select="func:parselabel(@inkscape:label)/widget"/> + <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_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(func:parselabel(@inkscape:label)/widget/path/@value, $desc/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"/> + <xsl:text>": { +</xsl:text> + <xsl:text> widget: hmi_widgets["</xsl:text> + <xsl:value-of select="@id"/> + <xsl:text>"], +</xsl:text> + <xsl:text> bbox: [</xsl:text> + <xsl:value-of select="$p/@x"/> + <xsl:text>, </xsl:text> + <xsl:value-of select="$p/@y"/> + <xsl:text>, </xsl:text> + <xsl:value-of select="$p/@w"/> + <xsl:text>, </xsl:text> + <xsl:value-of select="$p/@h"/> + <xsl:text>], +</xsl:text> + <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="@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> + </xsl:if> + <xsl:text> +</xsl:text> + </xsl:for-each> + <xsl:text> ], +</xsl:text> + <xsl:text> required_detachables: { +</xsl:text> + <xsl:for-each select="$required_detachables"> + <xsl:text> "</xsl:text> + <xsl:value-of select="@id"/> + <xsl:text>": detachable_elements["</xsl:text> + <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> }</xsl:text> + <xsl:if test="position()!=last()"> + <xsl:text>,</xsl:text> + </xsl:if> + <xsl:text> +</xsl:text> + </xsl:template> + <xsl:template name="debug_detachables"> + <xsl:for-each select="$detachable_elements"> + <xsl:text> </xsl:text> + <xsl:value-of select="@id"/> + <xsl:text> +</xsl:text> + </xsl:for-each> + </xsl:template> + <xsl:template mode="inline_svg" match="@* | node()"> + <xsl:if test="not(@id = $discardable_elements/@id)"> + <xsl:copy> + <xsl:apply-templates mode="inline_svg" select="@* | node()"/> + </xsl:copy> + </xsl:if> + </xsl:template> + <xsl:template mode="inline_svg" match="svg:svg/@width"/> + <xsl:template mode="inline_svg" match="svg:svg/@height"/> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:svg"> + <svg> + <xsl:attribute name="preserveAspectRatio"> + <xsl:text>none</xsl:text> + </xsl:attribute> + <xsl:attribute name="height"> + <xsl:text>100vh</xsl:text> + </xsl:attribute> + <xsl:attribute name="width"> + <xsl:text>100vw</xsl:text> + </xsl:attribute> + <xsl:apply-templates mode="inline_svg" select="@* | node()"/> + </svg> + </xsl:template> + <xsl:template mode="inline_svg" match="svg:svg[@viewBox!=concat('0 0 ', @width, ' ', @height)]"> + <xsl:message terminate="yes"> + <xsl:text>ViewBox settings other than X=0, Y=0 and Scale=1 are not supported</xsl:text> + </xsl:message> + </xsl:template> + <xsl:template mode="inline_svg" match="sodipodi:namedview[@units!='px' or @inkscape:document-units!='px']"> + <xsl:message terminate="yes"> + <xsl:text>All units must be set to "px" in Inkscape's document properties</xsl:text> + </xsl:message> + </xsl:template> + <xsl:variable name="to_unlink" select="$hmi_elements[not(@id = $hmi_pages)]//svg:use"/> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:use"> + <xsl:choose> + <xsl:when test="@id = $to_unlink/@id"> + <xsl:call-template name="unlink_clone"/> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:apply-templates mode="inline_svg" select="@* | node()"/> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <xsl:variable name="_excluded_use_attrs"> + <name> + <xsl:text>href</xsl:text> + </name> + <name> + <xsl:text>width</xsl:text> + </name> + <name> + <xsl:text>height</xsl:text> + </name> + <name> + <xsl:text>x</xsl:text> + </name> + <name> + <xsl:text>y</xsl:text> + </name> + </xsl:variable> + <xsl:variable name="excluded_use_attrs" select="exsl:node-set($_excluded_use_attrs)"/> + <xsl:template xmlns="http://www.w3.org/2000/svg" name="unlink_clone"> + <g> + <xsl:for-each select="@*[not(local-name() = $excluded_use_attrs/name)]"> + <xsl:attribute name="{name()}"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:for-each> + <xsl:variable name="targetid" select="substring-after(@xlink:href,'#')"/> + <xsl:apply-templates mode="unlink_clone" select="//svg:*[@id = $targetid]"> + <xsl:with-param name="seed" select="@id"/> + </xsl:apply-templates> + </g> + </xsl:template> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@id"> + <xsl:param name="seed"/> + <xsl:attribute name="id"> + <xsl:value-of select="$seed"/> + <xsl:text>_</xsl:text> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:template> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@*"> + <xsl:copy/> + </xsl:template> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="svg:*"> + <xsl:param name="seed"/> + <xsl:choose> + <xsl:when test="@id = $hmi_elements/@id"> + <use> + <xsl:attribute name="xlink:href"> + <xsl:value-of select="concat('#',@id)"/> + </xsl:attribute> + </use> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:apply-templates mode="unlink_clone" select="@* | node()"> + <xsl:with-param name="seed" select="$seed"/> + </xsl:apply-templates> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <xsl:variable name="result_svg"> + <xsl:apply-templates mode="inline_svg" select="/"/> + </xsl:variable> + <xsl:variable name="result_svg_ns" select="exsl:node-set($result_svg)"/> + <xsl:template match="/"> + <xsl:comment> + <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text> + </xsl:comment> + <xsl:comment> + <xsl:text> +</xsl:text> + <xsl:text>debug_hmitree: +</xsl:text> + <xsl:call-template name="debug_hmitree"/> + <xsl:text> +</xsl:text> + </xsl:comment> + <xsl:comment> + <xsl:text> +</xsl:text> + <xsl:text>debug_geometry: +</xsl:text> + <xsl:call-template name="debug_geometry"/> + <xsl:text> +</xsl:text> + </xsl:comment> + <xsl:comment> + <xsl:text> +</xsl:text> + <xsl:text>debug_detachables: +</xsl:text> + <xsl:call-template name="debug_detachables"/> + <xsl:text> +</xsl:text> + </xsl:comment> + <xsl:comment> + <xsl:text>Unlinked : +</xsl:text> + <xsl:for-each select="$to_unlink"> + <xsl:value-of select="@id"/> + <xsl:text> +</xsl:text> + </xsl:for-each> + </xsl:comment> + <html xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/1999/xhtml"> + <head/> + <body style="margin:0;overflow:hidden;"> + <xsl:copy-of select="$result_svg"/> + <script> + <xsl:call-template name="scripts"/> + </script> + </body> + </html> + </xsl:template> <xsl:template name="scripts"> <xsl:text>//(function(){ </xsl:text> @@ -613,98 +705,7 @@ </xsl:text> <xsl:text>var page_desc = { </xsl:text> - <xsl:for-each select="$hmi_pages"> - <xsl:variable name="desc" select="func:parselabel(@inkscape:label)/widget"/> - <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_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(func:parselabel(@inkscape:label)/widget/path/@value, $desc/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"/> - <xsl:text>": { -</xsl:text> - <xsl:text> widget: hmi_widgets["</xsl:text> - <xsl:value-of select="@id"/> - <xsl:text>"], -</xsl:text> - <xsl:text> bbox: [</xsl:text> - <xsl:value-of select="$p/@x"/> - <xsl:text>, </xsl:text> - <xsl:value-of select="$p/@y"/> - <xsl:text>, </xsl:text> - <xsl:value-of select="$p/@w"/> - <xsl:text>, </xsl:text> - <xsl:value-of select="$p/@h"/> - <xsl:text>], -</xsl:text> - <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="@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> - </xsl:if> - <xsl:text> -</xsl:text> - </xsl:for-each> - <xsl:text> ], -</xsl:text> - <xsl:text> required_detachables: { -</xsl:text> - <xsl:for-each select="$required_detachables"> - <xsl:text> "</xsl:text> - <xsl:value-of select="@id"/> - <xsl:text>": detachable_elements["</xsl:text> - <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> }</xsl:text> - <xsl:if test="position()!=last()"> - <xsl:text>,</xsl:text> - </xsl:if> - <xsl:text> -</xsl:text> - </xsl:for-each> + <xsl:apply-templates mode="page_desc" select="$hmi_pages"/> <xsl:text>} </xsl:text> <xsl:text> diff -r d2adbc273125 -r 682bce953795 svghmi/gen_index_xhtml.ysl2 --- a/svghmi/gen_index_xhtml.ysl2 Tue Mar 17 10:34:26 2020 +0100 +++ b/svghmi/gen_index_xhtml.ysl2 Tue Mar 17 11:24:07 2020 +0100 @@ -36,47 +36,14 @@ exclude-result-prefixes="ns str regexp exsl func dyn" { + include hmi_tree.ysl2 + + include geometry.ysl2 + const "svg_root_id", "/svg:svg/@id"; const "hmi_elements", "//svg:*[starts-with(@inkscape:label, 'HMI:')]"; - const "hmi_pages", "$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"; - - const "default_page" choose { - when "count($hmi_pages) > 1" { - const "Home_page", - "$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"; - choose { - when "$Home_page" > Home - otherwise { - error "No Home page defined!"; - } - } - } - when "count($hmi_pages) = 0" { - error "No page defined!"; - } - otherwise > «func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value» - } - - const "_categories" { - noindex > HMI_ROOT - noindex > HMI_PLC_STATUS - noindex > HMI_CURRENT_PAGE - } - const "categories", "exsl:node-set($_categories)"; - - include geometry.ysl2 - - include detachable_elements.ysl2 - - include hmi_tree.ysl2 - - - def "func:is_descendant_path" { - param "descend"; - param "ancest"; - result "string-length($ancest) > 0 and starts-with($descend,$ancest)"; - } + include detachable_pages.ysl2 //////////////// Inline SVG @@ -230,43 +197,6 @@ } */ - def "func:parselabel" { - param "label"; - const "description", "substring-after($label,'HMI:')"; - - const "_args", "substring-before($description,'@')"; - const "args" choose { - when "$_args" value "$_args"; - otherwise value "$description"; - } - - const "_type", "substring-before($args,':')"; - const "type" choose { - when "$_type" value "$_type"; - otherwise value "$args"; - } - - const "ast" if "$type" widget { - attrib "type" > «$type» - foreach "str:split(substring-after($args, ':'), ':')" { - arg { - attrib "value" > «.» - } - } - const "paths", "substring-after($description,'@')"; - foreach "str:split($paths, '@')" { - if "string-length(.) > 0" path { - attrib "value" > «.» - const "path", "."; - const "item", "$indexed_hmitree/*[@hmipath = $path]"; - if "count($item) = 1" - attrib "index" > «$item/@index» - } - } - } - - result "exsl:node-set($ast)"; - } function "scripts" { @@ -341,50 +271,7 @@ | | var page_desc = { - - foreach "$hmi_pages" { - const "desc", "func:parselabel(@inkscape:label)/widget"; - 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_relative_widgets", - "$all_page_widgets[func:is_descendant_path(func:parselabel(@inkscape:label)/widget/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 "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" { - | hmi_widgets["«@id»"]`if "position()!=last()" > ,` - } - | ], - | required_detachables: { - foreach "$required_detachables" { - | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` - } - | } - | }`if "position()!=last()" > ,` - } + apply "$hmi_pages", mode="page_desc"; | } | diff -r d2adbc273125 -r 682bce953795 svghmi/hmi_tree.ysl2 --- a/svghmi/hmi_tree.ysl2 Tue Mar 17 10:34:26 2020 +0100 +++ b/svghmi/hmi_tree.ysl2 Tue Mar 17 11:24:07 2020 +0100 @@ -4,6 +4,12 @@ // HMI Tree computed from VARIABLES.CSV in svghmi.py const "hmitree", "ns:GetHMITree()"; +const "_categories" { + noindex > HMI_ROOT + noindex > HMI_PLC_STATUS + noindex > HMI_CURRENT_PAGE +} +const "categories", "exsl:node-set($_categories)"; // HMI Tree Index const "_indexed_hmitree" apply "$hmitree", mode="index"; @@ -46,6 +52,44 @@ } } +def "func:parselabel" { + param "label"; + const "description", "substring-after($label,'HMI:')"; + + const "_args", "substring-before($description,'@')"; + const "args" choose { + when "$_args" value "$_args"; + otherwise value "$description"; + } + + const "_type", "substring-before($args,':')"; + const "type" choose { + when "$_type" value "$_type"; + otherwise value "$args"; + } + + const "ast" if "$type" widget { + attrib "type" > «$type» + foreach "str:split(substring-after($args, ':'), ':')" { + arg { + attrib "value" > «.» + } + } + const "paths", "substring-after($description,'@')"; + foreach "str:split($paths, '@')" { + if "string-length(.) > 0" path { + attrib "value" > «.» + const "path", "."; + const "item", "$indexed_hmitree/*[@hmipath = $path]"; + if "count($item) = 1" + attrib "index" > «$item/@index» + } + } + } + + result "exsl:node-set($ast)"; +} + // Debug data template "*", mode="testtree"{ param "indent", "''";