# HG changeset patch # User Edouard Tisserant # Date 1584440647 -3600 # Node ID 682bce95379598f67df85b861c1da940e3271b09 # Parent d2adbc273125bb4437130448cd58e1112cdb1cee SVGHMI: detachable_elements.ysl2 becomes detachable_pages.ysl2, and includes logic to process pages elements. Other minor code moves. diff -r d2adbc273125 -r 682bce953795 svghmi/detachable_elements.ysl2 --- a/svghmi/detachable_elements.ysl2 Tue Mar 17 10:34:26 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -// detachable_elements.ysl2 -// -// compute what elements are required by pages -// and decide where to cut when removing/attaching -// pages elements on page switch - -// returns all directly or indirectly refered elements -def "func:refered_elements" { - param "elems"; - const "descend", "$elems/descendant-or-self::svg:*"; - const "clones", "$descend[self::svg:use]"; - const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]"; - choose { - when "$originals" - result "$descend | func:refered_elements($originals)"; - otherwise - result "$descend"; - } -} - -def "func:all_related_elements" { - param "page"; - const "page_overlapping_geometry", "func:overlapping_geometry($page)"; - const "page_overlapping_elements", "//svg:*[@id = $page_overlapping_geometry/@Id]"; - const "page_sub_elements", "func:refered_elements($page | $page_overlapping_elements)"; - result "$page_sub_elements"; -} - -def "func:required_elements" { - param "pages"; - choose{ - when "$pages"{ - result """func:all_related_elements($pages[1]) - | func:required_elements($pages[position()!=1])"""; - }otherwise{ - result "/.."; - } - } -} - -const "required_elements", - """//svg:defs/descendant-or-self::svg:* - | func:required_elements($hmi_pages)/ancestor-or-self::svg:*"""; - -const "discardable_elements", "//svg:*[not(@id = $required_elements/@id)]"; - -def "func:sumarized_elements" { - param "elements"; - const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]"; - const "filled_groups", """$short_list/parent::svg:*[ - not(descendant::*[ - not(self::svg:g) and - not(@id = $discardable_elements/@id) and - not(@id = $short_list/descendant-or-self::*[not(self::svg:g)]/@id) - ])]"""; - const "groups_to_add", "$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"; - result "$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]"; -} - -def "func:detachable_elements" { - param "pages"; - choose{ - when "$pages"{ - result """func:sumarized_elements(func:all_related_elements($pages[1])) - | func:detachable_elements($pages[position()!=1])"""; - }otherwise{ - result "/.."; - } - } -} - -// Avoid nested detachables -const "_detachable_elements", "func:detachable_elements($hmi_pages)"; -const "detachable_elements", "$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]"; - -function "debug_detachables" { - foreach "$detachable_elements"{ - | «@id» - } -} -!debug_output_calls.append("debug_detachables") diff -r d2adbc273125 -r 682bce953795 svghmi/detachable_pages.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svghmi/detachable_pages.ysl2 Tue Mar 17 11:24:07 2020 +0100 @@ -0,0 +1,150 @@ +// detachable_elements.ysl2 +// +// compute what elements are required by pages +// 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 "default_page" choose { + when "count($hmi_pages) > 1" { + const "Home_page", + "$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"; + choose { + when "$Home_page" > Home + otherwise { + error "No Home page defined!"; + } + } + } + when "count($hmi_pages) = 0" { + error "No page defined!"; + } + otherwise > «func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value» +} + +// returns all directly or indirectly refered elements +def "func:refered_elements" { + param "elems"; + const "descend", "$elems/descendant-or-self::svg:*"; + const "clones", "$descend[self::svg:use]"; + const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]"; + choose { + when "$originals" + result "$descend | func:refered_elements($originals)"; + otherwise + result "$descend"; + } +} + +def "func:all_related_elements" { + param "page"; + const "page_overlapping_geometry", "func:overlapping_geometry($page)"; + const "page_overlapping_elements", "//svg:*[@id = $page_overlapping_geometry/@Id]"; + const "page_sub_elements", "func:refered_elements($page | $page_overlapping_elements)"; + result "$page_sub_elements"; +} + +def "func:required_elements" { + param "pages"; + choose{ + when "$pages"{ + result """func:all_related_elements($pages[1]) + | func:required_elements($pages[position()!=1])"""; + }otherwise{ + result "/.."; + } + } +} + +const "required_elements", + """//svg:defs/descendant-or-self::svg:* + | func:required_elements($hmi_pages)/ancestor-or-self::svg:*"""; + +const "discardable_elements", "//svg:*[not(@id = $required_elements/@id)]"; + +def "func:sumarized_elements" { + param "elements"; + const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]"; + const "filled_groups", """$short_list/parent::svg:*[ + not(descendant::*[ + not(self::svg:g) and + not(@id = $discardable_elements/@id) and + not(@id = $short_list/descendant-or-self::*[not(self::svg:g)]/@id) + ])]"""; + const "groups_to_add", "$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"; + result "$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]"; +} + +def "func:detachable_elements" { + param "pages"; + choose{ + when "$pages"{ + result """func:sumarized_elements(func:all_related_elements($pages[1])) + | func:detachable_elements($pages[position()!=1])"""; + }otherwise{ + result "/.."; + } + } +} + +// Avoid nested detachables +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)"; +} + +template "svg:*", mode="page_desc" { + const "desc", "func:parselabel(@inkscape:label)/widget"; + 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]"; + + const "page_relative_widgets", + "$all_page_widgets[func:is_descendant_path(func:parselabel(@inkscape:label)/widget/path/@value, $desc/path/@value)]"; + + // Take closest ancestor in detachable_elements + // since nested detachable elements are filtered out + const "required_detachables", + """func:sumarized_elements($page_all_elements)/ + ancestor-or-self::*[@id = $detachable_elements/@id]"""; + + | "«$desc/arg[1]/@value»": { + | widget: hmi_widgets["«@id»"], + | bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»], + if "$desc/path/@value" { + if "count($desc/path/@index)=0" + warning > Page id="«$page/@id»" : No match for path "«$desc/path/@value»" in HMI tree + | page_index: «$desc/path/@index», + } + | relative_widgets: [ + foreach "$page_relative_widgets" { + | hmi_widgets["«@id»"]`if "position()!=last()" > ,` + } + | ], + | absolute_widgets: [ + foreach "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" { + | hmi_widgets["«@id»"]`if "position()!=last()" > ,` + } + | ], + | required_detachables: { + foreach "$required_detachables" { + | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` + } + | } + | }`if "position()!=last()" > ,` +} + +function "debug_detachables" { + foreach "$detachable_elements"{ + | «@id» + } +} +!debug_output_calls.append("debug_detachables") diff -r d2adbc273125 -r 682bce953795 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Tue Mar 17 10:34:26 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Tue Mar 17 11:24:07 2020 +0100 @@ -1,30 +1,7 @@ - - - - - - - - - - Home - - - No Home page defined! - - - - - No page defined! - - - - - - + HMI_ROOT @@ -37,134 +14,6 @@ - - - ID, x, y, w, h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -223,202 +72,6 @@ - - - - - - - - - =" - - " - - - - - - - - - - - Raw HMI tree - - - - - Indexed HMI tree - - - - - - - - - - - - - - - - - - - - - none - - - 100vh - - - 100vw - - - - - - - ViewBox settings other than X=0, Y=0 and Scale=1 are not supported - - - - - All units must be set to "px" in Inkscape's document properties - - - - - - - - - - - - - - - - - - href - - - width - - - height - - - x - - - y - - - - - - - - - - - - - - - - - - - - - _ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Made with SVGHMI. https://beremiz.org - - - - - debug_geometry: - - - - - - - - - debug_detachables: - - - - - - - - - debug_hmitree: - - - - - - - Unlinked : - - - - - - - - - - - - - - - @@ -479,6 +132,445 @@ + + + + + + + + + =" + + " + + + + + + + + + + + Raw HMI tree + + + + + Indexed HMI tree + + + + + + ID, x, y, w, h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Home + + + No Home page defined! + + + + + No page defined! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " + + ": { + + widget: hmi_widgets[" + + "], + + bbox: [ + + , + + , + + , + + ], + + + + + Page id=" + + " : No match for path " + + " in HMI tree + + + page_index: + + , + + + relative_widgets: [ + + + hmi_widgets[" + + "] + + , + + + + + ], + + absolute_widgets: [ + + + hmi_widgets[" + + "] + + , + + + + + ], + + required_detachables: { + + + " + + ": detachable_elements[" + + "] + + , + + + + + } + + } + + , + + + + + + + + + + + + + + + + + + + + + + + + + none + + + 100vh + + + 100vw + + + + + + + ViewBox settings other than X=0, Y=0 and Scale=1 are not supported + + + + + All units must be set to "px" in Inkscape's document properties + + + + + + + + + + + + + + + + + + href + + + width + + + height + + + x + + + y + + + + + + + + + + + + + + + + + + + + + _ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Made with SVGHMI. https://beremiz.org + + + + + debug_hmitree: + + + + + + + + + debug_geometry: + + + + + + + + + debug_detachables: + + + + + + + Unlinked : + + + + + + + + + + + + + + + //(function(){ @@ -613,98 +705,7 @@ var page_desc = { - - - - - - - - - " - - ": { - - widget: hmi_widgets[" - - "], - - bbox: [ - - , - - , - - , - - ], - - - - - Page id=" - - " : No match for path " - - " in HMI tree - - - page_index: - - , - - - relative_widgets: [ - - - hmi_widgets[" - - "] - - , - - - - - ], - - absolute_widgets: [ - - - hmi_widgets[" - - "] - - , - - - - - ], - - required_detachables: { - - - " - - ": detachable_elements[" - - "] - - , - - - - - } - - } - - , - - - - + } diff -r d2adbc273125 -r 682bce953795 svghmi/gen_index_xhtml.ysl2 --- a/svghmi/gen_index_xhtml.ysl2 Tue Mar 17 10:34:26 2020 +0100 +++ b/svghmi/gen_index_xhtml.ysl2 Tue Mar 17 11:24:07 2020 +0100 @@ -36,47 +36,14 @@ exclude-result-prefixes="ns str regexp exsl func dyn" { + include hmi_tree.ysl2 + + include geometry.ysl2 + const "svg_root_id", "/svg:svg/@id"; const "hmi_elements", "//svg:*[starts-with(@inkscape:label, 'HMI:')]"; - const "hmi_pages", "$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"; - - const "default_page" choose { - when "count($hmi_pages) > 1" { - const "Home_page", - "$hmi_pages[func:parselabel(@inkscape:label)/widget/arg[1]/@value = 'Home']"; - choose { - when "$Home_page" > Home - otherwise { - error "No Home page defined!"; - } - } - } - when "count($hmi_pages) = 0" { - error "No page defined!"; - } - otherwise > «func:parselabel($hmi_pages/@inkscape:label)/widget/arg[1]/@value» - } - - const "_categories" { - noindex > HMI_ROOT - noindex > HMI_PLC_STATUS - noindex > HMI_CURRENT_PAGE - } - const "categories", "exsl:node-set($_categories)"; - - include geometry.ysl2 - - include detachable_elements.ysl2 - - include hmi_tree.ysl2 - - - def "func:is_descendant_path" { - param "descend"; - param "ancest"; - result "string-length($ancest) > 0 and starts-with($descend,$ancest)"; - } + include detachable_pages.ysl2 //////////////// Inline SVG @@ -230,43 +197,6 @@ } */ - def "func:parselabel" { - param "label"; - const "description", "substring-after($label,'HMI:')"; - - const "_args", "substring-before($description,'@')"; - const "args" choose { - when "$_args" value "$_args"; - otherwise value "$description"; - } - - const "_type", "substring-before($args,':')"; - const "type" choose { - when "$_type" value "$_type"; - otherwise value "$args"; - } - - const "ast" if "$type" widget { - attrib "type" > «$type» - foreach "str:split(substring-after($args, ':'), ':')" { - arg { - attrib "value" > «.» - } - } - const "paths", "substring-after($description,'@')"; - foreach "str:split($paths, '@')" { - if "string-length(.) > 0" path { - attrib "value" > «.» - const "path", "."; - const "item", "$indexed_hmitree/*[@hmipath = $path]"; - if "count($item) = 1" - attrib "index" > «$item/@index» - } - } - } - - result "exsl:node-set($ast)"; - } function "scripts" { @@ -341,50 +271,7 @@ | | var page_desc = { - - foreach "$hmi_pages" { - const "desc", "func:parselabel(@inkscape:label)/widget"; - 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]"; - - const "page_relative_widgets", - "$all_page_widgets[func:is_descendant_path(func:parselabel(@inkscape:label)/widget/path/@value, $desc/path/@value)]"; - - // Take closest ancestor in detachable_elements - // since nested detachable elements are filtered out - const "required_detachables", - """func:sumarized_elements($page_all_elements)/ - ancestor-or-self::*[@id = $detachable_elements/@id]"""; - - | "«$desc/arg[1]/@value»": { - | widget: hmi_widgets["«@id»"], - | bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»], - if "$desc/path/@value" { - if "count($desc/path/@index)=0" - warning > Page id="«$page/@id»" : No match for path "«$desc/path/@value»" in HMI tree - | page_index: «$desc/path/@index», - } - | relative_widgets: [ - foreach "$page_relative_widgets" { - | hmi_widgets["«@id»"]`if "position()!=last()" > ,` - } - | ], - | absolute_widgets: [ - foreach "$all_page_widgets[not(@id = $page_relative_widgets/@id)]" { - | hmi_widgets["«@id»"]`if "position()!=last()" > ,` - } - | ], - | required_detachables: { - foreach "$required_detachables" { - | "«@id»": detachable_elements["«@id»"]`if "position()!=last()" > ,` - } - | } - | }`if "position()!=last()" > ,` - } + apply "$hmi_pages", mode="page_desc"; | } | diff -r d2adbc273125 -r 682bce953795 svghmi/hmi_tree.ysl2 --- a/svghmi/hmi_tree.ysl2 Tue Mar 17 10:34:26 2020 +0100 +++ b/svghmi/hmi_tree.ysl2 Tue Mar 17 11:24:07 2020 +0100 @@ -4,6 +4,12 @@ // HMI Tree computed from VARIABLES.CSV in svghmi.py const "hmitree", "ns:GetHMITree()"; +const "_categories" { + noindex > HMI_ROOT + noindex > HMI_PLC_STATUS + noindex > HMI_CURRENT_PAGE +} +const "categories", "exsl:node-set($_categories)"; // HMI Tree Index const "_indexed_hmitree" apply "$hmitree", mode="index"; @@ -46,6 +52,44 @@ } } +def "func:parselabel" { + param "label"; + const "description", "substring-after($label,'HMI:')"; + + const "_args", "substring-before($description,'@')"; + const "args" choose { + when "$_args" value "$_args"; + otherwise value "$description"; + } + + const "_type", "substring-before($args,':')"; + const "type" choose { + when "$_type" value "$_type"; + otherwise value "$args"; + } + + const "ast" if "$type" widget { + attrib "type" > «$type» + foreach "str:split(substring-after($args, ':'), ':')" { + arg { + attrib "value" > «.» + } + } + const "paths", "substring-after($description,'@')"; + foreach "str:split($paths, '@')" { + if "string-length(.) > 0" path { + attrib "value" > «.» + const "path", "."; + const "item", "$indexed_hmitree/*[@hmipath = $path]"; + if "count($item) = 1" + attrib "index" > «$item/@index» + } + } + } + + result "exsl:node-set($ast)"; +} + // Debug data template "*", mode="testtree"{ param "indent", "''";