SVGHMI: Simplification and optimization. func:parselabel becomes a template.
All labels are parsed into a global variable containing resulting widget
description as a node-set. func:widget(id) was added for random access to
widget description.
--- a/svghmi/detachable_pages.ysl2 Wed Mar 18 12:06:50 2020 +0100
+++ b/svghmi/detachable_pages.ysl2 Thu Mar 19 09:31:07 2020 +0100
@@ -4,12 +4,13 @@
// 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 "hmi_pages_ids", "$parsed_widgets/widget[@type = 'Page']/@id";
+const "hmi_pages", "$hmi_elements[@id = $hmi_pages_ids]";
const "default_page" choose {
when "count($hmi_pages) > 1" {
const "Home_page",
- "$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']";
+ "$hmi_pages[func:widget(@id)/arg[1]/@value = 'Home']";
choose {
when "$Home_page" > Home
otherwise {
@@ -20,7 +21,7 @@
when "count($hmi_pages) = 0" {
error "No page defined!";
}
- otherwise > «func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value»
+ otherwise > «func:widget($hmi_pages/@id)/arg[1]/@value»
}
// returns all directly or indirectly refered elements
@@ -100,16 +101,16 @@
template "svg:*", mode="page_desc" {
- const "desc", "func:parselabel(@inkscape:label)/widget";
+ 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][not(func:parselabels(ancestor::svg:*)/widget/@type = 'ForEach')]";
+ 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)]";
+ "$all_page_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
--- a/svghmi/gen_index_xhtml.xslt Wed Mar 18 12:06:50 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Thu Mar 19 09:31:07 2020 +0100
@@ -73,8 +73,8 @@
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
- <func:function name="func:parselabel">
- <xsl:param name="label"/>
+ <xsl:template mode="parselabel" match="*">
+ <xsl:variable name="label" select="@inkscape:label"/>
<xsl:variable name="description" select="substring-after($label,'HMI:')"/>
<xsl:variable name="_args" select="substring-before($description,'@')"/>
<xsl:variable name="args">
@@ -98,51 +98,48 @@
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
- <xsl:variable name="ast">
- <xsl:if test="$type">
- <widget>
- <xsl:attribute name="type">
- <xsl:value-of select="$type"/>
- </xsl:attribute>
- <xsl:for-each select="str:split(substring-after($args, ':'), ':')">
- <arg>
+ <xsl:if test="$type">
+ <widget>
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ <xsl:attribute name="type">
+ <xsl:value-of select="$type"/>
+ </xsl:attribute>
+ <xsl:for-each select="str:split(substring-after($args, ':'), ':')">
+ <arg>
+ <xsl:attribute name="value">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </arg>
+ </xsl:for-each>
+ <xsl:variable name="paths" select="substring-after($description,'@')"/>
+ <xsl:for-each select="str:split($paths, '@')">
+ <xsl:if test="string-length(.) > 0">
+ <path>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
- </arg>
- </xsl:for-each>
- <xsl:variable name="paths" select="substring-after($description,'@')"/>
- <xsl:for-each select="str:split($paths, '@')">
- <xsl:if test="string-length(.) > 0">
- <path>
- <xsl:attribute name="value">
- <xsl:value-of select="."/>
+ <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: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>
- </xsl:variable>
- <func:result select="exsl:node-set($ast)"/>
- </func:function>
- <func:function name="func:parselabels">
- <xsl:param name="nodes"/>
- <xsl:choose>
- <xsl:when test="$nodes">
- <func:result select="func:parselabel($nodes[1]/@inkscape:label) | func:parselabels($nodes[position()!=1])"/>
- </xsl:when>
- <xsl:otherwise>
- <func:result select="/.."/>
- </xsl:otherwise>
- </xsl:choose>
+ </xsl:if>
+ </path>
+ </xsl:if>
+ </xsl:for-each>
+ </widget>
+ </xsl:if>
+ </xsl:template>
+ <xsl:variable name="_parsed_widgets">
+ <xsl:apply-templates mode="parselabel" select="$hmi_elements"/>
+ </xsl:variable>
+ <xsl:variable name="parsed_widgets" select="exsl:node-set($_parsed_widgets)"/>
+ <func:function name="func:widget">
+ <xsl:param name="id"/>
+ <func:result select="$parsed_widgets/widget[@id = $id]"/>
</func:function>
<xsl:template mode="testtree" match="*">
<xsl:param name="indent" select="''"/>
@@ -173,6 +170,12 @@
<xsl:text>Indexed HMI tree
</xsl:text>
<xsl:apply-templates mode="testtree" select="$indexed_hmitree"/>
+ <xsl:text>
+</xsl:text>
+ <xsl:text>Parsed Widgets
+</xsl:text>
+ <xsl:copy-of select="_parsed_widgets"/>
+ <xsl:apply-templates mode="testtree" select="$parsed_widgets"/>
</xsl:template>
<xsl:variable name="geometry" select="ns:GetSVGGeometry()"/>
<xsl:template name="debug_geometry">
@@ -239,11 +242,12 @@
<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="hmi_pages" select="$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"/>
+ <xsl:variable name="hmi_pages_ids" select="$parsed_widgets/widget[@type = 'Page']/@id"/>
+ <xsl:variable name="hmi_pages" select="$hmi_elements[@id = $hmi_pages_ids]"/>
<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:variable name="Home_page" select="$hmi_pages[func:widget(@id)/arg[1]/@value = 'Home']"/>
<xsl:choose>
<xsl:when test="$Home_page">
<xsl:text>Home</xsl:text>
@@ -257,7 +261,7 @@
<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:value-of select="func:widget($hmi_pages/@id)/arg[1]/@value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@@ -321,12 +325,12 @@
<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="desc" select="func:widget(@id)"/>
<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][not(func:parselabels(ancestor::svg:*)/widget/@type = 'ForEach')]"/>
- <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="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:widget(@id)/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"/>
@@ -539,7 +543,7 @@
</xsl:for-each>
</xsl:template>
<xsl:template mode="hmi_elements" match="svg:*">
- <xsl:variable name="widget" select="func:parselabel(@inkscape:label)/widget"/>
+ <xsl:variable name="widget" select="func:widget(@id)"/>
<xsl:variable name="eltid" select="@id"/>
<xsl:text> "</xsl:text>
<xsl:value-of select="@id"/>
--- a/svghmi/hmi_tree.ysl2 Wed Mar 18 12:06:50 2020 +0100
+++ b/svghmi/hmi_tree.ysl2 Thu Mar 19 09:31:07 2020 +0100
@@ -63,8 +63,8 @@
// path value="path2";
// }
//
-def "func:parselabel" {
- param "label";
+template "*", mode="parselabel" {
+ const "label","@inkscape:label";
const "description", "substring-after($label,'HMI:')";
const "_args", "substring-before($description,'@')";
@@ -79,7 +79,8 @@
otherwise value "$args";
}
- const "ast" if "$type" widget {
+ if "$type" widget {
+ attrib "id" > «@id»
attrib "type" > «$type»
foreach "str:split(substring-after($args, ':'), ':')" {
arg {
@@ -97,22 +98,17 @@
}
}
}
-
- result "exsl:node-set($ast)";
}
-def "func:parselabels" {
- param "nodes";
- choose{
- when "$nodes"{
- result """func:parselabel($nodes[1]/@inkscape:label)
- | func:parselabels($nodes[position()!=1])""";
- }otherwise{
- result "/..";
- }
- }
+const "_parsed_widgets" apply "$hmi_elements", mode="parselabel";
+const "parsed_widgets","exsl:node-set($_parsed_widgets)";
+
+def "func:widget" {
+ param "id";
+ result "$parsed_widgets/widget[@id = $id]";
}
+
// Debug data
template "*", mode="testtree"{
param "indent", "''";
@@ -129,5 +125,9 @@
|
| Indexed HMI tree
apply "$indexed_hmitree", mode="testtree";
+ |
+ | Parsed Widgets
+ copy "_parsed_widgets";
+ apply "$parsed_widgets", mode="testtree";
}
!debug_output_calls.append("debug_hmitree")
--- a/svghmi/widgets_common.ysl2 Wed Mar 18 12:06:50 2020 +0100
+++ b/svghmi/widgets_common.ysl2 Thu Mar 19 09:31:07 2020 +0100
@@ -12,7 +12,7 @@
};
template "svg:*", mode="hmi_elements" {
- const "widget", "func:parselabel(@inkscape:label)/widget";
+ const "widget", "func:widget(@id)";
const "eltid","@id";
| "«@id»": {
| type: "«$widget/@type»",