--- a/svghmi/gen_index_xhtml.xslt Fri Feb 21 16:22:44 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Thu Feb 27 13:14:24 2020 +0100
@@ -126,40 +126,6 @@
<xsl:text>All units must be set to "px" in Inkscape's document properties</xsl:text>
- <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:use">
- <xsl:attribute name="style">
- <xsl:value-of select="@style"/>
- <xsl:attribute name="transform">
- <xsl:value-of select="@transform"/>
- <xsl:attribute name="id">
- <xsl:value-of select="@id"/>
- <xsl:variable name="targetid" select="substring-after(@xlink:href,'#')"/>
- <xsl:apply-templates mode="unlink_clone" select="//svg:*[@id = $targetid]"/>
- <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@*">
- <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="svg:*">
- <xsl:when test="@id = $hmi_elements/@id">
- <xsl:attribute name="xlink:href">
- <xsl:value-of select="concat('#',@id)"/>
- <xsl:apply-templates mode="unlink_clone" select="@* | node()"/>
<xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
@@ -238,17 +204,35 @@
<xsl:param name="elems"/>
<xsl:variable name="descend" select="$elems/descendant-or-self::svg:*"/>
<xsl:variable name="clones" select="$descend[self::svg:use]"/>
- <xsl:variable name="reals" select="$descend[not(self::svg:use)]"/>
<xsl:variable name="originals" select="//svg:*[concat('#',@id) = $clones/@xlink:href]"/>
<xsl:when test="$originals">
- <func:result select="$reals | func:refered_elements($originals)"/>
+ <func:result select="$descend | func:refered_elements($originals)"/> - <func:result select="$reals"/>
+ <func:result select="$descend"/> + <func:function name="func:included_geometry"> + <xsl:param name="elt"/> + <xsl:variable name="g" select="$geometry[@Id = $elt/@id]"/> + <func:result select="$geometry[@Id != $elt/@id and @x >= $g/@x and @y >= $g/@y and @x+@w <= $g/@x+$g/@w and @y+@h <= $g/@y+$g/@h]"/> + <func:function name="func:sumarized_elements"> + <xsl:param name="elements"/> + <xsl:variable name="short_list" select="$elements[not(ancestor::*/@id = $elements/@id)]"/> + <xsl:variable name="filled_groups" select="$short_list/parent::svg:*[not(descendant::*[not(self::svg:g)][not(@id = $short_list/descendant-or-self::*[not(self::svg:g)]/@id)])]"/> + <xsl:variable name="groups_to_add" select="$filled_groups[not(ancestor::*/@id = $filled_groups/@id)]"/> + <func:result select="$groups_to_add | $short_list[not(ancestor::svg:g/@id = $filled_groups/@id)]"/> + <func:function name="func:all_related_elements"> + <xsl:param name="page"/> + <xsl:variable name="page_included_geometry" select="func:included_geometry($page)"/> + <xsl:variable name="page_sub_elements" select="func:refered_elements($page)"/> + <xsl:variable name="page_included_elements" select="//svg:*[@id = $page_included_geometry/@Id]"/> + <func:result select="$page_sub_elements | $page_included_elements"/> <xsl:template name="scripts">
@@ -359,10 +343,10 @@
<xsl:for-each select="$hmi_pages">
<xsl:variable name="desc" select="func:parselabel(@inkscape:label)/widget"/>
<xsl:variable name="page" select="."/>
- <xsl:variable name="p" select="$hmi_geometry[@Id = $page/@id]"/>
- <xsl:variable name="page_ids" select="$hmi_geometry[@Id != $page/@id and @x >= $p/@x and @y >= $p/@y and @x+@w <= $p/@x+$p/@w and @y+@h <= $p/@y+$p/@h]/@Id"/>
- <xsl:variable name="page_sub_ids" select="func:refered_elements($page)[@id = $hmi_elements/@id]/@id"/>
- <xsl:variable name="all_page_ids" select="$page_ids | $page_sub_ids[not(. = $page_ids)]"/>
+ <xsl:variable name="p" select="$geometry[@Id = $page/@id]"/> + <xsl:variable name="page_all_elements" select="func:all_related_elements($page)"/> + <xsl:variable name="all_page_ids" select="$page_all_elements[@id = $hmi_elements/@id and @id != $page/@id]/@id"/> + <xsl:variable name="shorter_list" select="func:sumarized_elements($page_all_elements)"/> <xsl:value-of select="$desc/arg[1]/@value"/>
@@ -395,6 +379,16 @@
+ <xsl:text> required_elements: [ + <xsl:for-each select="$shorter_list"> + <xsl:text> "</xsl:text> + <xsl:value-of select="@id"/> <xsl:if test="position()!=last()">
@@ -852,6 +846,32 @@
+ <xsl:text>function prepare_svg() { + <xsl:text> /* set everybody hidden initially for better performance */ + <xsl:text> for(let widget in hmi_widgets){ + <xsl:text> if(widget.element != undefined) + <xsl:text> widget.element.style.display = "none"; + <xsl:text> /*for(let name in page_desc){ + <xsl:text> if(name != new_desc){ + <xsl:text> page_desc[name].widget.element.style.display = "none"; <xsl:text>function switch_page(page_name) {
<xsl:text> let old_desc = page_desc[current_page];
@@ -862,18 +882,30 @@
<xsl:text> if(new_desc == undefined){
+ <xsl:text> /* TODO LOG ERROR */ - <xsl:text> /* remove subsribers of previous page if any */
<xsl:text> for(let widget of old_desc.widgets){
+ <xsl:text> /* hide widget */ + <xsl:text> if(widget.element != undefined) + <xsl:text> widget.element.style.display = "none"; + <xsl:text> /* remove subsribers */ <xsl:text> for(let index of widget.indexes){
<xsl:text> subscribers[index].delete(widget);
@@ -884,27 +916,23 @@
<xsl:text> old_desc.widget.element.style.display = "none";
- <xsl:text> /* initial page switch : set everybody hidden */
- <xsl:text> for(let name in page_desc){
- <xsl:text> if(name != new_desc){
- <xsl:text> page_desc[name].widget.element.style.display = "none";
- <xsl:text> /* add new subsribers if any */
+ <xsl:text> for(let widget of new_desc.widgets){ + <xsl:text> /* unhide widget */ - <xsl:text> for(let widget of new_desc.widgets){
+ <xsl:text> if(widget.element != undefined) + <xsl:text> widget.element.style.display = "inline"; + <xsl:text> /* add widget's subsribers */ <xsl:text> for(let index of widget.indexes){
@@ -952,6 +980,8 @@
<xsl:text> // show main page
+ <xsl:text> prepare_svg(); <xsl:text> switch_page(default_page);
--- a/svghmi/gen_index_xhtml.ysl2 Fri Feb 21 16:22:44 2020 +0100
+++ b/svghmi/gen_index_xhtml.ysl2 Thu Feb 27 13:14:24 2020 +0100
@@ -72,6 +72,10 @@
const "_indexed_hmitree" apply "$hmitree", mode="index";
const "indexed_hmitree", "exsl:node-set($_indexed_hmitree)";
+ // TODO globally discardable elements, not (used by | ancestor of) any page template "*", mode="index" {
param "parentpath", "''";
@@ -113,6 +117,7 @@
template "@* | node()", mode="inline_svg" {
/* use real xsl:copy instead copy-of alias from yslt.yml2 */
xsl:copy apply "@* | node()", mode="inline_svg";
+ /* TODO filter out globally discardable elements */ /* replaces inkscape's height and width hints. forces fit */
@@ -133,32 +138,35 @@
error > All units must be set to "px" in Inkscape's document properties
- /* clone unlinkink until widget for better perf with webkit */
- svgtmpl "svg:use", mode="inline_svg"
- attrib "style" > «@style»
- attrib "transform" > «@transform»
- /* keep same id and label in case it is a widget */
- //attrib "inkscape:label","@inkscape:label";
- const "targetid","substring-after(@xlink:href,'#')";
- apply "//svg:*[@id = $targetid]", mode="unlink_clone";
- svgtmpl "@*", mode="unlink_clone" xsl:copy;
- svgtmpl "svg:*", mode="unlink_clone" {
- when "@id = $hmi_elements/@id" {
- attrib "xlink:href" > «concat('#',@id)»
- xsl:copy apply "@* | node()", mode="unlink_clone";
+ //// Commented out before implementing runtime DOM remove/append on page switch - would have side effect + //// /* clone unlinkink until widget for better perf with webkit */ + //// svgtmpl "svg:use", mode="inline_svg" + //// attrib "style" > «@style» + //// attrib "transform" > «@transform» + //// /* keep same id and label in case it is a widget */ + //// //attrib "inkscape:label","@inkscape:label"; + //// attrib "id" > «@id» + //// const "targetid","substring-after(@xlink:href,'#')"; + //// apply "//svg:*[@id = $targetid]", mode="unlink_clone"; + //// svgtmpl "@*", mode="unlink_clone" xsl:copy; + //// svgtmpl "svg:*", mode="unlink_clone" { + //// when "@id = $hmi_elements/@id" { + //// attrib "xlink:href" > «concat('#',@id)» + //// xsl:copy apply "@* | node()", mode="unlink_clone"; // template "svg:use/@style", mode="inline_svg"{
// attrib "style" > all:initial;
@@ -212,7 +220,7 @@
- func:function name="func:parselabel" {
+ def "func:parselabel" { const "description", "substring-after($label,'HMI:')";
@@ -243,24 +251,51 @@
- func:result select="exsl:node-set($ast)"
+ result "exsl:node-set($ast)"; // returns all directly or indirectly refered elements
- func:function name="func:refered_elements" {
+ def "func:refered_elements" { const "descend", "$elems/descendant-or-self::svg:*";
const "clones", "$descend[self::svg:use]";
- const "reals", "$descend[not(self::svg:use)]";
const "originals", "//svg:*[concat('#',@id) = $clones/@xlink:href]";
- func:result select="$reals | func:refered_elements($originals)";
+ result "$descend | func:refered_elements($originals)"; - func:result select="$reals";
+ // return included geometry a given element + def "func:included_geometry" { + const "g", "$geometry[@Id = $elt/@id]"; + result """$geometry[@Id != $elt/@id and + @x >= $g/@x and @y >= $g/@y and + @x+@w <= $g/@x+$g/@w and @y+@h <= $g/@y+$g/@h]"""; + def "func:sumarized_elements" { + const "short_list", "$elements[not(ancestor::*/@id = $elements/@id)]"; + /* TODO exclude globally discardable elements from group fulfillment check */ + const "filled_groups", "$short_list/parent::svg:*[not(descendant::*[not(self::svg:g)][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:all_related_elements" { + const "page_included_geometry", "func:included_geometry($page)"; + const "page_sub_elements", "func:refered_elements($page)"; + const "page_included_elements", "//svg:*[@id = $page_included_geometry/@Id]"; + result "$page_sub_elements | $page_included_elements"; @@ -324,17 +359,20 @@
const "desc", "func:parselabel(@inkscape:label)/widget";
- const "p", "$hmi_geometry[@Id = $page/@id]";
- const "page_ids","""$hmi_geometry[@Id != $page/@id and
- @x >= $p/@x and @y >= $p/@y and
- @x+@w <= $p/@x+$p/@w and @y+@h <= $p/@y+$p/@h]/@Id""";
- const "page_sub_ids", "func:refered_elements($page)[@id = $hmi_elements/@id]/@id";
- const "all_page_ids","$page_ids | $page_sub_ids[not(. = $page_ids)]";
+ const "p", "$geometry[@Id = $page/@id]"; + const "page_all_elements", "func:all_related_elements($page)"; + const "all_page_ids","$page_all_elements[@id = $hmi_elements/@id and @id != $page/@id]/@id"; + const "shorter_list", "func:sumarized_elements($page_all_elements)"; | "«$desc/arg[1]/@value»": {
| widget: hmi_widgets["«@id»"],
| bbox: [«$p/@x», «$p/@y», «$p/@w», «$p/@h»],
@@ -343,6 +381,11 @@
| hmi_widgets["«.»"]`if "position()!=last()" > ,`
+ foreach "$shorter_list" { | }`if "position()!=last()" > ,`
--- a/svghmi/svghmi.js Fri Feb 21 16:22:44 2020 +0100
+++ b/svghmi/svghmi.js Thu Feb 27 13:14:24 2020 +0100
@@ -217,33 +217,50 @@
+function prepare_svg() { + /* set everybody hidden initially for better performance */ + for(let widget in hmi_widgets){ + if(widget.element != undefined) + widget.element.style.display = "none"; + /*for(let name in page_desc){ + page_desc[name].widget.element.style.display = "none"; function switch_page(page_name) {
let old_desc = page_desc[current_page];
let new_desc = page_desc[page_name];
if(new_desc == undefined){
- /* remove subsribers of previous page if any */
for(let widget of old_desc.widgets){
+ if(widget.element != undefined) + widget.element.style.display = "none"; + /* remove subsribers */ for(let index of widget.indexes){
subscribers[index].delete(widget);
old_desc.widget.element.style.display = "none";
- /* initial page switch : set everybody hidden */
- for(let name in page_desc){
- page_desc[name].widget.element.style.display = "none";
- /* add new subsribers if any */
for(let widget of new_desc.widgets){
+ if(widget.element != undefined) + widget.element.style.display = "inline"; + /* add widget's subsribers */ for(let index of widget.indexes){
subscribers[index].add(widget);
/* dispatch current cache in newly opened page widgets */
@@ -267,6 +284,7 @@
switch_page(default_page);