beremiz

Parents ac08a5d15c15
Children 50b9832c51fc
SVGHMI: created widget_*.ysl2. Renamed widget_common in widgets_common, so that it doesn't match globing.
--- a/svghmi/gen_index_xhtml.xslt Tue Mar 17 14:11:54 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Wed Mar 18 09:16:14 2020 +0100
@@ -624,6 +624,230 @@
</xsl:choose>
</xsl:for-each>
</xsl:template>
+ <func:function name="func:escape_quotes">
+ <xsl:param name="txt"/>
+ <xsl:variable name="frst" select="substring-before($txt,'&quot;')"/>
+ <xsl:variable name="frstln" select="string-length($frst)"/>
+ <xsl:choose>
+ <xsl:when test="$frstln &gt; 0 and string-length($txt) &gt; $frstln">
+ <func:result select="concat($frst,'\&quot;',func:escape_quotes(substring-after($txt,'&quot;')))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <func:result select="$txt"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </func:function>
+ <xsl:template mode="widget_defs" match="widget[@type='Display']">
+ <xsl:param name="hmi_element"/>
+ <xsl:text> frequency: 5,
+</xsl:text>
+ <xsl:text> dispatch: function(value) {
+</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$hmi_element[self::svg:text]">
+ <xsl:text> this.element.textContent = String(value);
+</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="no">
+ <xsl:text>Display widget as a group not implemented</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> },
+</xsl:text>
+ </xsl:template>
+ <xsl:template mode="widget_defs" match="widget[@type='Input']">
+ <xsl:param name="hmi_element"/>
+ <xsl:variable name="value_elt">
+ <xsl:call-template name="defs_by_labels">
+ <xsl:with-param name="hmi_element" select="$hmi_element"/>
+ <xsl:with-param name="labels">
+ <xsl:text>value</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="mandatory" select="'no'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="have_value" select="string-length($value_elt)&gt;0"/>
+ <xsl:value-of select="$value_elt"/>
+ <xsl:if test="$have_value">
+ <xsl:text> frequency: 5,
+</xsl:text>
+ </xsl:if>
+ <xsl:text> dispatch: function(value) {
+</xsl:text>
+ <xsl:if test="$have_value">
+ <xsl:text> this.value_elt.textContent = String(value);
+</xsl:text>
+ </xsl:if>
+ <xsl:text> },
+</xsl:text>
+ <xsl:variable name="edit_elt_id" select="$hmi_element/*[@inkscape:label='edit'][1]/@id"/>
+ <xsl:text> init: function() {
+</xsl:text>
+ <xsl:if test="$edit_elt_id">
+ <xsl:text> id("</xsl:text>
+ <xsl:value-of select="$edit_elt_id"/>
+ <xsl:text>").addEventListener(
+</xsl:text>
+ <xsl:text> "click",
+</xsl:text>
+ <xsl:text> evt =&gt; alert('XXX TODO : Edit value'));
+</xsl:text>
+ </xsl:if>
+ <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]">
+ <xsl:text> id("</xsl:text>
+ <xsl:value-of select="@id"/>
+ <xsl:text>").addEventListener(
+</xsl:text>
+ <xsl:text> "click",
+</xsl:text>
+ <xsl:text> evt =&gt; {let new_val = change_hmi_value(this.indexes[0], "</xsl:text>
+ <xsl:value-of select="func:escape_quotes(@inkscape:label)"/>
+ <xsl:text>");
+</xsl:text>
+ <xsl:if test="$have_value">
+ <xsl:text> this.value_elt.textContent = String(new_val);
+</xsl:text>
+ </xsl:if>
+ <xsl:text> });
+</xsl:text>
+ </xsl:for-each>
+ <xsl:text> },
+</xsl:text>
+ </xsl:template>
+ <xsl:template mode="widget_defs" match="widget[@type='Jump']">
+ <xsl:param name="hmi_element"/>
+ <xsl:text> on_click: function(evt) {
+</xsl:text>
+ <xsl:text> switch_page(this.args[0], this.indexes[0]);
+</xsl:text>
+ <xsl:text> },
+</xsl:text>
+ <xsl:text> init: function() {
+</xsl:text>
+ <xsl:text> this.element.setAttribute("onclick", "hmi_widgets['</xsl:text>
+ <xsl:value-of select="$hmi_element/@id"/>
+ <xsl:text>'].on_click(evt)");
+</xsl:text>
+ <xsl:text> },
+</xsl:text>
+ </xsl:template>
+ <xsl:template mode="widget_defs" match="widget[@type='Meter']">
+ <xsl:param name="hmi_element"/>
+ <xsl:text> frequency: 10,
+</xsl:text>
+ <xsl:call-template name="defs_by_labels">
+ <xsl:with-param name="hmi_element" select="$hmi_element"/>
+ <xsl:with-param name="labels">
+ <xsl:text>needle range</xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:call-template name="defs_by_labels">
+ <xsl:with-param name="hmi_element" select="$hmi_element"/>
+ <xsl:with-param name="labels">
+ <xsl:text>value min max</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="mandatory" select="'no'"/>
+ </xsl:call-template>
+ <xsl:text> dispatch: function(value) {
+</xsl:text>
+ <xsl:text> if(this.value_elt)
+</xsl:text>
+ <xsl:text> this.value_elt.textContent = String(value);
+</xsl:text>
+ <xsl:text> let [min,max,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.needle_elt.setAttribute('d', "M "+this.origin.x+","+this.origin.y+" "+tip.x+","+tip.y);
+</xsl:text>
+ <xsl:text> },
+</xsl:text>
+ <xsl:text> origin: undefined,
+</xsl:text>
+ <xsl:text> range: undefined,
+</xsl:text>
+ <xsl:text> init: function() {
+</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 &gt;= 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 &gt;= 2 ? this.args[1] : 100;
+</xsl:text>
+ <xsl:text> this.range = [min, max, this.range_elt.getTotalLength()]
+</xsl:text>
+ <xsl:text> this.origin = this.needle_elt.getPointAtLength(0);
+</xsl:text>
+ <xsl:text> },
+</xsl:text>
+ </xsl:template>
+ <xsl:template mode="widget_defs" match="widget[@type='Switch']">
+ <xsl:param name="hmi_element"/>
+ <xsl:text> frequency: 5,
+</xsl:text>
+ <xsl:text> dispatch: function(value) {
+</xsl:text>
+ <xsl:text> for(let choice of this.choices){
+</xsl:text>
+ <xsl:text> if(value != choice.value){
+</xsl:text>
+ <xsl:text> choice.elt.setAttribute("style", "display:none");
+</xsl:text>
+ <xsl:text> } else {
+</xsl:text>
+ <xsl:text> choice.elt.setAttribute("style", choice.style);
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> },
+</xsl:text>
+ <xsl:text> init: function() {
+</xsl:text>
+ <xsl:text> // Hello Switch
+</xsl:text>
+ <xsl:text> },
+</xsl:text>
+ <xsl:text> choices: [
+</xsl:text>
+ <xsl:variable name="regex" select="'^(&quot;[^&quot;].*&quot;|\-?[0-9]+)(#.*)?$'"/>
+ <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label,$regex)]">
+ <xsl:variable name="literal" select="regexp:match(@inkscape:label,$regex)[2]"/>
+ <xsl:text> {
+</xsl:text>
+ <xsl:text> elt:id("</xsl:text>
+ <xsl:value-of select="@id"/>
+ <xsl:text>"),
+</xsl:text>
+ <xsl:text> style:"</xsl:text>
+ <xsl:value-of select="@style"/>
+ <xsl:text>",
+</xsl:text>
+ <xsl:text> value:</xsl:text>
+ <xsl:value-of select="$literal"/>
+ <xsl:text>
+</xsl:text>
+ <xsl:text> }</xsl:text>
+ <xsl:if test="position()!=last()">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ <xsl:text>
+</xsl:text>
+ </xsl:for-each>
+ <xsl:text> ],
+</xsl:text>
+ </xsl:template>
<xsl:template match="/">
<xsl:comment>
<xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
@@ -675,8 +899,6 @@
</html>
</xsl:template>
<xsl:template name="scripts">
- <xsl:text>//(function(){
-</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>id = idstr =&gt; document.getElementById(idstr);
@@ -1535,236 +1757,5 @@
</xsl:text>
<xsl:text>};
</xsl:text>
- <xsl:text>//})();
-</xsl:text>
- </xsl:template>
- <xsl:template mode="widget_defs" match="widget[@type='Display']">
- <xsl:param name="hmi_element"/>
- <xsl:text> frequency: 5,
-</xsl:text>
- <xsl:text> dispatch: function(value) {
-</xsl:text>
- <xsl:choose>
- <xsl:when test="$hmi_element[self::svg:text]">
- <xsl:text> this.element.textContent = String(value);
-</xsl:text>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="no">
- <xsl:text>Display widget as a group not implemented</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- <xsl:text> },
-</xsl:text>
- </xsl:template>
- <xsl:template mode="widget_defs" match="widget[@type='Meter']">
- <xsl:param name="hmi_element"/>
- <xsl:text> frequency: 10,
-</xsl:text>
- <xsl:call-template name="defs_by_labels">
- <xsl:with-param name="hmi_element" select="$hmi_element"/>
- <xsl:with-param name="labels">
- <xsl:text>needle range</xsl:text>
- </xsl:with-param>
- </xsl:call-template>
- <xsl:call-template name="defs_by_labels">
- <xsl:with-param name="hmi_element" select="$hmi_element"/>
- <xsl:with-param name="labels">
- <xsl:text>value min max</xsl:text>
- </xsl:with-param>
- <xsl:with-param name="mandatory" select="'no'"/>
- </xsl:call-template>
- <xsl:text> dispatch: function(value) {
-</xsl:text>
- <xsl:text> if(this.value_elt)
-</xsl:text>
- <xsl:text> this.value_elt.textContent = String(value);
-</xsl:text>
- <xsl:text> let [min,max,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.needle_elt.setAttribute('d', "M "+this.origin.x+","+this.origin.y+" "+tip.x+","+tip.y);
-</xsl:text>
- <xsl:text> },
-</xsl:text>
- <xsl:text> origin: undefined,
-</xsl:text>
- <xsl:text> range: undefined,
-</xsl:text>
- <xsl:text> init: function() {
-</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 &gt;= 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 &gt;= 2 ? this.args[1] : 100;
-</xsl:text>
- <xsl:text> this.range = [min, max, this.range_elt.getTotalLength()]
-</xsl:text>
- <xsl:text> this.origin = this.needle_elt.getPointAtLength(0);
-</xsl:text>
- <xsl:text> },
-</xsl:text>
- </xsl:template>
- <func:function name="func:escape_quotes">
- <xsl:param name="txt"/>
- <xsl:variable name="frst" select="substring-before($txt,'&quot;')"/>
- <xsl:variable name="frstln" select="string-length($frst)"/>
- <xsl:choose>
- <xsl:when test="$frstln &gt; 0 and string-length($txt) &gt; $frstln">
- <func:result select="concat($frst,'\&quot;',func:escape_quotes(substring-after($txt,'&quot;')))"/>
- </xsl:when>
- <xsl:otherwise>
- <func:result select="$txt"/>
- </xsl:otherwise>
- </xsl:choose>
- </func:function>
- <xsl:template mode="widget_defs" match="widget[@type='Input']">
- <xsl:param name="hmi_element"/>
- <xsl:variable name="value_elt">
- <xsl:call-template name="defs_by_labels">
- <xsl:with-param name="hmi_element" select="$hmi_element"/>
- <xsl:with-param name="labels">
- <xsl:text>value</xsl:text>
- </xsl:with-param>
- <xsl:with-param name="mandatory" select="'no'"/>
- </xsl:call-template>
- </xsl:variable>
- <xsl:variable name="have_value" select="string-length($value_elt)&gt;0"/>
- <xsl:value-of select="$value_elt"/>
- <xsl:if test="$have_value">
- <xsl:text> frequency: 5,
-</xsl:text>
- </xsl:if>
- <xsl:text> dispatch: function(value) {
-</xsl:text>
- <xsl:if test="$have_value">
- <xsl:text> this.value_elt.textContent = String(value);
-</xsl:text>
- </xsl:if>
- <xsl:text> },
-</xsl:text>
- <xsl:variable name="edit_elt_id" select="$hmi_element/*[@inkscape:label='edit'][1]/@id"/>
- <xsl:text> init: function() {
-</xsl:text>
- <xsl:if test="$edit_elt_id">
- <xsl:text> id("</xsl:text>
- <xsl:value-of select="$edit_elt_id"/>
- <xsl:text>").addEventListener(
-</xsl:text>
- <xsl:text> "click",
-</xsl:text>
- <xsl:text> evt =&gt; alert('XXX TODO : Edit value'));
-</xsl:text>
- </xsl:if>
- <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]">
- <xsl:text> id("</xsl:text>
- <xsl:value-of select="@id"/>
- <xsl:text>").addEventListener(
-</xsl:text>
- <xsl:text> "click",
-</xsl:text>
- <xsl:text> evt =&gt; {let new_val = change_hmi_value(this.indexes[0], "</xsl:text>
- <xsl:value-of select="func:escape_quotes(@inkscape:label)"/>
- <xsl:text>");
-</xsl:text>
- <xsl:if test="$have_value">
- <xsl:text> this.value_elt.textContent = String(new_val);
-</xsl:text>
- </xsl:if>
- <xsl:text> });
-</xsl:text>
- </xsl:for-each>
- <xsl:text> },
-</xsl:text>
- </xsl:template>
- <xsl:template mode="widget_defs" match="widget[@type='Button']"/>
- <xsl:template mode="widget_defs" match="widget[@type='Toggle']">
- <xsl:text> frequency: 5,
-</xsl:text>
- </xsl:template>
- <xsl:template mode="widget_defs" match="widget[@type='Switch']">
- <xsl:param name="hmi_element"/>
- <xsl:text> frequency: 5,
-</xsl:text>
- <xsl:text> dispatch: function(value) {
-</xsl:text>
- <xsl:text> for(let choice of this.choices){
-</xsl:text>
- <xsl:text> if(value != choice.value){
-</xsl:text>
- <xsl:text> choice.elt.setAttribute("style", "display:none");
-</xsl:text>
- <xsl:text> } else {
-</xsl:text>
- <xsl:text> choice.elt.setAttribute("style", choice.style);
-</xsl:text>
- <xsl:text> }
-</xsl:text>
- <xsl:text> }
-</xsl:text>
- <xsl:text> },
-</xsl:text>
- <xsl:text> init: function() {
-</xsl:text>
- <xsl:text> // Hello Switch
-</xsl:text>
- <xsl:text> },
-</xsl:text>
- <xsl:text> choices: [
-</xsl:text>
- <xsl:variable name="regex" select="'^(&quot;[^&quot;].*&quot;|\-?[0-9]+)(#.*)?$'"/>
- <xsl:for-each select="$hmi_element/*[regexp:test(@inkscape:label,$regex)]">
- <xsl:variable name="literal" select="regexp:match(@inkscape:label,$regex)[2]"/>
- <xsl:text> {
-</xsl:text>
- <xsl:text> elt:id("</xsl:text>
- <xsl:value-of select="@id"/>
- <xsl:text>"),
-</xsl:text>
- <xsl:text> style:"</xsl:text>
- <xsl:value-of select="@style"/>
- <xsl:text>",
-</xsl:text>
- <xsl:text> value:</xsl:text>
- <xsl:value-of select="$literal"/>
- <xsl:text>
-</xsl:text>
- <xsl:text> }</xsl:text>
- <xsl:if test="position()!=last()">
- <xsl:text>,</xsl:text>
- </xsl:if>
- <xsl:text>
-</xsl:text>
- </xsl:for-each>
- <xsl:text> ],
-</xsl:text>
- </xsl:template>
- <xsl:template mode="widget_defs" match="widget[@type='Jump']">
- <xsl:param name="hmi_element"/>
- <xsl:text> on_click: function(evt) {
-</xsl:text>
- <xsl:text> switch_page(this.args[0], this.indexes[0]);
-</xsl:text>
- <xsl:text> },
-</xsl:text>
- <xsl:text> init: function() {
-</xsl:text>
- <xsl:text> this.element.setAttribute("onclick", "hmi_widgets['</xsl:text>
- <xsl:value-of select="$hmi_element/@id"/>
- <xsl:text>'].on_click(evt)");
-</xsl:text>
- <xsl:text> },
-</xsl:text>
</xsl:template>
</xsl:stylesheet>
--- a/svghmi/gen_index_xhtml.ysl2 Tue Mar 17 14:11:54 2020 +0100
+++ b/svghmi/gen_index_xhtml.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -60,7 +60,9 @@
include inline_svg.ysl2
- include widget_common.ysl2
+ include widgets_common.ysl2
+
+ include widget_*.ysl2
template "/" {
comment > Made with SVGHMI. https://beremiz.org
@@ -73,6 +75,7 @@
xmlns:xlink="http://www.w3.org/1999/xlink" {
head;
body style="margin:0;overflow:hidden;" {
+ // Inline SVG
copy "$result_svg";
script{
call "scripts";
@@ -83,30 +86,11 @@
function "scripts"
{
- | //(function(){
|
| id = idstr => document.getElementById(idstr);
|
| var hmi_hash = [«$hmitree/@hash»];
- /* TODO re-enable
- ||
- function evaluate_js_from_descriptions() {
- var Page;
- var Input;
- var Display;
- var res = [];
- ||
- const "midmark" > \n«$mark»
- apply """//*[contains(child::svg:desc, $midmark) or \
- starts-with(child::svg:desc, $mark)]""",2
- mode="code_from_descs";
- ||
- return res;
- }
- ||
- */
-
| var hmi_widgets = {
apply "$hmi_elements", mode="hmi_elements";
| }
@@ -137,177 +121,5 @@
| var default_page = "«$default_page»";
| var svg_root = id("«/svg:svg/@id»");
include text svghmi.js
- | //})();
- }
-
- // template "*", mode="code_from_descs" {
- // ||
- // {
- // var path, role, name, priv;
- // var id = "«@id»";
- // ||
-
- // /* if label is used, use it as default name */
- // if "@inkscape:label"
- // |> name = "«@inkscape:label»";
-
- // | /* -------------- */
-
- // // this breaks indent, but fixing indent could break string literals
- // value "substring-after(svg:desc, $mark)";
- // // nobody reads generated code anyhow...
-
- // ||
-
- // /* -------------- */
- // res.push({
- // path:path,
- // role:role,
- // name:name,
- // priv:priv
- // })
- // }
- // ||
- // }
-
-
- template "widget[@type='Display']", mode="widget_defs" {
- param "hmi_element";
- | frequency: 5,
- | dispatch: function(value) {
- choose {
- when "$hmi_element[self::svg:text]"{
- // TODO : care about <tspan> ?
- | this.element.textContent = String(value);
- }
- otherwise {
- warning > Display widget as a group not implemented
- }
- }
- | },
-
- }
- template "widget[@type='Meter']", mode="widget_defs" {
- param "hmi_element";
- | frequency: 10,
- labels("needle range");
- optional_labels("value min max");
- | dispatch: function(value) {
- | if(this.value_elt)
- | this.value_elt.textContent = String(value);
- | let [min,max,totallength] = this.range;
- | let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
- | let tip = this.range_elt.getPointAtLength(length);
- | this.needle_elt.setAttribute('d', "M "+this.origin.x+","+this.origin.y+" "+tip.x+","+tip.y);
- | },
- | origin: undefined,
- | range: undefined,
- | init: function() {
- | let min = this.min_elt ?
- | Number(this.min_elt.textContent) :
- | this.args.length >= 1 ? this.args[0] : 0;
- | let max = this.max_elt ?
- | Number(this.max_elt.textContent) :
- | this.args.length >= 2 ? this.args[1] : 100;
- | this.range = [min, max, this.range_elt.getTotalLength()]
- | this.origin = this.needle_elt.getPointAtLength(0);
- | },
- }
-
- def "func:escape_quotes" {
- param "txt";
- // have to use a python string to enter escaped quote
- const "frst", !"substring-before($txt,'\"')"!;
- const "frstln", "string-length($frst)";
- choose {
- when "$frstln > 0 and string-length($txt) > $frstln" {
- result !"concat($frst,'\\\"',func:escape_quotes(substring-after($txt,'\"')))"!;
- }
- otherwise {
- result "$txt";
- }
- }
- }
-
- template "widget[@type='Input']", mode="widget_defs" {
- param "hmi_element";
- const "value_elt" {
- optional_labels("value");
- }
- const "have_value","string-length($value_elt)>0";
- value "$value_elt";
- if "$have_value"
- | frequency: 5,
-
- | dispatch: function(value) {
-
- if "$have_value"
- | this.value_elt.textContent = String(value);
-
- | },
- const "edit_elt_id","$hmi_element/*[@inkscape:label='edit'][1]/@id";
- | init: function() {
- if "$edit_elt_id" {
- | id("«$edit_elt_id»").addEventListener(
- | "click",
- | evt => alert('XXX TODO : Edit value'));
- }
- foreach "$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]" {
- | id("«@id»").addEventListener(
- | "click",
- | evt => {let new_val = change_hmi_value(this.indexes[0], "«func:escape_quotes(@inkscape:label)»");
- if "$have_value"{
- | this.value_elt.textContent = String(new_val);
- }
- | });
- /* TODO gray out value until refreshed */
- }
- | },
- }
- template "widget[@type='Button']", mode="widget_defs" {
- }
- template "widget[@type='Toggle']", mode="widget_defs" {
- | frequency: 5,
- }
- template "widget[@type='Switch']", mode="widget_defs" {
- param "hmi_element";
- | frequency: 5,
- | dispatch: function(value) {
- | for(let choice of this.choices){
- | if(value != choice.value){
- | choice.elt.setAttribute("style", "display:none");
- | } else {
- | choice.elt.setAttribute("style", choice.style);
- | }
- | }
- | },
- | init: function() {
- | // Hello Switch
- | },
- | choices: [
- const "regex",!"'^(\"[^\"].*\"|\-?[0-9]+)(#.*)?$'"!;
- foreach "$hmi_element/*[regexp:test(@inkscape:label,$regex)]" {
- const "literal", "regexp:match(@inkscape:label,$regex)[2]";
- | {
- | elt:id("«@id»"),
- | style:"«@style»",
- | value:«$literal»
- | }`if "position()!=last()" > ,`
- }
- | ],
- }
- template "widget[@type='Jump']", mode="widget_defs" {
- param "hmi_element";
- | on_click: function(evt) {
- | switch_page(this.args[0], this.indexes[0]);
- | },
- | init: function() {
- /* registering event this way doies not "click" through svg:use
- | this.element.onclick = evt => switch_page(this.args[0]);
- event must be registered by adding attribute to element instead
- TODO : generalize mouse event handling by global event capture + getElementsAtPoint()
- */
- | this.element.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_click(evt)");
- | },
}
}
--- a/svghmi/widget_common.ysl2 Tue Mar 17 14:11:54 2020 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-in xsl decl labels(*ptr, name="defs_by_labels") alias call-template {
- with "hmi_element", "$hmi_element";
- with "labels"{text *ptr};
-};
-
-in xsl decl optional_labels(*ptr, name="defs_by_labels") alias call-template {
- with "hmi_element", "$hmi_element";
- with "labels"{text *ptr};
- with "mandatory","'no'";
-};
-
-template "svg:*", mode="hmi_elements" {
- const "widget", "func:parselabel(@inkscape:label)/widget";
- const "eltid","@id";
- | "«@id»": {
- | type: "«$widget/@type»",
- | args: [
- foreach "$widget/arg"
- | "«@value»"`if "position()!=last()" > ,`
- | ],
- | indexes: [
- foreach "$widget/path" {
- choose {
- when "not(@index)" {
- warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«@value»" in HMI tree
- }
- otherwise {
- | «@index»`if "position()!=last()" > ,`
- }
- }
- }
- | ],
- | element: id("«@id»"),
- apply "$widget", mode="widget_defs" with "hmi_element",".";
- | }`if "position()!=last()" > ,`
-}
-
-
-function "defs_by_labels" {
- param "labels","''";
- param "mandatory","'yes'";
- param "hmi_element";
- const "widget_type","@type";
- foreach "str:split($labels)" {
- const "name",".";
- const "elt_id","$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]/@id";
- choose {
- when "not($elt_id)" {
- if "$mandatory='yes'" {
- // TODO FIXME error > «$widget_type» widget must have a «$name» element
- warning > «$widget_type» widget must have a «$name» element
- }
- // otherwise produce nothing
- }
- otherwise {
- | «$name»_elt: id("«$elt_id»"),
- }
- }
- }
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_custom.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,60 @@
+// widget_custom.ysl2
+//
+// widget entierely defined from JS code in Inkscape description field
+
+// TODO
+
+// a preliminary implementation was initially attempted but disabled
+// code collected around before code refactoring
+
+
+
+ /* TODO re-enable
+ ||
+ function evaluate_js_from_descriptions() {
+ var Page;
+ var Input;
+ var Display;
+ var res = [];
+ ||
+ const "midmark" > \n«$mark»
+ apply """//*[contains(child::svg:desc, $midmark) or \
+ starts-with(child::svg:desc, $mark)]""",2
+ mode="code_from_descs";
+ ||
+ return res;
+ }
+ ||
+ */
+
+ // template "*", mode="code_from_descs" {
+ // ||
+ // {
+ // var path, role, name, priv;
+ // var id = "«@id»";
+ // ||
+
+ // /* if label is used, use it as default name */
+ // if "@inkscape:label"
+ // |> name = "«@inkscape:label»";
+
+ // | /* -------------- */
+
+ // // this breaks indent, but fixing indent could break string literals
+ // value "substring-after(svg:desc, $mark)";
+ // // nobody reads generated code anyhow...
+
+ // ||
+
+ // /* -------------- */
+ // res.push({
+ // path:path,
+ // role:role,
+ // name:name,
+ // priv:priv
+ // })
+ // }
+ // ||
+ // }
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_display.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,19 @@
+// widget_display.ysl2
+
+
+template "widget[@type='Display']", mode="widget_defs" {
+ param "hmi_element";
+ | frequency: 5,
+ | dispatch: function(value) {
+ choose {
+ when "$hmi_element[self::svg:text]"{
+ // TODO : care about <tspan> ?
+ | this.element.textContent = String(value);
+ }
+ otherwise {
+ warning > Display widget as a group not implemented
+ }
+ }
+ | },
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_input.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,37 @@
+// widget_input.ysl2
+
+template "widget[@type='Input']", mode="widget_defs" {
+ param "hmi_element";
+ const "value_elt" {
+ optional_labels("value");
+ }
+ const "have_value","string-length($value_elt)>0";
+ value "$value_elt";
+ if "$have_value"
+ | frequency: 5,
+
+ | dispatch: function(value) {
+
+ if "$have_value"
+ | this.value_elt.textContent = String(value);
+
+ | },
+ const "edit_elt_id","$hmi_element/*[@inkscape:label='edit'][1]/@id";
+ | init: function() {
+ if "$edit_elt_id" {
+ | id("«$edit_elt_id»").addEventListener(
+ | "click",
+ | evt => alert('XXX TODO : Edit value'));
+ }
+ foreach "$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]" {
+ | id("«@id»").addEventListener(
+ | "click",
+ | evt => {let new_val = change_hmi_value(this.indexes[0], "«func:escape_quotes(@inkscape:label)»");
+ if "$have_value"{
+ | this.value_elt.textContent = String(new_val);
+ }
+ | });
+ /* TODO gray out value until refreshed */
+ }
+ | },
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_jump.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,16 @@
+// widget_jump.ysl2
+
+template "widget[@type='Jump']", mode="widget_defs" {
+ param "hmi_element";
+ | on_click: function(evt) {
+ | switch_page(this.args[0], this.indexes[0]);
+ | },
+ | init: function() {
+ /* registering event this way doies not "click" through svg:use
+ | this.element.onclick = evt => switch_page(this.args[0]);
+ event must be registered by adding attribute to element instead
+ TODO : generalize mouse event handling by global event capture + getElementsAtPoint()
+ */
+ | this.element.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_click(evt)");
+ | },
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_meter.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,31 @@
+// widget_meter.ysl2
+
+
+template "widget[@type='Meter']", mode="widget_defs" {
+ param "hmi_element";
+ | frequency: 10,
+ labels("needle range");
+ optional_labels("value min max");
+ | dispatch: function(value) {
+ | if(this.value_elt)
+ | this.value_elt.textContent = String(value);
+ | let [min,max,totallength] = this.range;
+ | let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
+ | let tip = this.range_elt.getPointAtLength(length);
+ | this.needle_elt.setAttribute('d', "M "+this.origin.x+","+this.origin.y+" "+tip.x+","+tip.y);
+ | },
+ | origin: undefined,
+ | range: undefined,
+ | init: function() {
+ | let min = this.min_elt ?
+ | Number(this.min_elt.textContent) :
+ | this.args.length >= 1 ? this.args[0] : 0;
+ | let max = this.max_elt ?
+ | Number(this.max_elt.textContent) :
+ | this.args.length >= 2 ? this.args[1] : 100;
+ | this.range = [min, max, this.range_elt.getTotalLength()]
+ | this.origin = this.needle_elt.getPointAtLength(0);
+ | },
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widget_switch.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,29 @@
+// widget_switch.ysl2
+
+template "widget[@type='Switch']", mode="widget_defs" {
+ param "hmi_element";
+ | frequency: 5,
+ | dispatch: function(value) {
+ | for(let choice of this.choices){
+ | if(value != choice.value){
+ | choice.elt.setAttribute("style", "display:none");
+ | } else {
+ | choice.elt.setAttribute("style", choice.style);
+ | }
+ | }
+ | },
+ | init: function() {
+ | // Hello Switch
+ | },
+ | choices: [
+ const "regex",!"'^(\"[^\"].*\"|\-?[0-9]+)(#.*)?$'"!;
+ foreach "$hmi_element/*[regexp:test(@inkscape:label,$regex)]" {
+ const "literal", "regexp:match(@inkscape:label,$regex)[2]";
+ | {
+ | elt:id("«@id»"),
+ | style:"«@style»",
+ | value:«$literal»
+ | }`if "position()!=last()" > ,`
+ }
+ | ],
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/widgets_common.ysl2 Wed Mar 18 09:16:14 2020 +0100
@@ -0,0 +1,76 @@
+in xsl decl labels(*ptr, name="defs_by_labels") alias call-template {
+ with "hmi_element", "$hmi_element";
+ with "labels"{text *ptr};
+};
+
+in xsl decl optional_labels(*ptr, name="defs_by_labels") alias call-template {
+ with "hmi_element", "$hmi_element";
+ with "labels"{text *ptr};
+ with "mandatory","'no'";
+};
+
+template "svg:*", mode="hmi_elements" {
+ const "widget", "func:parselabel(@inkscape:label)/widget";
+ const "eltid","@id";
+ | "«@id»": {
+ | type: "«$widget/@type»",
+ | args: [
+ foreach "$widget/arg"
+ | "«@value»"`if "position()!=last()" > ,`
+ | ],
+ | indexes: [
+ foreach "$widget/path" {
+ choose {
+ when "not(@index)" {
+ warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«@value»" in HMI tree
+ }
+ otherwise {
+ | «@index»`if "position()!=last()" > ,`
+ }
+ }
+ }
+ | ],
+ | element: id("«@id»"),
+ apply "$widget", mode="widget_defs" with "hmi_element",".";
+ | }`if "position()!=last()" > ,`
+}
+
+
+function "defs_by_labels" {
+ param "labels","''";
+ param "mandatory","'yes'";
+ param "hmi_element";
+ const "widget_type","@type";
+ foreach "str:split($labels)" {
+ const "name",".";
+ const "elt_id","$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]/@id";
+ choose {
+ when "not($elt_id)" {
+ if "$mandatory='yes'" {
+ // TODO FIXME error > «$widget_type» widget must have a «$name» element
+ warning > «$widget_type» widget must have a «$name» element
+ }
+ // otherwise produce nothing
+ }
+ otherwise {
+ | «$name»_elt: id("«$elt_id»"),
+ }
+ }
+ }
+}
+
+def "func:escape_quotes" {
+ param "txt";
+ // have to use a python string to enter escaped quote
+ const "frst", !"substring-before($txt,'\"')"!;
+ const "frstln", "string-length($frst)";
+ choose {
+ when "$frstln > 0 and string-length($txt) > $frstln" {
+ result !"concat($frst,'\\\"',func:escape_quotes(substring-after($txt,'\"')))"!;
+ }
+ otherwise {
+ result "$txt";
+ }
+ }
+}
+