# HG changeset patch # User Edouard Tisserant # Date 1597924581 -7200 # Node ID 440d74319a74f6f9ade1a12c94bf9fac52c587b1 # Parent 2d13a4379e2fad4d5292a9dd46deb55300827376 SVGHMI: Refactor the way JsonTable generate javascript code to access json data. Now support multiple assignments, used in the case of text to change both content and style on the same element. diff -r 2d13a4379e2f -r 440d74319a74 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Thu Aug 20 13:52:00 2020 +0200 +++ b/svghmi/gen_index_xhtml.xslt Thu Aug 20 13:56:21 2020 +0200 @@ -637,7 +637,10 @@ - + + + + @@ -672,19 +675,24 @@ - + + + + + + - + - + @@ -705,6 +713,9 @@ y + + id + @@ -718,8 +729,27 @@ + + + + + + _ + + + + + + + + + + + + + @@ -746,7 +776,7 @@ - + @@ -756,7 +786,7 @@ - + @@ -769,10 +799,32 @@ _ + + + + + + + + + + + + + + + + + + + + + + @@ -1024,8 +1076,6 @@ let defaultval = local_defaults[varname]; - console.log("page_local_index creat local", varname, pagename, new_index, defaultval); - if(defaultval != undefined) cache[new_index] = defaultval; @@ -3365,60 +3415,177 @@ . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JsonTable : missplaced '=' or inconsistent names in Json data expressions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdata + + + + - + - - - Clones (svg:use) in JsonTable Widget must point to a valid HMI:List widget or HMI:List item. Reference " - - " is not valid. - - - id(" - - ").setAttribute("xlink:href", - - "#"+hmi_widgets[" - - "].items[ - - ]); - + + + id(" + + ").setAttribute("xlink:href", + + "#"+hmi_widgets[" + + "].items[ + + ]); + + + + + Clones (svg:use) in JsonTable Widget must point to a valid HMI:List widget or item. Reference " + + " is not valid and will not be updated. + + + - - id(" - - ").textContent = String( - - ); - - + + + + + + + + + + Clones (svg:use) in JsonTable Widget pointing to a HMI:TextStyleList widget or item must have a "textContent=.someVal" assignement following value expression in label. + + + { + + let elt = id(" + + "); + + elt.textContent = String( + + ); + + elt.style = hmi_widgets[" + + "].styles[ + + ]; + + } + + + + id(" + + ").textContent = String( + + ); + + + + + + + + + + + + + + + + + + + - + + + - - - - + - - let obj_ - - = - - - ; - - - - obj_ - - + + + + + + @@ -3440,7 +3607,8 @@ spread_json_data: function(jdata) { - + + } @@ -4079,7 +4247,7 @@ - + : " ", @@ -4088,6 +4256,22 @@ }, + + + styles: { + + + + + + : " + + ", + + + }, + + frequency: 10, diff -r 2d13a4379e2f -r 440d74319a74 svghmi/widget_jsontable.ysl2 --- a/svghmi/widget_jsontable.ysl2 Thu Aug 20 13:52:00 2020 +0200 +++ b/svghmi/widget_jsontable.ysl2 Thu Aug 20 13:56:21 2020 +0200 @@ -41,44 +41,128 @@ const "hmi_textstylelists_descs", "$parsed_widgets/widget[@type = 'TextStyleList']"; const "hmi_textstylelists", "$hmi_elements[@id = $hmi_textstylelists_descs/@id]"; +const "textstylelist_related" foreach "$hmi_textstylelists" list { + attrib "listid" value "@id"; + foreach "func:refered_elements(.)" elt { + attrib "eltid" value "@id"; + } +} +const "textstylelist_related_ns", "exsl:node-set($textstylelist_related)"; + +def "func:json_expressions" { + param "expressions"; + param "label"; + + // compute javascript expressions to access JSON data + // desscribed in given svg element's "label" + // knowing that parent element already has given "expressions". + + choose { + when "$label" { + const "suffixes", "str:split($label)"; + const "res" foreach "$suffixes" expression { + const "suffix","."; + const "pos","position()"; + // take last available expression (i.e can have more suffixes than expressions) + const "expr","$expressions[position() <= $pos][last()]/expression"; + choose { + when "contains($suffix,'=')" { + const "name", "substring-before($suffix,'=')"; + if "$expr/@name[. != $name]" + error > JsonTable : missplaced '=' or inconsistent names in Json data expressions. + attrib "name" value "$name"; + attrib "content" > «$expr/@content»«substring-after($suffix,'=')» + } + otherwise { + copy "$expr/@name"; + attrib "content" > «$expr/@content»«$suffix» + } + } + } + result "exsl:node-set($res)"; + } + // Empty labels are ignored, expressions are then passed as-is. + otherwise result "$expressions"; + } + +} + +const "initexpr" expression attrib "content" > jdata +const "initexpr_ns", "exsl:node-set($initexpr)"; + template "svg:use", mode="json_table_elt_render" { - param "value_expr"; + param "expressions"; // cloned element must be part of a HMI:List const "targetid", "substring-after(@xlink:href,'#')"; const "from_list", "$hmi_lists[(@id | */@id) = $targetid]"; - const "from_textstylelist", "$hmi_textstylelists[(@id | */@id) = $targetid]"; choose { when "count($from_list) > 0" { | id("«@id»").setAttribute("xlink:href", // obtain new target id from HMI:List widget - | "#"+hmi_widgets["«$from_list/@id»"].items[«$value_expr»]); - } - when "count($from_textstylelist) > 0" { - | console.log("from_textsylelist","«@id»", "«$value_expr»", «$value_expr», - // obtain new style from HMI:TextStyleList widget - | hmi_widgets["«$from_textstylelist/@id»"].items[«$value_expr»]); + | "#"+hmi_widgets["«$from_list/@id»"].items[«$expressions/expression[1]/@content»]); } otherwise - warning > Clones (svg:use) in JsonTable Widget must point to a valid HMI:List or HMI:TextStyleList widget or item. Reference "«@xlink:href»" is not valid and will not be updated. + warning > Clones (svg:use) in JsonTable Widget must point to a valid HMI:List widget or item. Reference "«@xlink:href»" is not valid and will not be updated. } } template "svg:text", mode="json_table_elt_render" { - param "value_expr"; - | id("«@id»").textContent = String(«$value_expr»); + param "expressions"; + const "value_expr", "$expressions/expression[1]/@content"; + const "original", "@original"; + const "from_textstylelist", "$textstylelist_related_ns/list[elt/@eltid = $original]"; + choose { + + when "count($from_textstylelist) > 0" { + const "content_expr", "$expressions/expression[2]/@content"; + if "string-length($content_expr) = 0 or $expressions/expression[2]/@name != 'textContent'" + error > Clones (svg:use) in JsonTable Widget pointing to a HMI:TextStyleList widget or item must have a "textContent=.someVal" assignement following value expression in label. + | { + | let elt = id("«@id»"); + | elt.textContent = String(«$content_expr»); + | elt.style = hmi_widgets["«$from_textstylelist/@listid»"].styles[«$value_expr»]; + | } + } + otherwise { + | id("«@id»").textContent = String(«$value_expr»); + } + } +} + + +// only labels comming from Json widget are counted in +def "func:filter_non_widget_label" { + param "elt"; + param "widget_elts"; + const "eltid" choose { + when "$elt/@original" value "$elt/@original"; + otherwise value "$elt/@id"; + } + result "$widget_elts[@id=$eltid]/@inkscape:label"; } template "svg:*", mode="json_table_render" { - param "objname"; - apply ".", mode="json_table_elt_render" with "value_expr" > «$objname»«substring-before(@inkscape:label, ' ')» + param "expressions"; + param "widget_elts"; + const "label", "func:filter_non_widget_label(., $widget_elts)"; + apply ".", mode="json_table_elt_render" { + with "expressions", "func:json_expressions($expressions, $label)"; + } } template "svg:g", mode="json_table_render" { - param "objname"; - | let obj_«@id» = «$objname»«substring-before(@inkscape:label, ' ')»; - apply "*[@inkscape:label]", mode="json_table_render" - with "objname" > obj_«@id» + param "expressions"; + param "widget_elts"; + /* TODO : use intermediate variables for optimization + foreach "$new_expressions" + | let obj_«@id»_«position()» = «.»; + */ + const "label", "func:filter_non_widget_label(., $widget_elts)"; + apply "*", mode="json_table_render" { + with "expressions", "func:json_expressions($expressions, $label)"; + with "widget_elts", "$widget_elts"; + } } template "widget[@type='JsonTable']", mode="widget_defs" { @@ -87,6 +171,9 @@ optional_labels("forward backward cursor"); const "data_elt", "$result_svg_ns//*[@id = $hmi_element/@id]/*[@inkscape:label = 'data']"; | spread_json_data: function(jdata) { - apply "$data_elt/*", mode="json_table_render" with "objname","'jdata'"; + apply "$data_elt/*", mode="json_table_render" { + with "expressions","$initexpr_ns"; + with "widget_elts","$hmi_element/*[@inkscape:label = 'data']/descendant::svg:*"; + } | } } diff -r 2d13a4379e2f -r 440d74319a74 svghmi/widget_list.ysl2 --- a/svghmi/widget_list.ysl2 Thu Aug 20 13:52:00 2020 +0200 +++ b/svghmi/widget_list.ysl2 Thu Aug 20 13:56:21 2020 +0200 @@ -1,10 +1,20 @@ // widget_list.ysl2 -template "widget[@type='List' or @type='TextStyleList']", mode="widget_defs" { +template "widget[@type='List']", mode="widget_defs" { param "hmi_element"; | items: { foreach "$hmi_element/*[@inkscape:label]" { - | «func:escape_quotes(@inkscape:label)»: "«@id»", + | «@inkscape:label»: "«@id»", } | }, } + +template "widget[@type='TextStyleList']", mode="widget_defs" { + param "hmi_element"; + | styles: { + foreach "$hmi_element/*[@inkscape:label]" { + const "style", "func:refered_elements(.)[self::svg:text]/@style"; + | «@inkscape:label»: "«$style»", + } + | }, +} diff -r 2d13a4379e2f -r 440d74319a74 tests/svghmi/py_ext_0@py_ext/pyfile.xml --- a/tests/svghmi/py_ext_0@py_ext/pyfile.xml Thu Aug 20 13:52:00 2020 +0200 +++ b/tests/svghmi/py_ext_0@py_ext/pyfile.xml Thu Aug 20 13:56:21 2020 +0200 @@ -18,10 +18,10 @@ newdata = request.content.getvalue() print newdata selected_alarms = [ - {"name":"three", "sides":3}, - {"name":"four", "sides":4}, - {"name":"five", "sides":5}, - {"name":"six", "sides":6}, + {"name":"three", "sides":3, "textstyle":"alarm"}, + {"name":"four", "sides":4, "textstyle":"ack"}, + {"name":"five", "sides":5, "textstyle":"active"}, + {"name":"six", "sides":6, "textstyle":"disabled"}, ] return json.dumps(selected_alarms) diff -r 2d13a4379e2f -r 440d74319a74 tests/svghmi/svghmi_0@svghmi/svghmi.svg --- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg Thu Aug 20 13:52:00 2020 +0200 +++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg Thu Aug 20 13:56:21 2020 +0200 @@ -16,7 +16,7 @@ version="1.1" id="hmi0" sodipodi:docname="svghmi.svg" - inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> + inkscape:version="0.92.3 (2405546, 2018-03-11)"> @@ -182,17 +182,17 @@ inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:document-units="px" - inkscape:current-layer="g907" + inkscape:current-layer="g1384" showgrid="false" units="px" inkscape:zoom="0.50000001" - inkscape:cx="632.83299" - inkscape:cy="-317.59408" - inkscape:window-width="2443" - inkscape:window-height="1567" - inkscape:window-x="816" - inkscape:window-y="103" - inkscape:window-maximized="0" + inkscape:cx="503.83301" + inkscape:cy="474.4059" + inkscape:window-width="1800" + inkscape:window-height="836" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" /> + style="fill:none;fill-rule:evenodd;stroke:#ff3000;stroke-width:2.9633333;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:29.63333301;stroke-opacity:1;marker-end:url(#marker1656)" />