# HG changeset patch # User Edouard Tisserant <edouard.tisserant@gmail.com> # Date 1584996268 -3600 # Node ID 4cf9ad35e6d0151217a9b130b0e141f774838fdd # Parent d57a12b8f5dbc64fa5e59dbd0d8fc193b2d3adff SVGHMI: Easier way to match HMI tree elements to paths. ForEach widget now looks for paths and indexes of all items, and enforce path to be consistent with ForEach items sub widgets diff -r d57a12b8f5db -r 4cf9ad35e6d0 svghmi/detachable_pages.ysl2 --- a/svghmi/detachable_pages.ysl2 Mon Mar 23 15:13:36 2020 +0100 +++ b/svghmi/detachable_pages.ysl2 Mon Mar 23 21:44:28 2020 +0100 @@ -91,13 +91,6 @@ 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)"; -} - - const "forEach_widgets_ids", "$parsed_widgets/widget[@type = 'ForEach']/@id"; const "forEach_widgets", "$hmi_elements[@id = $forEach_widgets_ids]"; const "in_forEach_widget_ids", "func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]/@id"; diff -r d57a12b8f5db -r 4cf9ad35e6d0 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Mon Mar 23 15:13:36 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Mon Mar 23 21:44:28 2020 +0100 @@ -74,49 +74,6 @@ </xsl:with-param> </xsl:apply-templates> </xsl:template> - <func:function name="func:get_hmi_tree_elt"> - <xsl:param name="path"/> - <xsl:param name="root" select="$hmitree"/> - <xsl:message> - <xsl:text>get_hmi_tree_elt </xsl:text> - <xsl:value-of select="$path"/> - </xsl:message> - <xsl:if test="not(starts-with($path, '/'))"> - <xsl:message terminate="yes"> - <xsl:text>Given path "</xsl:text> - <xsl:value-of select="$path"/> - <xsl:text>" should start with a "/"</xsl:text> - </xsl:message> - </xsl:if> - <xsl:variable name="stripped" select="substring($path, 2)"/> - <xsl:variable name="token"> - <xsl:choose> - <xsl:when test="contains($stripped, '/')"> - <xsl:value-of select="substring-before($stripped, '/')"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$stripped"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - <xsl:choose> - <xsl:when test="string-length($token) = 0"> - <func:result select="$root"/> - </xsl:when> - <xsl:otherwise> - <xsl:variable name="rest" select="substring-after($stripped, $token)"/> - <xsl:variable name="match" select="$root/*[@name = $token]"/> - <xsl:choose> - <xsl:when test="string-length($rest) > 0"> - <func:result select="func:get_hmi_tree_el($rest, $match)"/> - </xsl:when> - <xsl:otherwise> - <func:result select="$match"/> - </xsl:otherwise> - </xsl:choose> - </xsl:otherwise> - </xsl:choose> - </func:function> <xsl:template mode="parselabel" match="*"> <xsl:variable name="label" select="@inkscape:label"/> <xsl:variable name="description" select="substring-after($label,'HMI:')"/> @@ -185,6 +142,11 @@ <xsl:param name="id"/> <func:result select="$parsed_widgets/widget[@id = $id]"/> </func:function> + <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="testtree" match="*"> <xsl:param name="indent" select="''"/> <xsl:value-of select="$indent"/> @@ -362,11 +324,6 @@ </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:variable name="forEach_widgets_ids" select="$parsed_widgets/widget[@type = 'ForEach']/@id"/> <xsl:variable name="forEach_widgets" select="$hmi_elements[@id = $forEach_widgets_ids]"/> <xsl:variable name="in_forEach_widget_ids" select="func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]/@id"/> @@ -746,21 +703,28 @@ <xsl:template mode="widget_defs" match="widget[@type='ForEach']"> <xsl:param name="hmi_element"/> <xsl:variable name="widgets" select="func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]"/> - <xsl:text> frequency: 2, -</xsl:text> - <xsl:text> dispatch: function(value) { -</xsl:text> - <xsl:text> // do something -</xsl:text> - <xsl:text> }, -</xsl:text> + <xsl:variable name="class" select="arg[1]/@value"/> + <xsl:variable name="base_path" select="path/@value"/> + <xsl:variable name="hmi_index_base" select="$indexed_hmitree/*[@hmipath = $base_path]"/> + <xsl:variable name="hmi_tree_base" select="$hmitree/descendant-or-self::*[@path = $hmi_index_base/@path]"/> + <xsl:variable name="hmi_tree_items" select="$hmi_tree_base/*[@class = $class]"/> + <xsl:variable name="hmi_index_items" select="$indexed_hmitree/*[@path = $hmi_tree_items/@path]"/> + <xsl:variable name="items_paths" select="$hmi_index_items/@hmipath"/> <xsl:text> index_pool: [ </xsl:text> + <xsl:for-each select="$hmi_index_items"> + <xsl:text> </xsl:text> + <xsl:value-of select="@index"/> + <xsl:if test="position()!=last()"> + <xsl:text>,</xsl:text> + </xsl:if> + <xsl:text> +</xsl:text> + </xsl:for-each> <xsl:text> ], </xsl:text> <xsl:text> buttons: [ </xsl:text> - <xsl:variable name="class" select="arg[1]/@value"/> <xsl:variable name="prefix" select="concat($class,':')"/> <xsl:variable name="buttons_regex" select="concat('^',$prefix,'[+\-][0-9]+')"/> <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label, $buttons_regex)]"> @@ -787,19 +751,18 @@ </xsl:text> <xsl:text> items: [ </xsl:text> - <xsl:variable name="base_path" select="path/@value"/> <xsl:variable name="items_regex" select="concat('^',$prefix,'[0-9]+')"/> <xsl:variable name="unordered_items" select="$hmi_element//*[regexp:test(@inkscape:label, $items_regex)]"/> <xsl:for-each select="$unordered_items"> <xsl:variable name="elt_label" select="concat($prefix, string(position()))"/> <xsl:variable name="elt" select="$unordered_items[@inkscape:label = $elt_label]"/> - <xsl:text> /* </xsl:text> - <xsl:apply-templates mode="testtree" select="func:get_hmi_tree_elt($base_path)"/> - <xsl:text> */ -</xsl:text> - <xsl:text> [ /* </xsl:text> + <xsl:variable name="pos" select="position()"/> + <xsl:variable name="item_path" select="$items_paths[$pos]"/> + <xsl:text> [ /* item="</xsl:text> <xsl:value-of select="$elt_label"/> - <xsl:text> */ + <xsl:text>" path="</xsl:text> + <xsl:value-of select="$item_path"/> + <xsl:text>" */ </xsl:text> <xsl:if test="count($elt)=0"> <xsl:message terminate="yes"> @@ -810,6 +773,19 @@ </xsl:message> </xsl:if> <xsl:for-each select="func:refered_elements($elt)[@id = $hmi_elements/@id][not(@id = $elt/@id)]"> + <xsl:if test="not(func:is_descendant_path(func:widget(@id)/path/@value, $item_path))"> + <xsl:message terminate="yes"> + <xsl:text>Widget id="</xsl:text> + <xsl:value-of select="@id"/> + <xsl:text>" label="</xsl:text> + <xsl:value-of select="@inkscape:label"/> + <xsl:text>" is having wrong path. Accroding to ForEach widget ancestor id="</xsl:text> + <xsl:value-of select="$hmi_element/@id"/> + <xsl:text>", path should be descendant of </xsl:text> + <xsl:value-of select="$item_path"/> + <xsl:text>.</xsl:text> + </xsl:message> + </xsl:if> <xsl:text> hmi_widgets["</xsl:text> <xsl:value-of select="@id"/> <xsl:text>"]</xsl:text> @@ -832,13 +808,13 @@ <xsl:template mode="widget_subscribe" match="widget[@type='ForEach']"> <xsl:text> sub: function(off){ </xsl:text> - <xsl:text> subscribe.call(this,off); + <xsl:text> /*subscribe.call(this,off);*/ </xsl:text> <xsl:text> }, </xsl:text> <xsl:text> unsub: function(){ </xsl:text> - <xsl:text> unsubscribe.call(this); + <xsl:text> /*unsubscribe.call(this);*/ </xsl:text> <xsl:text> }, </xsl:text> diff -r d57a12b8f5db -r 4cf9ad35e6d0 svghmi/hmi_tree.ysl2 --- a/svghmi/hmi_tree.ysl2 Mon Mar 23 15:13:36 2020 +0100 +++ b/svghmi/hmi_tree.ysl2 Mon Mar 23 21:44:28 2020 +0100 @@ -52,36 +52,6 @@ } } -def "func:get_hmi_tree_elt" { - param "path"; - param "root", "$hmitree"; - message > get_hmi_tree_elt «$path» - if "not(starts-with($path, '/'))" error > Given path "«$path»" should start with a "/" - const "stripped", "substring($path, 2)"; - const "token" choose { - when "contains($stripped, '/')" value "substring-before($stripped, '/')"; - otherwise value "$stripped"; - } - - choose { - when "string-length($token) = 0"{ - result "$root"; - } - otherwise{ - const "rest", "substring-after($stripped, $token)"; - const "match", "$root/*[@name = $token]"; - choose { - when "string-length($rest) > 0"{ - result "func:get_hmi_tree_el($rest, $match)"; - } - otherwise{ - result "$match"; - } - } - } - } -} - // Parses: // "HMI:WidgetType:param1:param2@path1@path2" // @@ -139,6 +109,14 @@ } +def "func:is_descendant_path" { + param "descend"; + param "ancest"; + // TODO : use HMI tree to answer more accurately + result "string-length($ancest) > 0 and starts-with($descend,$ancest)"; +} + + // Debug data template "*", mode="testtree"{ param "indent", "''"; diff -r d57a12b8f5db -r 4cf9ad35e6d0 svghmi/widget_foreach.ysl2 --- a/svghmi/widget_foreach.ysl2 Mon Mar 23 15:13:36 2020 +0100 +++ b/svghmi/widget_foreach.ysl2 Mon Mar 23 21:44:28 2020 +0100 @@ -2,14 +2,21 @@ template "widget[@type='ForEach']", mode="widget_defs" { param "hmi_element"; const "widgets", "func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]"; - | frequency: 2, - | dispatch: function(value) { - | // do something - | }, + + const "class","arg[1]/@value"; + + const "base_path","path/@value"; + const "hmi_index_base", "$indexed_hmitree/*[@hmipath = $base_path]"; + const "hmi_tree_base", "$hmitree/descendant-or-self::*[@path = $hmi_index_base/@path]"; + const "hmi_tree_items", "$hmi_tree_base/*[@class = $class]"; + const "hmi_index_items", "$indexed_hmitree/*[@path = $hmi_tree_items/@path]"; + const "items_paths", "$hmi_index_items/@hmipath"; | index_pool: [ + foreach "$hmi_index_items" { + | «@index»`if "position()!=last()" > ,` + } | ], | buttons: [ - const "class","arg[1]/@value"; const "prefix","concat($class,':')"; const "buttons_regex","concat('^',$prefix,'[+\-][0-9]+')"; foreach "$hmi_element/*[regexp:test(@inkscape:label, $buttons_regex)]" { @@ -21,17 +28,18 @@ | }, | items: [ - const "base_path","path/@value"; const "items_regex","concat('^',$prefix,'[0-9]+')"; const "unordered_items","$hmi_element//*[regexp:test(@inkscape:label, $items_regex)]"; foreach "$unordered_items" { const "elt_label","concat($prefix, string(position()))"; const "elt","$unordered_items[@inkscape:label = $elt_label]"; - - | /* `apply "func:get_hmi_tree_elt($base_path)", mode="testtree";` */ - | [ /* «$elt_label» */ + const "pos","position()"; + const "item_path", "$items_paths[$pos]"; + | [ /* item="«$elt_label»" path="«$item_path»" */ if "count($elt)=0" error > Missing item labeled «$elt_label» in ForEach widget «$hmi_element/@id» foreach "func:refered_elements($elt)[@id = $hmi_elements/@id][not(@id = $elt/@id)]" { + if "not(func:is_descendant_path(func:widget(@id)/path/@value, $item_path))" + error > Widget id="«@id»" label="«@inkscape:label»" is having wrong path. Accroding to ForEach widget ancestor id="«$hmi_element/@id»", path should be descendant of «$item_path». | hmi_widgets["«@id»"]`if "position()!=last()" > ,` } | ]`if "position()!=last()" > ,` @@ -42,12 +50,12 @@ template "widget[@type='ForEach']", mode="widget_subscribe"{ // param "hmi_element"; | sub: function(off){ - | subscribe.call(this,off); + | /*subscribe.call(this,off);*/ /* TODO */ | }, | unsub: function(){ - | unsubscribe.call(this); + | /*unsubscribe.call(this);*/ /* TODO */ | }, }