# HG changeset patch # User Edouard Tisserant # Date 1597060735 -7200 # Node ID 497aac6522a3a6433382e137c2a13f96a11237e6 # Parent 22b969b409b033ab0f6862f865dcfd11f39edfcc SVGHMI: provide request_animate() to Widget authors so that they can register redraw code when events lead to redraw. Widget member animate() is called when it is time to update DOM. diff -r 22b969b409b0 -r 497aac6522a3 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Mon Aug 10 11:30:06 2020 +0200 +++ b/svghmi/gen_index_xhtml.xslt Mon Aug 10 13:58:55 2020 +0200 @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<xsl:stylesheet xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:definitions="definitions" xmlns:ns="beremiz" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:exsl="http://exslt.org/common" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:preamble="preamble" xmlns:func="http://exslt.org/functions" xmlns:epilogue="epilogue" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:str="http://exslt.org/strings" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:debug="debug" xmlns:svg="http://www.w3.org/2000/svg" xmlns:declarations="declarations" xmlns:cc="http://creativecommons.org/ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" version="1.0" extension-element-prefixes="ns func exsl regexp str dyn" exclude-result-prefixes="ns func exsl regexp str dyn debug preamble epilogue declarations definitions"> - <xsl:output cdata-section-elements="xhtml:script" method="xml"/> +<xsl:stylesheet xmlns:ns="beremiz" xmlns:definitions="definitions" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:func="http://exslt.org/functions" xmlns:epilogue="epilogue" xmlns:preamble="preamble" 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" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:str="http://exslt.org/strings" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:exsl="http://exslt.org/common" xmlns:declarations="declarations" xmlns:debug="debug" exclude-result-prefixes="ns func exsl regexp str dyn debug preamble epilogue declarations definitions" extension-element-prefixes="ns func exsl regexp str dyn" version="1.0"> + <xsl:output method="xml" cdata-section-elements="xhtml:script"/> <xsl:variable name="svg" select="/svg:svg"/> <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/> <xsl:variable name="hmitree" select="ns:GetHMITree()"/> @@ -14,7 +14,7 @@ </xsl:variable> <xsl:variable name="categories" select="exsl:node-set($_categories)"/> <xsl:variable name="_indexed_hmitree"> - <xsl:apply-templates select="$hmitree" mode="index"/> + <xsl:apply-templates mode="index" select="$hmitree"/> </xsl:variable> <xsl:variable name="indexed_hmitree" select="exsl:node-set($_indexed_hmitree)"/> <preamble:hmi-tree/> @@ -62,7 +62,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="*" mode="index"> + <xsl:template mode="index" match="*"> <xsl:param name="index" select="0"/> <xsl:param name="parentpath" select="''"/> <xsl:variable name="content"> @@ -95,7 +95,7 @@ <xsl:copy/> </xsl:for-each> </xsl:copy> - <xsl:apply-templates select="*[1]" mode="index"> + <xsl:apply-templates mode="index" select="*[1]"> <xsl:with-param name="index" select="$index + 1"/> <xsl:with-param name="parentpath"> <xsl:value-of select="$path"/> @@ -103,7 +103,7 @@ </xsl:apply-templates> </xsl:when> <xsl:otherwise> - <xsl:apply-templates select="*[1]" mode="index"> + <xsl:apply-templates mode="index" select="*[1]"> <xsl:with-param name="index" select="$index"/> <xsl:with-param name="parentpath"> <xsl:value-of select="$path"/> @@ -113,14 +113,14 @@ </xsl:choose> </xsl:variable> <xsl:copy-of select="$content"/> - <xsl:apply-templates select="following-sibling::*[1]" mode="index"> + <xsl:apply-templates mode="index" select="following-sibling::*[1]"> <xsl:with-param name="index" select="$index + count(exsl:node-set($content)/*)"/> <xsl:with-param name="parentpath"> <xsl:value-of select="$parentpath"/> </xsl:with-param> </xsl:apply-templates> </xsl:template> - <xsl:template match="*" mode="parselabel"> + <xsl:template mode="parselabel" match="*"> <xsl:variable name="label" select="@inkscape:label"/> <xsl:variable name="description" select="substring-after($label,'HMI:')"/> <xsl:variable name="_args" select="substring-before($description,'@')"/> @@ -184,7 +184,7 @@ </xsl:if> </xsl:template> <xsl:variable name="_parsed_widgets"> - <xsl:apply-templates select="$hmi_elements" mode="parselabel"/> + <xsl:apply-templates mode="parselabel" select="$hmi_elements"/> </xsl:variable> <xsl:variable name="parsed_widgets" select="exsl:node-set($_parsed_widgets)"/> <func:function name="func:widget"> @@ -203,7 +203,7 @@ <xsl:variable name="class_b" select="$indexed_hmitree/*[@hmipath = $b]/@class"/> <func:result select="$class_a and $class_b and $class_a = $class_b"/> </func:function> - <xsl:template match="*" mode="testtree"> + <xsl:template mode="testtree" match="*"> <xsl:param name="indent" select="''"/> <xsl:value-of select="$indent"/> <xsl:text> </xsl:text> @@ -217,7 +217,7 @@ </xsl:for-each> <xsl:text> </xsl:text> - <xsl:apply-templates select="*" mode="testtree"> + <xsl:apply-templates mode="testtree" select="*"> <xsl:with-param name="indent"> <xsl:value-of select="concat($indent,'>')"/> </xsl:with-param> @@ -235,18 +235,18 @@ </xsl:text> <xsl:text>Raw HMI tree </xsl:text> - <xsl:apply-templates select="$hmitree" mode="testtree"/> + <xsl:apply-templates mode="testtree" select="$hmitree"/> <xsl:text> </xsl:text> <xsl:text>Indexed HMI tree </xsl:text> - <xsl:apply-templates select="$indexed_hmitree" mode="testtree"/> + <xsl:apply-templates mode="testtree" select="$indexed_hmitree"/> <xsl:text> </xsl:text> <xsl:text>Parsed Widgets </xsl:text> <xsl:copy-of select="_parsed_widgets"/> - <xsl:apply-templates select="$parsed_widgets" mode="testtree"/> + <xsl:apply-templates mode="testtree" select="$parsed_widgets"/> <xsl:text> </xsl:text> </xsl:template> @@ -459,7 +459,7 @@ <xsl:variable name="forEach_widgets_ids" select="$parsed_widgets/widget[@type = 'ForEach']/@id"/> <xsl:variable name="forEach_widgets" select="$hmi_elements[@id = $forEach_widgets_ids]"/> <xsl:variable name="in_forEach_widget_ids" select="func:refered_elements($forEach_widgets)[not(@id = $forEach_widgets_ids)]/@id"/> - <xsl:template match="svg:*" mode="page_desc"> + <xsl:template mode="page_desc" match="svg:*"> <xsl:variable name="desc" select="func:widget(@id)"/> <xsl:variable name="page" select="."/> <xsl:variable name="p" select="$geometry[@Id = $page/@id]"/> @@ -559,7 +559,7 @@ </xsl:for-each> <xsl:text> } </xsl:text> - <xsl:apply-templates select="$parsed_widgets/widget[@id = $all_page_widgets/@id]" mode="per_page_widget_template"> + <xsl:apply-templates mode="per_page_widget_template" select="$parsed_widgets/widget[@id = $all_page_widgets/@id]"> <xsl:with-param name="page_desc" select="$desc"/> </xsl:apply-templates> <xsl:text> }</xsl:text> @@ -583,13 +583,13 @@ </xsl:text> <xsl:text>var page_desc = { </xsl:text> - <xsl:apply-templates select="$hmi_pages" mode="page_desc"/> + <xsl:apply-templates mode="page_desc" select="$hmi_pages"/> <xsl:text>} </xsl:text> <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="*" mode="per_page_widget_template"/> + <xsl:template mode="per_page_widget_template" match="*"/> <debug:detachable-pages/> <xsl:template match="debug:detachable-pages"> <xsl:text> @@ -621,16 +621,16 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="@* | node()" mode="inline_svg"> + <xsl:template mode="inline_svg" match="@* | node()"> <xsl:if test="not(@id = $discardable_elements/@id)"> <xsl:copy> - <xsl:apply-templates select="@* | node()" mode="inline_svg"/> + <xsl:apply-templates mode="inline_svg" select="@* | node()"/> </xsl:copy> </xsl:if> </xsl:template> - <xsl:template match="svg:svg/@width" mode="inline_svg"/> - <xsl:template match="svg:svg/@height" mode="inline_svg"/> - <xsl:template xmlns="http://www.w3.org/2000/svg" match="svg:svg" mode="inline_svg"> + <xsl:template mode="inline_svg" match="svg:svg/@width"/> + <xsl:template mode="inline_svg" match="svg:svg/@height"/> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:svg"> <svg> <xsl:attribute name="preserveAspectRatio"> <xsl:text>none</xsl:text> @@ -641,15 +641,15 @@ <xsl:attribute name="width"> <xsl:text>100vw</xsl:text> </xsl:attribute> - <xsl:apply-templates select="@* | node()" mode="inline_svg"/> + <xsl:apply-templates mode="inline_svg" select="@* | node()"/> </svg> </xsl:template> - <xsl:template match="svg:svg[@viewBox!=concat('0 0 ', @width, ' ', @height)]" mode="inline_svg"> + <xsl:template mode="inline_svg" match="svg:svg[@viewBox!=concat('0 0 ', @width, ' ', @height)]"> <xsl:message terminate="yes"> <xsl:text>ViewBox settings other than X=0, Y=0 and Scale=1 are not supported</xsl:text> </xsl:message> </xsl:template> - <xsl:template match="sodipodi:namedview[@units!='px' or @inkscape:document-units!='px']" mode="inline_svg"> + <xsl:template mode="inline_svg" match="sodipodi:namedview[@units!='px' or @inkscape:document-units!='px']"> <xsl:message terminate="yes"> <xsl:text>All units must be set to "px" in Inkscape's document properties</xsl:text> </xsl:message> @@ -658,7 +658,7 @@ <xsl:variable name="hmi_lists" select="$hmi_elements[@id = $hmi_lists_descs/@id]"/> <xsl:variable name="targets_not_to_unlink" select="$hmi_elements[@id = $hmi_lists/@id]/descendant::svg:*"/> <xsl:variable name="to_unlink" select="$hmi_elements[not(@id = $hmi_pages/@id)]/descendant-or-self::svg:use"/> - <xsl:template xmlns="http://www.w3.org/2000/svg" match="svg:use" mode="inline_svg"> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:use"> <xsl:variable name="targetid" select="substring-after(@xlink:href,'#')"/> <xsl:choose> <xsl:when test="@id = $to_unlink/@id and not($targetid = $targets_not_to_unlink/@id)"> @@ -668,7 +668,7 @@ </xsl:when> <xsl:otherwise> <xsl:copy> - <xsl:apply-templates select="@* | node()" mode="inline_svg"/> + <xsl:apply-templates mode="inline_svg" select="@* | node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> @@ -729,7 +729,7 @@ <xsl:value-of select="$target/@transform"/> </xsl:attribute> </xsl:if> - <xsl:apply-templates select="$target/*" mode="unlink_clone"> + <xsl:apply-templates mode="unlink_clone" select="$target/*"> <xsl:with-param name="seed" select="@id"/> </xsl:apply-templates> </xsl:when> @@ -739,14 +739,14 @@ <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> - <xsl:apply-templates select="$target" mode="unlink_clone"> + <xsl:apply-templates mode="unlink_clone" select="$target"> <xsl:with-param name="seed" select="@id"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </g> </xsl:template> - <xsl:template xmlns="http://www.w3.org/2000/svg" match="@id" mode="unlink_clone"> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@id"> <xsl:param name="seed"/> <xsl:attribute name="id"> <xsl:value-of select="$seed"/> @@ -754,10 +754,10 @@ <xsl:value-of select="."/> </xsl:attribute> </xsl:template> - <xsl:template xmlns="http://www.w3.org/2000/svg" match="@*" mode="unlink_clone"> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@*"> <xsl:copy/> </xsl:template> - <xsl:template xmlns="http://www.w3.org/2000/svg" match="svg:*" mode="unlink_clone"> + <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="svg:*"> <xsl:param name="seed"/> <xsl:choose> <xsl:when test="@id = $hmi_elements/@id"> @@ -769,7 +769,7 @@ </xsl:when> <xsl:otherwise> <xsl:copy> - <xsl:apply-templates select="@* | node()" mode="unlink_clone"> + <xsl:apply-templates mode="unlink_clone" select="@* | node()"> <xsl:with-param name="seed" select="$seed"/> </xsl:apply-templates> </xsl:copy> @@ -777,7 +777,7 @@ </xsl:choose> </xsl:template> <xsl:variable name="result_svg"> - <xsl:apply-templates select="/" mode="inline_svg"/> + <xsl:apply-templates mode="inline_svg" select="/"/> </xsl:variable> <xsl:variable name="result_svg_ns" select="exsl:node-set($result_svg)"/> <preamble:inline-svg/> @@ -828,7 +828,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="svg:*" mode="hmi_widgets"> + <xsl:template mode="hmi_widgets" match="svg:*"> <xsl:variable name="widget" select="func:widget(@id)"/> <xsl:variable name="eltid" select="@id"/> <xsl:variable name="args"> @@ -876,7 +876,7 @@ <xsl:value-of select="$indexes"/> <xsl:text>],{ </xsl:text> - <xsl:apply-templates select="$widget" mode="widget_defs"> + <xsl:apply-templates mode="widget_defs" select="$widget"> <xsl:with-param name="hmi_element" select="."/> </xsl:apply-templates> <xsl:text> })</xsl:text> @@ -915,6 +915,10 @@ </xsl:text> <xsl:text> </xsl:text> + <xsl:text>var pending_widget_animates = []; +</xsl:text> + <xsl:text> +</xsl:text> <xsl:text>class Widget { </xsl:text> <xsl:text> offset = 0; @@ -923,6 +927,10 @@ </xsl:text> <xsl:text> unsubscribable = false; </xsl:text> + <xsl:text> pending_animate = false; +</xsl:text> + <xsl:text> +</xsl:text> <xsl:text> constructor(elt_id,args,indexes,members){ </xsl:text> <xsl:text> this.element_id = elt_id; @@ -1091,6 +1099,34 @@ </xsl:text> <xsl:text> } </xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> _animate(){ +</xsl:text> + <xsl:text> this.animate(); +</xsl:text> + <xsl:text> this.pending_animate = false; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> request_animate(){ +</xsl:text> + <xsl:text> if(!this.pending_animate){ +</xsl:text> + <xsl:text> pending_widget_animates.push(this); +</xsl:text> + <xsl:text> this.pending_animate = true; +</xsl:text> + <xsl:text> requestHMIAnimation(); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> } +</xsl:text> <xsl:text>} </xsl:text> <xsl:text> @@ -1107,11 +1143,11 @@ <xsl:text> </xsl:text> <xsl:variable name="used_widget_types" select="func:unique_types($parsed_widgets/widget)"/> - <xsl:apply-templates select="$used_widget_types" mode="widget_class"/> - <xsl:text> -</xsl:text> - </xsl:template> - <xsl:template match="widget" mode="widget_class"> + <xsl:apply-templates mode="widget_class" select="$used_widget_types"/> + <xsl:text> +</xsl:text> + </xsl:template> + <xsl:template mode="widget_class" match="widget"> <xsl:text>class </xsl:text> <xsl:value-of select="@type"/> <xsl:text>Widget extends Widget{ @@ -1137,7 +1173,7 @@ </xsl:text> <xsl:text>var hmi_widgets = { </xsl:text> - <xsl:apply-templates select="$hmi_elements[@id = $excluded_ids]" mode="hmi_widgets"/> + <xsl:apply-templates mode="hmi_widgets" select="$hmi_elements[@id = $excluded_ids]"/> <xsl:text>} </xsl:text> <xsl:text> @@ -1231,7 +1267,7 @@ </xsl:otherwise> </xsl:choose> </func:function> - <xsl:template match="widget[@type='Back']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='Back']"> <xsl:text>class BackWidget extends Widget{ </xsl:text> <xsl:text> on_click(evt) { @@ -1257,7 +1293,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Button']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='Button']"> <xsl:text>t{ </xsl:text> <xsl:text>5; @@ -1331,7 +1367,7 @@ <xsl:text>|| </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Button']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Button']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -1343,7 +1379,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="widget[@type='CircularBar']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='CircularBar']"> <xsl:param name="hmi_element"/> <xsl:text>frequency: 10, </xsl:text> @@ -1439,7 +1475,7 @@ <xsl:text>}, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='CircularSlider']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='CircularSlider']"> <xsl:text>class CircularSliderWidget extends Widget{ </xsl:text> <xsl:text> frequency = 5; @@ -1614,7 +1650,7 @@ </xsl:text> <xsl:text> this.value_elt.textContent = String(Math.ceil(svg_dist)); </xsl:text> - <xsl:text> change_hmi_value(this.indexes[0], "="+Math.ceil(svg_dist)); + <xsl:text> this.apply_hmi_value(0, Math.ceil(svg_dist)); </xsl:text> <xsl:text> </xsl:text> @@ -1735,7 +1771,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='CircularSlider']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='CircularSlider']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -1753,7 +1789,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Display']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='Display']"> <xsl:text>class DisplayWidget extends Widget{ </xsl:text> <xsl:text> frequency = 5; @@ -1771,7 +1807,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Display']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Display']"> <xsl:param name="hmi_element"/> <xsl:if test="$hmi_element[not(self::svg:text)]"> <xsl:message terminate="yes"> @@ -2262,7 +2298,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="widget[@type='DropDown']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='DropDown']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -2775,7 +2811,7 @@ <xsl:text> }, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='ForEach']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='ForEach']"> <xsl:param name="hmi_element"/> <xsl:if test="count(path) != 1"> <xsl:message terminate="yes"> @@ -2889,7 +2925,7 @@ <xsl:text> item_offset: 0, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='ForEach']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='ForEach']"> <xsl:text>class ForEachWidget extends Widget{ </xsl:text> <xsl:text> @@ -3025,7 +3061,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Input']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Input']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -3109,7 +3145,7 @@ <xsl:text> }, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='JsonTable']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='JsonTable']"> <xsl:text>class JsonTableWidget extends Widget{ </xsl:text> <xsl:text> do_http_request() { @@ -3169,14 +3205,14 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="svg:*" mode="json_table_elt_render"> + <xsl:template mode="json_table_elt_render" match="svg:*"> <xsl:message terminate="yes"> <xsl:text>JsonTable Widget can't contain element of type </xsl:text> <xsl:value-of select="local-name()"/> <xsl:text>.</xsl:text> </xsl:message> </xsl:template> - <xsl:template match="svg:use" mode="json_table_elt_render"> + <xsl:template mode="json_table_elt_render" match="svg:use"> <xsl:param name="value_expr"/> <xsl:variable name="targetid" select="substring-after(@xlink:href,'#')"/> <xsl:variable name="from_list" select="$hmi_lists[(@id | */@id) = $targetid]"/> @@ -3198,7 +3234,7 @@ <xsl:text>]); </xsl:text> </xsl:template> - <xsl:template match="svg:text" mode="json_table_elt_render"> + <xsl:template mode="json_table_elt_render" match="svg:text"> <xsl:param name="value_expr"/> <xsl:text> id("</xsl:text> <xsl:value-of select="@id"/> @@ -3207,16 +3243,16 @@ <xsl:text>); </xsl:text> </xsl:template> - <xsl:template match="svg:*" mode="json_table_render"> + <xsl:template mode="json_table_render" match="svg:*"> <xsl:param name="objname"/> - <xsl:apply-templates select="." mode="json_table_elt_render"> + <xsl:apply-templates mode="json_table_elt_render" select="."> <xsl:with-param name="value_expr"> <xsl:value-of select="$objname"/> <xsl:value-of select="@inkscape:label"/> </xsl:with-param> </xsl:apply-templates> </xsl:template> - <xsl:template match="svg:g" mode="json_table_render"> + <xsl:template mode="json_table_render" match="svg:g"> <xsl:param name="objname"/> <xsl:text> let obj_</xsl:text> <xsl:value-of select="@id"/> @@ -3225,14 +3261,14 @@ <xsl:value-of select="@inkscape:label"/> <xsl:text>; </xsl:text> - <xsl:apply-templates select="*[@inkscape:label]" mode="json_table_render"> + <xsl:apply-templates mode="json_table_render" select="*[@inkscape:label]"> <xsl:with-param name="objname"> <xsl:text>obj_</xsl:text> <xsl:value-of select="@id"/> </xsl:with-param> </xsl:apply-templates> </xsl:template> - <xsl:template match="widget[@type='JsonTable']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='JsonTable']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -3250,7 +3286,7 @@ <xsl:variable name="data_elt" select="$result_svg_ns//*[@id = $hmi_element/@id]/*[@inkscape:label = 'data']"/> <xsl:text> spread_json_data: function(jdata) { </xsl:text> - <xsl:apply-templates select="$data_elt/*" mode="json_table_render"> + <xsl:apply-templates mode="json_table_render" select="$data_elt/*"> <xsl:with-param name="objname" select="'jdata'"/> </xsl:apply-templates> <xsl:text> } @@ -3276,7 +3312,7 @@ <xsl:with-param name="mandatory" select="'no'"/> </xsl:call-template> </xsl:template> - <xsl:template match="widget[@type='Jump']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Jump']"> <xsl:param name="hmi_element"/> <xsl:variable name="activity"> <xsl:call-template name="jump_widget_activity"> @@ -3411,7 +3447,7 @@ <xsl:text> }, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Jump']" mode="per_page_widget_template"> + <xsl:template mode="per_page_widget_template" match="widget[@type='Jump']"> <xsl:param name="page_desc"/> <xsl:if test="path"> <xsl:variable name="target_page_name"> @@ -3513,7 +3549,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Keypad']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='Keypad']"> <xsl:text>class KeypadWidget extends Widget{ </xsl:text> <xsl:text> moving = undefined; @@ -3805,7 +3841,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Keypad']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Keypad']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -3884,7 +3920,7 @@ <xsl:text>], </xsl:text> </xsl:template> - <xsl:template match="widget[@type='List']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='List']"> <xsl:param name="hmi_element"/> <xsl:text> items: { </xsl:text> @@ -3899,7 +3935,7 @@ <xsl:text> }, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Meter']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Meter']"> <xsl:param name="hmi_element"/> <xsl:text> frequency: 10, </xsl:text> @@ -3957,7 +3993,7 @@ <xsl:text> }, </xsl:text> </xsl:template> - <xsl:template match="widget[@type='MultiState']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='MultiState']"> <xsl:text>class MultiStateWidget extends Widget{ </xsl:text> <xsl:text> frequency = 5; @@ -4024,7 +4060,7 @@ </xsl:text> <xsl:text> //post value to plc </xsl:text> - <xsl:text> change_hmi_value(this.indexes[0], "="+this.state); + <xsl:text> this.apply_hmi_value(0, this.state); </xsl:text> <xsl:text> } </xsl:text> @@ -4039,7 +4075,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='MultiState']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='MultiState']"> <xsl:param name="hmi_element"/> <xsl:text> choices: [ </xsl:text> @@ -4070,7 +4106,7 @@ <xsl:text> ], </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Slider']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='Slider']"> <xsl:text>class SliderWidget extends Widget{ </xsl:text> <xsl:text> frequency = 5; @@ -4083,19 +4119,43 @@ </xsl:text> <xsl:text> enTimer = false; </xsl:text> + <xsl:text> svg_dist = 0 +</xsl:text> <xsl:text> </xsl:text> <xsl:text> dispatch(value) { </xsl:text> - <xsl:text> if(!this.drag){ -</xsl:text> - <xsl:text> if(this.value_elt) -</xsl:text> - <xsl:text> this.value_elt.textContent = String(value); -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> this.handle_position(value); + <xsl:text> if(this.value_elt) +</xsl:text> + <xsl:text> this.value_elt.textContent = String(value); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> this.handle_position(value); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> handle_position(value){ +</xsl:text> + <xsl:text> let [min,max,start,totallength] = this.range; +</xsl:text> + <xsl:text> let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min))); +</xsl:text> + <xsl:text> let tip = this.range_elt.getPointAtLength(length); +</xsl:text> + <xsl:text> this.handle_elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")"); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> on_release(evt) { +</xsl:text> + <xsl:text> if(this.drag){ +</xsl:text> + <xsl:text> this.drag = false; </xsl:text> <xsl:text> } </xsl:text> @@ -4103,214 +4163,202 @@ </xsl:text> <xsl:text> </xsl:text> - <xsl:text> handle_position(value){ -</xsl:text> - <xsl:text> let [min,max,start,totallength] = this.range; -</xsl:text> - <xsl:text> let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min))); -</xsl:text> - <xsl:text> let tip = this.range_elt.getPointAtLength(length); -</xsl:text> - <xsl:text> this.handle_elt.setAttribute('transform',"translate("+(tip.x-start.x)+","+(tip.y-start.y)+")"); + <xsl:text> update_position(evt){ +</xsl:text> + <xsl:text> if(this.drag){ +</xsl:text> + <xsl:text> var html_dist = 0; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //calculate size of widget in html +</xsl:text> + <xsl:text> var range_borders = this.range_elt.getBoundingClientRect(); +</xsl:text> + <xsl:text> var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width ); +</xsl:text> + <xsl:text> var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top]; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //get range and mouse coordinates +</xsl:text> + <xsl:text> var mouseX = undefined; +</xsl:text> + <xsl:text> var mouseY = undefined; +</xsl:text> + <xsl:text> if (evt.type.startsWith("touch")){ +</xsl:text> + <xsl:text> mouseX = Math.ceil(evt.touches[0].clientX); +</xsl:text> + <xsl:text> mouseY = Math.ceil(evt.touches[0].clientY); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> mouseX = evt.pageX; +</xsl:text> + <xsl:text> mouseY = evt.pageY; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //get handle distance from mouse position +</xsl:text> + <xsl:text> if (minX > mouseX && minY < mouseY){ +</xsl:text> + <xsl:text> html_dist = 0; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if (maxX < mouseX && maxY > mouseY){ +</xsl:text> + <xsl:text> html_dist = range_length; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> // calculate distace +</xsl:text> + <xsl:text> if(this.fi > 0.7){ +</xsl:text> + <xsl:text> html_dist = (minY - mouseY)/Math.sin(this.fi); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else{ +</xsl:text> + <xsl:text> html_dist = (mouseX - minX)/Math.cos(this.fi); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //check if in range +</xsl:text> + <xsl:text> if (html_dist > range_length){ +</xsl:text> + <xsl:text> html_dist = range_length; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> else if (html_dist < 0){ +</xsl:text> + <xsl:text> html_dist = 0; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> this.svg_dist=(html_dist/range_length)*this.range[1]; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //redraw handle +</xsl:text> + <xsl:text> //this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]); +</xsl:text> + <xsl:text> //this.value_elt.textContent = String(Math.ceil(svg_dist)); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> if(this.enTimer){ +</xsl:text> + <xsl:text> this.apply_hmi_value(0, Math.ceil(this.svg_dist)); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> // TODO : update ghost cursor and call this.request_animate() +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> //reset timer +</xsl:text> + <xsl:text> this.enTimer = false; +</xsl:text> + <xsl:text> setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } </xsl:text> <xsl:text> } </xsl:text> <xsl:text> </xsl:text> - <xsl:text> on_release(evt) { -</xsl:text> - <xsl:text> if(this.drag){ -</xsl:text> - <xsl:text> this.drag = false; -</xsl:text> - <xsl:text> } + <xsl:text> on_select(evt){ +</xsl:text> + <xsl:text> this.drag = true; +</xsl:text> + <xsl:text> this.enTimer = true; +</xsl:text> + <xsl:text> this.update_position(evt); </xsl:text> <xsl:text> } </xsl:text> <xsl:text> </xsl:text> - <xsl:text> update_position(evt){ -</xsl:text> - <xsl:text> if(this.drag && this.enTimer){ -</xsl:text> - <xsl:text> var html_dist = 0; -</xsl:text> - <xsl:text> var svg_dist = 0; -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> //calculate size of widget in html -</xsl:text> - <xsl:text> var range_borders = this.range_elt.getBoundingClientRect(); -</xsl:text> - <xsl:text> var range_length = Math.sqrt( range_borders.height*range_borders.height + range_borders.width*range_borders.width ); -</xsl:text> - <xsl:text> var [minX,minY,maxX,maxY] = [range_borders.left,range_borders.bottom,range_borders.right,range_borders.top]; -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> //get range and mouse coordinates -</xsl:text> - <xsl:text> var mouseX = undefined; -</xsl:text> - <xsl:text> var mouseY = undefined; -</xsl:text> - <xsl:text> if (evt.type.startsWith("touch")){ -</xsl:text> - <xsl:text> mouseX = Math.ceil(evt.touches[0].clientX); -</xsl:text> - <xsl:text> mouseY = Math.ceil(evt.touches[0].clientY); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> else{ -</xsl:text> - <xsl:text> mouseX = evt.pageX; -</xsl:text> - <xsl:text> mouseY = evt.pageY; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> //get handle distance from mouse position -</xsl:text> - <xsl:text> if (minX > mouseX && minY < mouseY){ -</xsl:text> - <xsl:text> html_dist = 0; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> else if (maxX < mouseX && maxY > mouseY){ -</xsl:text> - <xsl:text> html_dist = range_length; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> else{ -</xsl:text> - <xsl:text> // calculate distace -</xsl:text> - <xsl:text> if(this.fi > 0.7){ -</xsl:text> - <xsl:text> html_dist = (minY - mouseY)/Math.sin(this.fi); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> else{ -</xsl:text> - <xsl:text> html_dist = (mouseX - minX)/Math.cos(this.fi); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> //check if in range -</xsl:text> - <xsl:text> if (html_dist > range_length){ -</xsl:text> - <xsl:text> html_dist = range_length; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> else if (html_dist < 0){ -</xsl:text> - <xsl:text> html_dist = 0; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> //redraw handle -</xsl:text> - <xsl:text> this.handle_position(svg_dist=(html_dist/range_length)*this.range[1]); -</xsl:text> - <xsl:text> this.value_elt.textContent = String(Math.ceil(svg_dist)); -</xsl:text> - <xsl:text> change_hmi_value(this.indexes[0], "="+Math.ceil(svg_dist)); -</xsl:text> - <xsl:text> //reset timer -</xsl:text> - <xsl:text> this.enTimer = false; -</xsl:text> - <xsl:text> setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); -</xsl:text> - <xsl:text> } + <xsl:text> init() { +</xsl:text> + <xsl:text> let min = this.min_elt ? +</xsl:text> + <xsl:text> Number(this.min_elt.textContent) : +</xsl:text> + <xsl:text> this.args.length >= 1 ? this.args[0] : 0; +</xsl:text> + <xsl:text> let max = this.max_elt ? +</xsl:text> + <xsl:text> Number(this.max_elt.textContent) : +</xsl:text> + <xsl:text> this.args.length >= 2 ? this.args[1] : 100; +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()]; +</xsl:text> + <xsl:text> let start = this.range_elt.getPointAtLength(0); +</xsl:text> + <xsl:text> let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength()); +</xsl:text> + <xsl:text> this.fi = Math.atan2(start.y-end.y, end.x-start.x); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> this.handle_elt.addEventListener("touchstart", hmi_widgets[this.element_id].on_select.bind(this)); +</xsl:text> + <xsl:text> this.handle_elt.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this)); +</xsl:text> + <xsl:text> this.element.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this)); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this)); +</xsl:text> + <xsl:text> window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this)); +</xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> window.addEventListener("mouseup", hmi_widgets[this.element_id].on_release.bind(this)) +</xsl:text> + <xsl:text> window.addEventListener("touchend", hmi_widgets[this.element_id].on_release.bind(this)); +</xsl:text> + <xsl:text> window.addEventListener("touchcancel", hmi_widgets[this.element_id].on_release.bind(this)); </xsl:text> <xsl:text> </xsl:text> <xsl:text> } </xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> on_select(evt){ -</xsl:text> - <xsl:text> this.drag = true; -</xsl:text> - <xsl:text> this.enTimer = true; -</xsl:text> - <xsl:text> this.update_position(evt); -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> init() { -</xsl:text> - <xsl:text> let min = this.min_elt ? -</xsl:text> - <xsl:text> Number(this.min_elt.textContent) : -</xsl:text> - <xsl:text> this.args.length >= 1 ? this.args[0] : 0; -</xsl:text> - <xsl:text> let max = this.max_elt ? -</xsl:text> - <xsl:text> Number(this.max_elt.textContent) : -</xsl:text> - <xsl:text> this.args.length >= 2 ? this.args[1] : 100; -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> this.range = [min, max, this.range_elt.getPointAtLength(0),this.range_elt.getTotalLength()]; -</xsl:text> - <xsl:text> let start = this.range_elt.getPointAtLength(0); -</xsl:text> - <xsl:text> let end = this.range_elt.getPointAtLength(this.range_elt.getTotalLength()); -</xsl:text> - <xsl:text> this.fi = Math.atan2(start.y-end.y, end.x-start.x); -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> this.handle_elt.addEventListener("touchstart", hmi_widgets[this.element_id].on_select.bind(this)); -</xsl:text> - <xsl:text> this.handle_elt.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this)); -</xsl:text> - <xsl:text> this.element.addEventListener("mousedown", hmi_widgets[this.element_id].on_select.bind(this)); -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> window.addEventListener("touchmove", hmi_widgets[this.element_id].update_position.bind(this)); -</xsl:text> - <xsl:text> window.addEventListener("mousemove", hmi_widgets[this.element_id].update_position.bind(this)); -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> window.addEventListener("mouseup", hmi_widgets[this.element_id].on_release.bind(this)) -</xsl:text> - <xsl:text> window.addEventListener("touchend", hmi_widgets[this.element_id].on_release.bind(this)); -</xsl:text> - <xsl:text> window.addEventListener("touchcancel", hmi_widgets[this.element_id].on_release.bind(this)); -</xsl:text> - <xsl:text> -</xsl:text> - <xsl:text> } -</xsl:text> <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Slider']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Slider']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -4328,7 +4376,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Switch']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='Switch']"> <xsl:text>class SwitchWidget extends Widget{ </xsl:text> <xsl:text> frequency = 5; @@ -4354,7 +4402,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='Switch']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='Switch']"> <xsl:param name="hmi_element"/> <xsl:text> choices: [ </xsl:text> @@ -4385,7 +4433,7 @@ <xsl:text> ], </xsl:text> </xsl:template> - <xsl:template match="widget[@type='ToggleButton']" mode="widget_class"> + <xsl:template mode="widget_class" match="widget[@type='ToggleButton']"> <xsl:text>class ToggleButtonWidget extends Widget{ </xsl:text> <xsl:text> frequency = 5; @@ -4426,7 +4474,7 @@ </xsl:text> <xsl:text> on_click(evt) { </xsl:text> - <xsl:text> change_hmi_value(this.indexes[0], "="+this.state); + <xsl:text> this.apply_hmi_value(0, this.state); </xsl:text> <xsl:text> } </xsl:text> @@ -4445,7 +4493,7 @@ <xsl:text>} </xsl:text> </xsl:template> - <xsl:template match="widget[@type='ToggleButton']" mode="widget_defs"> + <xsl:template mode="widget_defs" match="widget[@type='ToggleButton']"> <xsl:param name="hmi_element"/> <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> @@ -4656,6 +4704,14 @@ </xsl:text> <xsl:text> apply_updates(); </xsl:text> + <xsl:text> +</xsl:text> + <xsl:text> pending_widget_animates.forEach(widget => widget._animate()); +</xsl:text> + <xsl:text> pending_widget_animates = []; +</xsl:text> + <xsl:text> +</xsl:text> <xsl:text> requestAnimationFrameID = null; </xsl:text> <xsl:text>} @@ -5252,7 +5308,7 @@ </xsl:text> <xsl:text>var edit_callback; </xsl:text> - <xsl:text>function edit_value(path, valuetype, callback, initial,size) { + <xsl:text>function edit_value(path, valuetype, callback, initial, size) { </xsl:text> <xsl:text> </xsl:text> @@ -5264,7 +5320,7 @@ </xsl:text> <xsl:text> let widget = hmi_widgets[keypadid]; </xsl:text> - <xsl:text> widget.start_edit(path, valuetype, callback, initial,size); + <xsl:text> widget.start_edit(path, valuetype, callback, initial, size); </xsl:text> <xsl:text>}; </xsl:text> diff -r 22b969b409b0 -r 497aac6522a3 svghmi/svghmi.js --- a/svghmi/svghmi.js Mon Aug 10 11:30:06 2020 +0200 +++ b/svghmi/svghmi.js Mon Aug 10 13:58:55 2020 +0200 @@ -76,6 +76,10 @@ if(jumps_need_update) update_jumps(); apply_updates(); + + pending_widget_animates.forEach(widget => widget._animate()); + pending_widget_animates = []; + requestAnimationFrameID = null; } diff -r 22b969b409b0 -r 497aac6522a3 svghmi/widgets_common.ysl2 --- a/svghmi/widgets_common.ysl2 Mon Aug 10 11:30:06 2020 +0200 +++ b/svghmi/widgets_common.ysl2 Mon Aug 10 13:58:55 2020 +0200 @@ -64,10 +64,14 @@ emit "preamble:widget-base-class" { || + var pending_widget_animates = []; + class Widget { offset = 0; frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */ unsubscribable = false; + pending_animate = false; + constructor(elt_id,args,indexes,members){ this.element_id = elt_id; this.element = id(elt_id); @@ -152,6 +156,20 @@ console.log(err); } } + + _animate(){ + this.animate(); + this.pending_animate = false; + } + + request_animate(){ + if(!this.pending_animate){ + pending_widget_animates.push(this); + this.pending_animate = true; + requestHMIAnimation(); + } + + } } || }