SVGHMI: Make Back widget activable. (#52)
--- a/exemples/svghmi_jumps/svghmi_0@svghmi/svghmi.svg Wed Dec 11 09:30:07 2024 +0100
+++ b/exemples/svghmi_jumps/svghmi_0@svghmi/svghmi.svg Wed Dec 11 09:31:35 2024 +0100
@@ -2,21 +2,21 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="svghmi.svg"
id="hmi0"
version="1.1"
viewBox="0 0 1280 720"
height="720"
- width="1280">
+ width="1280"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata8">
<rdf:RDF>
@@ -40,24 +40,27 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:window-width="1850"
- inkscape:window-height="1036"
+ inkscape:window-width="1854"
+ inkscape:window-height="1011"
id="namedview4"
showgrid="false"
- inkscape:zoom="0.46354778"
- inkscape:cx="-544.27948"
- inkscape:cy="655.56978"
+ inkscape:zoom="1.04375"
+ inkscape:cx="626.58683"
+ inkscape:cy="1233.5329"
inkscape:window-x="0"
- inkscape:window-y="27"
+ inkscape:window-y="0"
inkscape:window-maximized="1"
- inkscape:current-layer="g2496"
+ inkscape:current-layer="g845"
showguides="true"
inkscape:guide-bbox="true"
borderlayer="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
- fit-margin-bottom="0" />
+ fit-margin-bottom="0"
+ inkscape:showpageshadow="2"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1" />
<use
sodipodi:insensitive="true"
x="0"
@@ -133,14 +136,25 @@
id="g845"
transform="translate(0,660.00004)">
<rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.77952766;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect839"
- width="244.72002"
- height="70.089722"
- x="517.64001"
- y="324.95514"
- ry="21.355932"
- rx="21.355932" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:5.07063;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ id="rect851-6-36-7"
+ width="214.92937"
+ height="74.929367"
+ x="532.53534"
+ y="320.53528"
+ ry="12.800982"
+ rx="18.525251"
+ inkscape:label="active" />
+ <rect
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffa32a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.84883;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ id="rect851-6-36"
+ width="220"
+ height="80"
+ x="530"
+ y="317.99997"
+ ry="13.667253"
+ rx="18.962297"
+ inkscape:label="inactive" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
--- a/svghmi/analyse_widget.xslt Wed Dec 11 09:30:07 2024 +0100
+++ b/svghmi/analyse_widget.xslt Wed Dec 11 09:31:35 2024 +0100
@@ -288,6 +288,12 @@
<longdesc>
<xsl:text>Back widget brings focus back to previous page in history when clicked.
</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text>"active" + "inactive" labeled elements can be provided and reflect whether
+</xsl:text>
+ <xsl:text>widget is pressed or not.
+</xsl:text>
</longdesc>
<shortdesc>
<xsl:text>Jump to previous page</xsl:text>
@@ -545,6 +551,15 @@
<path name="root" accepts="HMI_NODE">
<xsl:text> where to find HMI_NODEs whose HMI_CLASS is class_name</xsl:text>
</path>
+ <path name="position" accepts="HMI_INT">
+ <xsl:text>position of HMI_NODE mapped to first item, among similar siblings</xsl:text>
+ </path>
+ <path name="range" accepts="HMI_INT" count="optional">
+ <xsl:text> count of HMI_NODE siblings</xsl:text>
+ </path>
+ <path name="size" accepts="HMI_INT" count="optional">
+ <xsl:text> count of visible items</xsl:text>
+ </path>
</xsl:template>
<xsl:template match="widget[@type='Image']" mode="widget_desc">
<type>
@@ -627,7 +642,7 @@
</xsl:text>
<xsl:text>
</xsl:text>
- <xsl:text>If first path is pointint to HMI_NODE variable is used as new reference
+ <xsl:text>If first path is pointing to HMI_NODE variable is used as new reference
</xsl:text>
<xsl:text>when jumping to a relative page.
</xsl:text>
--- a/svghmi/gen_index_xhtml.xslt Wed Dec 11 09:30:07 2024 +0100
+++ b/svghmi/gen_index_xhtml.xslt Wed Dec 11 09:31:35 2024 +0100
@@ -2740,6 +2740,12 @@
<longdesc>
<xsl:text>Back widget brings focus back to previous page in history when clicked.
</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text>"active" + "inactive" labeled elements can be provided and reflect whether
+</xsl:text>
+ <xsl:text>widget is pressed or not.
+</xsl:text>
</longdesc>
<shortdesc>
<xsl:text>Jump to previous page</xsl:text>
@@ -2750,37 +2756,96 @@
<xsl:text>BackWidget</xsl:text>
<xsl:text> extends Widget{
</xsl:text>
- <xsl:text> on_click(evt) {
-</xsl:text>
- <xsl:text> if(jump_history.length > 1){
-</xsl:text>
- <xsl:text> let page_name, index;
+ <xsl:text> onmouseup(evt) {
+</xsl:text>
+ <xsl:text> svg_root.removeEventListener("pointerup", this.bound_onmouseup, true);
+</xsl:text>
+ <xsl:text> this.activity_state = false;
+</xsl:text>
+ <xsl:text> this.request_animate();
+</xsl:text>
+ <xsl:text> let page_name, index;
+</xsl:text>
+ <xsl:text> if (jump_history.length > 1) {
</xsl:text>
<xsl:text> do {
</xsl:text>
<xsl:text> jump_history.pop(); // forget current page
</xsl:text>
- <xsl:text> if(jump_history.length == 0) return;
+ <xsl:text> if (jump_history.length == 0) return;
</xsl:text>
<xsl:text> [page_name, index] = jump_history[jump_history.length-1];
</xsl:text>
- <xsl:text> } while(page_name == "ScreenSaver") // never go back to ScreenSaver
-</xsl:text>
- <xsl:text> switch_page(page_name, index);
+ <xsl:text> } while (page_name == "ScreenSaver") // never go back to ScreenSaver
+</xsl:text>
+ <xsl:text> fading_page_switch(page_name, index);
</xsl:text>
<xsl:text> }
</xsl:text>
<xsl:text> }
</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text> onmousedown(){
+</xsl:text>
+ <xsl:text> svg_root.addEventListener("pointerup", this.bound_onmouseup, true);
+</xsl:text>
+ <xsl:text> this.activity_state = true;
+</xsl:text>
+ <xsl:text> this.request_animate();
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text>
+</xsl:text>
<xsl:text> init() {
</xsl:text>
- <xsl:text> this.element.onclick = this.on_click.bind(this);
+ <xsl:text> this.bound_onmouseup = this.onmouseup.bind(this);
+</xsl:text>
+ <xsl:text> this.activity_state = false;
+</xsl:text>
+ <xsl:text> this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
</xsl:text>
<xsl:text> }
</xsl:text>
<xsl:text>}
</xsl:text>
</xsl:template>
+ <xsl:template match="widget[@type='Back']" mode="widget_defs">
+ <xsl:param name="hmi_element"/>
+ <xsl:variable name="disability">
+ <xsl:call-template name="defs_by_labels">
+ <xsl:with-param name="hmi_element" select="$hmi_element"/>
+ <xsl:with-param name="labels">
+ <xsl:text>/disabled</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="mandatory" select="'no'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$disability"/>
+ <xsl:variable name="has_disability" select="string-length($disability)>0"/>
+ <xsl:text> activable_sub:{
+</xsl:text>
+ <xsl:variable name="activity">
+ <xsl:call-template name="defs_by_labels">
+ <xsl:with-param name="hmi_element" select="$hmi_element"/>
+ <xsl:with-param name="labels">
+ <xsl:text>/active /inactive</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="mandatory">
+ <xsl:text>warn</xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$activity"/>
+ <xsl:variable name="has_activity" select="string-length($activity)>0"/>
+ <xsl:text> },
+</xsl:text>
+ <xsl:text> has_activity: </xsl:text>
+ <xsl:value-of select="$has_activity"/>
+ <xsl:text>,
+</xsl:text>
+ </xsl:template>
<xsl:template match="widget[@type='Button']" mode="widget_desc">
<type>
<xsl:value-of select="@type"/>
@@ -4454,6 +4519,15 @@
<path name="root" accepts="HMI_NODE">
<xsl:text> where to find HMI_NODEs whose HMI_CLASS is class_name</xsl:text>
</path>
+ <path name="position" accepts="HMI_INT">
+ <xsl:text>position of HMI_NODE mapped to first item, among similar siblings</xsl:text>
+ </path>
+ <path name="range" accepts="HMI_INT" count="optional">
+ <xsl:text> count of HMI_NODE siblings</xsl:text>
+ </path>
+ <path name="size" accepts="HMI_INT" count="optional">
+ <xsl:text> count of visible items</xsl:text>
+ </path>
</xsl:template>
<xsl:template match="widget[@type='ForEach']" mode="widget_defs">
<xsl:param name="hmi_element"/>
@@ -5606,7 +5680,7 @@
</xsl:text>
<xsl:text>
</xsl:text>
- <xsl:text>If first path is pointint to HMI_NODE variable is used as new reference
+ <xsl:text>If first path is pointing to HMI_NODE variable is used as new reference
</xsl:text>
<xsl:text>when jumping to a relative page.
</xsl:text>
@@ -5694,7 +5768,7 @@
</xsl:text>
<xsl:text> target_page_is_current_page = false;
</xsl:text>
- <xsl:text> button_beeing_pressed = false;
+ <xsl:text> button_being_pressed = false;
</xsl:text>
<xsl:text>
</xsl:text>
@@ -5710,9 +5784,9 @@
</xsl:text>
<xsl:text> this.indexes[0] + this.offset : undefined;
</xsl:text>
- <xsl:text> this.button_beeing_pressed = false;
-</xsl:text>
- <xsl:text> this.activity_state = this.target_page_is_current_page || this.button_beeing_pressed;
+ <xsl:text> this.button_being_pressed = false;
+</xsl:text>
+ <xsl:text> this.activity_state = this.target_page_is_current_page || this.button_being_pressed;
</xsl:text>
<xsl:text> fading_page_switch(this.args[0], index);
</xsl:text>
@@ -5730,7 +5804,7 @@
</xsl:text>
<xsl:text> svg_root.addEventListener("pointerup", this.bound_onmouseup, true);
</xsl:text>
- <xsl:text> this.button_beeing_pressed = true;
+ <xsl:text> this.button_being_pressed = true;
</xsl:text>
<xsl:text> this.activity_state = true;
</xsl:text>
@@ -5754,7 +5828,7 @@
</xsl:text>
<xsl:text> this.target_page_is_current_page = ((ref_name == undefined || ref_name == page_name) && index == ref_index);
</xsl:text>
- <xsl:text> this.activity_state = this.target_page_is_current_page || this.button_beeing_pressed;
+ <xsl:text> this.activity_state = this.target_page_is_current_page || this.button_being_pressed;
</xsl:text>
<xsl:text> // Since called from animate, update activity directly
</xsl:text>
--- a/svghmi/widget_back.ysl2 Wed Dec 11 09:30:07 2024 +0100
+++ b/svghmi/widget_back.ysl2 Wed Dec 11 09:31:35 2024 +0100
@@ -4,25 +4,45 @@
longdesc
||
Back widget brings focus back to previous page in history when clicked.
+
+ "active" + "inactive" labeled elements can be provided and reflect whether
+ widget is pressed or not.
||
shortdesc > Jump to previous page
}
-widget_class("Back")
- ||
- on_click(evt) {
- if(jump_history.length > 1){
- let page_name, index;
- do {
- jump_history.pop(); // forget current page
- if(jump_history.length == 0) return;
- [page_name, index] = jump_history[jump_history.length-1];
- } while(page_name == "ScreenSaver") // never go back to ScreenSaver
- switch_page(page_name, index);
- }
+widget_class("Back") {
+||
+ onmouseup(evt) {
+ svg_root.removeEventListener("pointerup", this.bound_onmouseup, true);
+ this.activity_state = false;
+ this.request_animate();
+ let page_name, index;
+ if (jump_history.length > 1) {
+ do {
+ jump_history.pop(); // forget current page
+ if (jump_history.length == 0) return;
+ [page_name, index] = jump_history[jump_history.length-1];
+ } while (page_name == "ScreenSaver") // never go back to ScreenSaver
+ fading_page_switch(page_name, index);
}
- init() {
- this.element.onclick = this.on_click.bind(this);
- }
- ||
+ }
+
+ onmousedown(){
+ svg_root.addEventListener("pointerup", this.bound_onmouseup, true);
+ this.activity_state = true;
+ this.request_animate();
+ }
+
+ init() {
+ this.bound_onmouseup = this.onmouseup.bind(this);
+ this.activity_state = false;
+ this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
+ }
+||
+}
+
+widget_defs("Back") {
+ activable();
+}
--- a/svghmi/widget_jump.ysl2 Wed Dec 11 09:30:07 2024 +0100
+++ b/svghmi/widget_jump.ysl2 Wed Dec 11 09:31:35 2024 +0100
@@ -6,7 +6,7 @@
Jump widget brings focus to a different page. Mandatory first argument
gives name of the page.
- If first path is pointint to HMI_NODE variable is used as new reference
+ If first path is pointing to HMI_NODE variable is used as new reference
when jumping to a relative page.
Additional arguments are unordered options:
@@ -53,7 +53,7 @@
activable = false;
frequency = 2;
target_page_is_current_page = false;
- button_beeing_pressed = false;
+ button_being_pressed = false;
onmouseup(evt) {
svg_root.removeEventListener("pointerup", this.bound_onmouseup, true);
@@ -61,8 +61,8 @@
const index =
(this.is_relative && this.indexes.length > 0) ?
this.indexes[0] + this.offset : undefined;
- this.button_beeing_pressed = false;
- this.activity_state = this.target_page_is_current_page || this.button_beeing_pressed;
+ this.button_being_pressed = false;
+ this.activity_state = this.target_page_is_current_page || this.button_being_pressed;
fading_page_switch(this.args[0], index);
this.notify();
}
@@ -71,7 +71,7 @@
onmousedown(){
if(this.enable_state) {
svg_root.addEventListener("pointerup", this.bound_onmouseup, true);
- this.button_beeing_pressed = true;
+ this.button_being_pressed = true;
this.activity_state = true;
this.request_animate();
}
@@ -83,7 +83,7 @@
const ref_index = this.indexes.length > 0 ? this.indexes[0] + this.offset : undefined;
const ref_name = this.args[0];
this.target_page_is_current_page = ((ref_name == undefined || ref_name == page_name) && index == ref_index);
- this.activity_state = this.target_page_is_current_page || this.button_beeing_pressed;
+ this.activity_state = this.target_page_is_current_page || this.button_being_pressed;
// Since called from animate, update activity directly
if(this.enable_displayed_state && this.has_activity) {
this.animate_activity();