# HG changeset patch # User Edouard Tisserant <edouard.tisserant@gmail.com> # Date 1608825379 -3600 # Node ID a098b2dd9dff387f040eb4368a414cb29a0c1d4c # Parent fc5a0b1ece1071e35c5ee5d1f3f613acdeb5fe1b SVGHMI: Added parsing of min and max value that can be given as @path,min,max in widget description diff -r fc5a0b1ece10 -r a098b2dd9dff svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Tue Dec 22 14:57:59 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Thu Dec 24 16:56:19 2020 +0100 @@ -55,7 +55,27 @@ <xsl:text> </xsl:text> </xsl:for-each> - <xsl:text>] + <xsl:text>]; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text>var hmitree_paths = [ +</xsl:text> + <xsl:for-each select="$indexed_hmitree/*"> + <xsl:text> /* </xsl:text> + <xsl:value-of select="@index"/> + <xsl:text> </xsl:text> + <xsl:value-of select="substring(local-name(), 5)"/> + <xsl:text> */ "</xsl:text> + <xsl:value-of select="@hmipath"/> + <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> @@ -122,6 +142,7 @@ </xsl:template> <xsl:template mode="parselabel" match="*"> <xsl:variable name="label" select="@inkscape:label"/> + <xsl:variable name="id" select="@id"/> <xsl:variable name="description" select="substring-after($label,'HMI:')"/> <xsl:variable name="_args" select="substring-before($description,'@')"/> <xsl:variable name="args"> @@ -148,7 +169,7 @@ <xsl:if test="$type"> <widget> <xsl:attribute name="id"> - <xsl:value-of select="@id"/> + <xsl:value-of select="$id"/> </xsl:attribute> <xsl:attribute name="type"> <xsl:value-of select="$type"/> @@ -164,33 +185,65 @@ <xsl:for-each select="str:split($paths, '@')"> <xsl:if test="string-length(.) > 0"> <path> + <xsl:variable name="pathminmax" select="str:split(.,',')"/> + <xsl:variable name="path" select="$pathminmax[1]"/> + <xsl:variable name="pathminmaxcount" select="count($pathminmax)"/> <xsl:attribute name="value"> - <xsl:value-of select="."/> + <xsl:value-of select="$path"/> </xsl:attribute> - <xsl:variable name="path" select="."/> - <xsl:variable name="item" select="$indexed_hmitree/*[@hmipath = $path]"/> <xsl:choose> - <xsl:when test="count($item) = 1"> - <xsl:attribute name="index"> - <xsl:value-of select="$item/@index"/> + <xsl:when test="$pathminmaxcount = 3"> + <xsl:attribute name="min"> + <xsl:value-of select="$pathminmax[2]"/> </xsl:attribute> + <xsl:attribute name="max"> + <xsl:value-of select="$pathminmax[3]"/> + </xsl:attribute> + </xsl:when> + <xsl:when test="$pathminmaxcount = 2"> + <xsl:message terminate="yes"> + <xsl:text>Widget id:</xsl:text> + <xsl:value-of select="$id"/> + <xsl:text> label:</xsl:text> + <xsl:value-of select="$label"/> + <xsl:text> has wrong syntax of path section </xsl:text> + <xsl:value-of select="$pathminmax"/> + </xsl:message> + </xsl:when> + </xsl:choose> + <xsl:choose> + <xsl:when test="regexp:test($path,'^\.[a-zA-Z0-9_]+')"> <xsl:attribute name="type"> - <xsl:value-of select="local-name($item)"/> + <xsl:text>PAGE_LOCAL</xsl:text> + </xsl:attribute> + </xsl:when> + <xsl:when test="regexp:test($path,'^[a-zA-Z0-9_]+')"> + <xsl:attribute name="type"> + <xsl:text>HMI_LOCAL</xsl:text> </xsl:attribute> </xsl:when> <xsl:otherwise> - <xsl:choose> - <xsl:when test="regexp:test($path,'^\.[a-zA-Z0-9_]+')"> - <xsl:attribute name="type"> - <xsl:text>PAGE_LOCAL</xsl:text> - </xsl:attribute> - </xsl:when> - <xsl:when test="regexp:test($path,'^[a-zA-Z0-9_]+')"> - <xsl:attribute name="type"> - <xsl:text>HMI_LOCAL</xsl:text> - </xsl:attribute> - </xsl:when> - </xsl:choose> + <xsl:variable name="item" select="$indexed_hmitree/*[@hmipath = $path]"/> + <xsl:variable name="pathtype" select="local-name($item)"/> + <xsl:if test="$pathminmaxcount = 3 and not($pathtype = 'HMI_INT' or $pathtype = 'HMI_REAL')"> + <xsl:message terminate="yes"> + <xsl:text>Widget id:</xsl:text> + <xsl:value-of select="$id"/> + <xsl:text> label:</xsl:text> + <xsl:value-of select="$label"/> + <xsl:text> path section </xsl:text> + <xsl:value-of select="$pathminmax"/> + <xsl:text> use min and max on non mumeric value</xsl:text> + </xsl:message> + </xsl:if> + <xsl:if test="count($item) = 1"> + <xsl:attribute name="index"> + <xsl:value-of select="$item/@index"/> + </xsl:attribute> + <xsl:attribute name="type"> + <xsl:value-of select="$pathtype"/> + </xsl:attribute> + </xsl:if> </xsl:otherwise> </xsl:choose> </path> @@ -1223,6 +1276,8 @@ </xsl:text> <xsl:text> if(typeof(index) == "string"){ </xsl:text> + <xsl:text> /* XXX return index as path */ +</xsl:text> <xsl:text> index = page_local_index(index, this.container_id); </xsl:text> <xsl:text> } else { @@ -1233,19 +1288,27 @@ </xsl:text> <xsl:text> } </xsl:text> + <xsl:text> /* XXX check for hmi_paths and return path */ +</xsl:text> <xsl:text> } </xsl:text> <xsl:text> return index; </xsl:text> <xsl:text> } </xsl:text> + <xsl:text> +</xsl:text> <xsl:text> change_hmi_value(index, opstr) { </xsl:text> <xsl:text> let realindex = this.get_variable_index(index); </xsl:text> <xsl:text> if(realindex == undefined) return undefined; </xsl:text> - <xsl:text> return change_hmi_value(realindex, opstr); + <xsl:text> let old_val = cache[realindex]; +</xsl:text> + <xsl:text> let new_val = eval_operation_string(old_val, opstr); +</xsl:text> + <xsl:text> return apply_hmi_value(realindex, new_val); </xsl:text> <xsl:text> } </xsl:text> @@ -3995,7 +4058,7 @@ </xsl:text> <xsl:text> on_op_click(opstr) { </xsl:text> - <xsl:text> let new_val = this.change_hmi_value(0, opstr); + <xsl:text> this.change_hmi_value(0, opstr); </xsl:text> <xsl:text> } </xsl:text> @@ -6827,71 +6890,83 @@ </xsl:text> <xsl:text> </xsl:text> + <xsl:text>function eval_operation_string(old_val, opstr) { +</xsl:text> + <xsl:text> let op = opstr[0]; +</xsl:text> + <xsl:text> let given_val; +</xsl:text> + <xsl:text> if(opstr.length < 2) +</xsl:text> + <xsl:text> return undefined; +</xsl:text> + <xsl:text> if(opstr[1] in quotes){ +</xsl:text> + <xsl:text> if(opstr.length < 3) +</xsl:text> + <xsl:text> return undefined; +</xsl:text> + <xsl:text> if(opstr[opstr.length-1] == opstr[1]){ +</xsl:text> + <xsl:text> given_val = opstr.slice(2,opstr.length-1); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } else { +</xsl:text> + <xsl:text> given_val = Number(opstr.slice(1)); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> let new_val; +</xsl:text> + <xsl:text> switch(op){ +</xsl:text> + <xsl:text> case "=": +</xsl:text> + <xsl:text> new_val = given_val; +</xsl:text> + <xsl:text> break; +</xsl:text> + <xsl:text> case "+": +</xsl:text> + <xsl:text> new_val = old_val + given_val; +</xsl:text> + <xsl:text> break; +</xsl:text> + <xsl:text> case "-": +</xsl:text> + <xsl:text> new_val = old_val - given_val; +</xsl:text> + <xsl:text> break; +</xsl:text> + <xsl:text> case "*": +</xsl:text> + <xsl:text> new_val = old_val * given_val; +</xsl:text> + <xsl:text> break; +</xsl:text> + <xsl:text> case "/": +</xsl:text> + <xsl:text> new_val = old_val / given_val; +</xsl:text> + <xsl:text> break; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> return new_val; +</xsl:text> + <xsl:text>} +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text>/* +</xsl:text> <xsl:text>function change_hmi_value(index, opstr) { </xsl:text> - <xsl:text> let op = opstr[0]; -</xsl:text> - <xsl:text> let given_val; -</xsl:text> - <xsl:text> if(opstr.length < 2) -</xsl:text> - <xsl:text> return undefined; // TODO raise -</xsl:text> - <xsl:text> if(opstr[1] in quotes){ -</xsl:text> - <xsl:text> if(opstr.length < 3) -</xsl:text> - <xsl:text> return undefined; // TODO raise -</xsl:text> - <xsl:text> if(opstr[opstr.length-1] == opstr[1]){ -</xsl:text> - <xsl:text> given_val = opstr.slice(2,opstr.length-1); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> } else { -</xsl:text> - <xsl:text> given_val = Number(opstr.slice(1)); -</xsl:text> - <xsl:text> } -</xsl:text> <xsl:text> let old_val = cache[index]; </xsl:text> - <xsl:text> let new_val; -</xsl:text> - <xsl:text> switch(op){ -</xsl:text> - <xsl:text> case "=": -</xsl:text> - <xsl:text> new_val = given_val; -</xsl:text> - <xsl:text> break; -</xsl:text> - <xsl:text> case "+": -</xsl:text> - <xsl:text> new_val = old_val + given_val; -</xsl:text> - <xsl:text> break; -</xsl:text> - <xsl:text> case "-": -</xsl:text> - <xsl:text> new_val = old_val - given_val; -</xsl:text> - <xsl:text> break; -</xsl:text> - <xsl:text> case "*": -</xsl:text> - <xsl:text> new_val = old_val * given_val; -</xsl:text> - <xsl:text> break; -</xsl:text> - <xsl:text> case "/": -</xsl:text> - <xsl:text> new_val = old_val / given_val; -</xsl:text> - <xsl:text> break; -</xsl:text> - <xsl:text> } + <xsl:text> let new_val = eval_operation_string(old_val, opstr); </xsl:text> <xsl:text> if(new_val != undefined && old_val != new_val) </xsl:text> @@ -6903,6 +6978,8 @@ </xsl:text> <xsl:text>} </xsl:text> + <xsl:text>*/ +</xsl:text> <xsl:text> </xsl:text> <xsl:text>var current_visible_page; diff -r fc5a0b1ece10 -r a098b2dd9dff svghmi/hmi_tree.ysl2 --- a/svghmi/hmi_tree.ysl2 Tue Dec 22 14:57:59 2020 +0100 +++ b/svghmi/hmi_tree.ysl2 Thu Dec 24 16:56:19 2020 +0100 @@ -24,7 +24,7 @@ foreach "$indexed_hmitree/*" | /* «@index» «@hmipath» */ "«substring(local-name(), 5)»"`if "position()!=last()" > ,` - | ] + | ]; | } @@ -67,19 +67,20 @@ } // Parses: -// "HMI:WidgetType:param1:param2@path1@path2" +// "HMI:WidgetType:param1:param2@path1,path1min,path1max@path2" // // Into: // widget type="WidgetType" id="blah456" { // arg value="param1"; // arg value="param2"; -// path value=".path1" index=".path1" type="PAGE_LOCAL"; +// path value=".path1" index=".path1" min="path1min" max="path1max" type="PAGE_LOCAL"; // path value="/path1" index="348" type="HMI_INT"; // path value="path4" index="path4" type="HMI_LOCAL"; // } // template "*", mode="parselabel" { const "label","@inkscape:label"; + const "id","@id"; const "description", "substring-after($label,'HMI:')"; const "_args", "substring-before($description,'@')"; @@ -95,7 +96,7 @@ } if "$type" widget { - attrib "id" > «@id» + attrib "id" > «$id» attrib "type" > «$type» foreach "str:split(substring-after($args, ':'), ':')" { arg { @@ -105,22 +106,35 @@ const "paths", "substring-after($description,'@')"; foreach "str:split($paths, '@')" { if "string-length(.) > 0" path { - attrib "value" > «.» - const "path", "."; - const "item", "$indexed_hmitree/*[@hmipath = $path]"; + const "pathminmax", "str:split(.,',')"; + const "path", "$pathminmax[1]"; + const "pathminmaxcount", "count($pathminmax)"; + attrib "value" > «$path» choose { - when "count($item) = 1" { - attrib "index" > «$item/@index» - attrib "type" > «local-name($item)» + when "$pathminmaxcount = 3" { + attrib "min" > «$pathminmax[2]» + attrib "max" > «$pathminmax[3]» + } + when "$pathminmaxcount = 2" { + error > Widget id:«$id» label:«$label» has wrong syntax of path section «$pathminmax» + } + } + choose { + when "regexp:test($path,'^\.[a-zA-Z0-9_]+')" { + attrib "type" > PAGE_LOCAL + } + when "regexp:test($path,'^[a-zA-Z0-9_]+')" { + attrib "type" > HMI_LOCAL } otherwise { - choose { - when "regexp:test($path,'^\.[a-zA-Z0-9_]+')" { - attrib "type" > PAGE_LOCAL - } - when "regexp:test($path,'^[a-zA-Z0-9_]+')" { - attrib "type" > HMI_LOCAL - } + const "item", "$indexed_hmitree/*[@hmipath = $path]"; + const "pathtype", "local-name($item)"; + if "$pathminmaxcount = 3 and not($pathtype = 'HMI_INT' or $pathtype = 'HMI_REAL')" { + error > Widget id:«$id» label:«$label» path section «$pathminmax» use min and max on non mumeric value + } + if "count($item) = 1" { + attrib "index" > «$item/@index» + attrib "type" > «$pathtype» } } } diff -r fc5a0b1ece10 -r a098b2dd9dff tests/svghmi/svghmi_0@svghmi/svghmi.svg --- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg Tue Dec 22 14:57:59 2020 +0100 +++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg Thu Dec 24 16:56:19 2020 +0100 @@ -304,7 +304,7 @@ </g> <g id="g84" - inkscape:label="HMI:Input@/TARGETPRESSURE" + inkscape:label="HMI:Input@/TARGETPRESSURE,0,100" transform="matrix(0.35865594,0,0,0.35865594,22.072155,63.074421)"> <text inkscape:label="value"