# HG changeset patch # User Edouard Tisserant # Date 1584972816 -3600 # Node ID d57a12b8f5dbc64fa5e59dbd0d8fc193b2d3adff # Parent 27dd409fba1dc1d5ca5a80a0e561991647acf62c SVGHMI: added func:get_hmi_tree_elt to match HMI tree node from path. Continue implementing ForEach widget : force order and completeness of items list. Now also collecting ForEach buttons. diff -r 27dd409fba1d -r d57a12b8f5db svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Mon Mar 23 10:16:38 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Mon Mar 23 15:13:36 2020 +0100 @@ -74,6 +74,49 @@ </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:')"/> @@ -600,9 +643,9 @@ <xsl:otherwise> <xsl:text> </xsl:text> <xsl:value-of select="@index"/> - <xsl:text> /*</xsl:text> - <xsl:value-of select="$widget/path"/> - <xsl:text>*/ </xsl:text> + <xsl:text> /* </xsl:text> + <xsl:value-of select="@value"/> + <xsl:text> */ </xsl:text> <xsl:if test="position()!=last()"> <xsl:text>,</xsl:text> </xsl:if> @@ -711,36 +754,62 @@ </xsl:text> <xsl:text> }, </xsl:text> + <xsl:text> index_pool: [ +</xsl:text> + <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)]"> + <xsl:text> ["</xsl:text> + <xsl:value-of select="substring-after(@inkscape:label, concat(arg[1]/@value, ':'))"/> + <xsl:text>", id("</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> init: function() { </xsl:text> - <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]"> - <xsl:text> id("</xsl:text> - <xsl:value-of select="@id"/> - <xsl:text>").addEventListener( -</xsl:text> - <xsl:text> "click", -</xsl:text> - <xsl:text> evt => {let new_val = "</xsl:text> - <xsl:value-of select="func:escape_quotes(@inkscape:label)"/> - <xsl:text>"); -</xsl:text> - <xsl:text> // do something with new_val -</xsl:text> - <xsl:text> }); -</xsl:text> - </xsl:for-each> + <xsl:text> /* TODO elt.setAttribute("onclick", "hmi_widgets['</xsl:text> + <xsl:value-of select="$hmi_element/@id"/> + <xsl:text>'].on_click(evt)");*/ +</xsl:text> <xsl:text> }, </xsl:text> - <xsl:text> widgets: [ -</xsl:text> - <xsl:variable name="labels_regex" select="concat('^',arg[1]/@value,':[0-9]+')"/> - <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label, $labels_regex)]"> + <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:value-of select="@inkscape:label"/> + <xsl:value-of select="$elt_label"/> <xsl:text> */ </xsl:text> - <xsl:variable name="elt" select="."/> - <xsl:for-each select="func:refered_elements(.)[@id = $hmi_elements/@id][not(@id = $elt/@id)]"> + <xsl:if test="count($elt)=0"> + <xsl:message terminate="yes"> + <xsl:text>Missing item labeled </xsl:text> + <xsl:value-of select="$elt_label"/> + <xsl:text> in ForEach widget </xsl:text> + <xsl:value-of select="$hmi_element/@id"/> + </xsl:message> + </xsl:if> + <xsl:for-each select="func:refered_elements($elt)[@id = $hmi_elements/@id][not(@id = $elt/@id)]"> <xsl:text> hmi_widgets["</xsl:text> <xsl:value-of select="@id"/> <xsl:text>"]</xsl:text> @@ -763,13 +832,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 27dd409fba1d -r d57a12b8f5db svghmi/hmi_tree.ysl2 --- a/svghmi/hmi_tree.ysl2 Mon Mar 23 10:16:38 2020 +0100 +++ b/svghmi/hmi_tree.ysl2 Mon Mar 23 15:13:36 2020 +0100 @@ -52,14 +52,44 @@ } } +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" // // Into: -// widget type="WidgetType" { +// widget type="WidgetType" id="blah456" { // arg value="param1"; // arg value="param2"; -// path value="path1"; +// path value="path1" index="345"; // path value="path2"; // } // diff -r 27dd409fba1d -r d57a12b8f5db svghmi/widget_foreach.ysl2 --- a/svghmi/widget_foreach.ysl2 Mon Mar 23 10:16:38 2020 +0100 +++ b/svghmi/widget_foreach.ysl2 Mon Mar 23 15:13:36 2020 +0100 @@ -6,23 +6,32 @@ | dispatch: function(value) { | // do something | }, + | index_pool: [ + | ], + | 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)]" { + | ["«substring-after(@inkscape:label, concat(arg[1]/@value, ':'))»", id("«@id»")]`if "position()!=last()" > ,` + } + | ], | init: function() { - foreach "$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]" { - | id("«@id»").addEventListener( - | "click", - | evt => {let new_val = "«func:escape_quotes(@inkscape:label)»"); - | // do something with new_val - | }); - } + | /* TODO elt.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_click(evt)");*/ | }, - | widgets: [ - const "labels_regex","concat('^',arg[1]/@value,':[0-9]+')"; - foreach "$hmi_element/*[regexp:test(@inkscape:label, $labels_regex)]" { - | [ /* «@inkscape:label» */ - const "elt","."; - //foreach "$hmi_elements[ancestor::svg:*/@id = $_id]" { - foreach "func:refered_elements(.)[@id = $hmi_elements/@id][not(@id = $elt/@id)]" { + | 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» */ + 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)]" { | hmi_widgets["«@id»"]`if "position()!=last()" > ,` } | ]`if "position()!=last()" > ,` diff -r 27dd409fba1d -r d57a12b8f5db svghmi/widgets_common.ysl2 --- a/svghmi/widgets_common.ysl2 Mon Mar 23 10:16:38 2020 +0100 +++ b/svghmi/widgets_common.ysl2 Mon Mar 23 15:13:36 2020 +0100 @@ -28,7 +28,7 @@ warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«@value»" in HMI tree } otherwise { - | «@index» /*«$widget/path»*/ `if "position()!=last()" > ,` + | «@index» /* «@value» */ `if "position()!=last()" > ,` } } }