svghmi/gen_index_xhtml.ysl2
branchsvghmi
changeset 2883 8e3d130399b0
parent 2882 ac08a5d15c15
child 2904 92d115d8828d
equal deleted inserted replaced
2882:ac08a5d15c15 2883:8e3d130399b0
    58 
    58 
    59     include detachable_pages.ysl2
    59     include detachable_pages.ysl2
    60 
    60 
    61     include inline_svg.ysl2
    61     include inline_svg.ysl2
    62 
    62 
    63     include widget_common.ysl2
    63     include widgets_common.ysl2
       
    64 
       
    65     include widget_*.ysl2
    64 
    66 
    65     template "/" {
    67     template "/" {
    66         comment > Made with SVGHMI. https://beremiz.org
    68         comment > Made with SVGHMI. https://beremiz.org
    67 
    69 
    68         // use python to call all debug output from included definitions
    70         // use python to call all debug output from included definitions
    71         html xmlns="http://www.w3.org/1999/xhtml"
    73         html xmlns="http://www.w3.org/1999/xhtml"
    72              xmlns:svg="http://www.w3.org/2000/svg"
    74              xmlns:svg="http://www.w3.org/2000/svg"
    73              xmlns:xlink="http://www.w3.org/1999/xlink" {
    75              xmlns:xlink="http://www.w3.org/1999/xlink" {
    74             head;
    76             head;
    75             body style="margin:0;overflow:hidden;" {
    77             body style="margin:0;overflow:hidden;" {
       
    78                 // Inline SVG
    76                 copy "$result_svg";
    79                 copy "$result_svg";
    77                 script{
    80                 script{
    78                     call "scripts";
    81                     call "scripts";
    79                 }
    82                 }
    80             }
    83             }
    81         }
    84         }
    82     }
    85     }
    83 
    86 
    84     function "scripts"
    87     function "scripts"
    85     {
    88     {
    86         | //(function(){
       
    87         |
    89         |
    88         | id = idstr => document.getElementById(idstr);
    90         | id = idstr => document.getElementById(idstr);
    89         |
    91         |
    90         | var hmi_hash = [«$hmitree/@hash»]; 
    92         | var hmi_hash = [«$hmitree/@hash»]; 
    91 
       
    92         /* TODO re-enable
       
    93         ||
       
    94         function evaluate_js_from_descriptions() {
       
    95             var Page;
       
    96             var Input;
       
    97             var Display;
       
    98             var res = [];
       
    99         ||
       
   100         const "midmark" > \n«$mark»
       
   101         apply """//*[contains(child::svg:desc, $midmark) or \
       
   102                      starts-with(child::svg:desc, $mark)]""",2 
       
   103               mode="code_from_descs";
       
   104         ||
       
   105             return res;
       
   106         }
       
   107         ||
       
   108         */
       
   109 
    93 
   110         | var hmi_widgets = {
    94         | var hmi_widgets = {
   111         apply "$hmi_elements", mode="hmi_elements";
    95         apply "$hmi_elements", mode="hmi_elements";
   112         | }
    96         | }
   113         |
    97         |
   135 
   119 
   136         |
   120         |
   137         | var default_page = "«$default_page»";
   121         | var default_page = "«$default_page»";
   138         | var svg_root = id("«/svg:svg/@id»");
   122         | var svg_root = id("«/svg:svg/@id»");
   139         include text svghmi.js
   123         include text svghmi.js
   140         | //})();
       
   141     }
       
   142 
       
   143     // template "*", mode="code_from_descs" {
       
   144     //     ||
       
   145     //     {
       
   146     //         var path, role, name, priv;
       
   147     //         var id = "«@id»";
       
   148     //     ||
       
   149 
       
   150     //     /* if label is used, use it as default name */
       
   151     //     if "@inkscape:label"
       
   152     //         |> name = "«@inkscape:label»";
       
   153 
       
   154     //     | /* -------------- */
       
   155 
       
   156     //     // this breaks indent, but fixing indent could break string literals
       
   157     //     value "substring-after(svg:desc, $mark)";
       
   158     //     // nobody reads generated code anyhow...
       
   159 
       
   160     //     ||
       
   161 
       
   162     //         /* -------------- */
       
   163     //         res.push({
       
   164     //             path:path,
       
   165     //             role:role,
       
   166     //             name:name,
       
   167     //             priv:priv
       
   168     //         })
       
   169     //     }
       
   170     //     ||
       
   171     // }
       
   172 
       
   173 
       
   174     template "widget[@type='Display']", mode="widget_defs" {
       
   175         param "hmi_element";
       
   176         |     frequency: 5,
       
   177         |     dispatch: function(value) {
       
   178         choose {
       
   179             when "$hmi_element[self::svg:text]"{
       
   180             // TODO : care about <tspan> ?
       
   181         |       this.element.textContent = String(value);
       
   182             }
       
   183             otherwise {
       
   184                 warning > Display widget as a group not implemented
       
   185             }
       
   186         }
       
   187         |     },
       
   188 
       
   189     }
       
   190     template "widget[@type='Meter']", mode="widget_defs" {
       
   191         param "hmi_element";
       
   192         |     frequency: 10,
       
   193         labels("needle range");
       
   194         optional_labels("value min max");
       
   195         |     dispatch: function(value) {
       
   196         |         if(this.value_elt)
       
   197         |             this.value_elt.textContent = String(value);
       
   198         |         let [min,max,totallength] = this.range;
       
   199         |         let length = Math.max(0,Math.min(totallength,(Number(value)-min)*totallength/(max-min)));
       
   200         |         let tip = this.range_elt.getPointAtLength(length);
       
   201         |         this.needle_elt.setAttribute('d', "M "+this.origin.x+","+this.origin.y+" "+tip.x+","+tip.y);
       
   202         |     },
       
   203         |     origin: undefined,
       
   204         |     range: undefined,
       
   205         |     init: function() {
       
   206         |         let min = this.min_elt ?
       
   207         |                     Number(this.min_elt.textContent) :
       
   208         |                     this.args.length >= 1 ? this.args[0] : 0;
       
   209         |         let max = this.max_elt ?
       
   210         |                     Number(this.max_elt.textContent) :
       
   211         |                     this.args.length >= 2 ? this.args[1] : 100;
       
   212         |         this.range = [min, max, this.range_elt.getTotalLength()]
       
   213         |         this.origin = this.needle_elt.getPointAtLength(0);
       
   214         |     },
       
   215     }
       
   216 
       
   217     def "func:escape_quotes" {
       
   218         param "txt";
       
   219         // have to use a python string to enter escaped quote
       
   220         const "frst", !"substring-before($txt,'\"')"!;
       
   221         const "frstln", "string-length($frst)";
       
   222         choose {
       
   223             when "$frstln > 0 and string-length($txt) > $frstln" {
       
   224                 result !"concat($frst,'\\\"',func:escape_quotes(substring-after($txt,'\"')))"!;
       
   225             }
       
   226             otherwise {
       
   227                 result "$txt";
       
   228             }
       
   229         }
       
   230     }
       
   231 
       
   232     template "widget[@type='Input']", mode="widget_defs" {
       
   233         param "hmi_element";
       
   234         const "value_elt" {
       
   235             optional_labels("value");
       
   236         }
       
   237         const "have_value","string-length($value_elt)>0";
       
   238         value "$value_elt";
       
   239         if "$have_value"
       
   240         |     frequency: 5,
       
   241 
       
   242         |     dispatch: function(value) {
       
   243 
       
   244         if "$have_value"
       
   245         |         this.value_elt.textContent = String(value);
       
   246 
       
   247         |     },
       
   248         const "edit_elt_id","$hmi_element/*[@inkscape:label='edit'][1]/@id";
       
   249         |     init: function() {
       
   250         if "$edit_elt_id" {
       
   251         |         id("«$edit_elt_id»").addEventListener(
       
   252         |             "click", 
       
   253         |             evt => alert('XXX TODO : Edit value'));
       
   254         }
       
   255         foreach "$hmi_element/*[regexp:test(@inkscape:label,'^[=+\-].+')]" {
       
   256         |         id("«@id»").addEventListener(
       
   257         |             "click", 
       
   258         |             evt => {let new_val = change_hmi_value(this.indexes[0], "«func:escape_quotes(@inkscape:label)»");
       
   259             if "$have_value"{
       
   260         |                     this.value_elt.textContent = String(new_val);
       
   261             }
       
   262         |                    });
       
   263                               /* TODO gray out value until refreshed */
       
   264         }
       
   265         |     },
       
   266     }
       
   267     template "widget[@type='Button']", mode="widget_defs" {
       
   268     }
       
   269     template "widget[@type='Toggle']", mode="widget_defs" {
       
   270         |     frequency: 5,
       
   271     }
       
   272     template "widget[@type='Switch']", mode="widget_defs" {
       
   273         param "hmi_element";
       
   274         |     frequency: 5,
       
   275         |     dispatch: function(value) {
       
   276         |         for(let choice of this.choices){
       
   277         |             if(value != choice.value){
       
   278         |                 choice.elt.setAttribute("style", "display:none");
       
   279         |             } else {
       
   280         |                 choice.elt.setAttribute("style", choice.style);
       
   281         |             }
       
   282         |         }
       
   283         |     },
       
   284         |     init: function() {
       
   285         |         // Hello Switch
       
   286         |     },
       
   287         |     choices: [
       
   288         const "regex",!"'^(\"[^\"].*\"|\-?[0-9]+)(#.*)?$'"!;
       
   289         foreach "$hmi_element/*[regexp:test(@inkscape:label,$regex)]" {
       
   290             const "literal", "regexp:match(@inkscape:label,$regex)[2]";
       
   291         |         {
       
   292         |             elt:id("«@id»"),
       
   293         |             style:"«@style»",
       
   294         |             value:«$literal»
       
   295         |         }`if "position()!=last()" > ,`
       
   296         }
       
   297         |     ],
       
   298     }
       
   299     template "widget[@type='Jump']", mode="widget_defs" {
       
   300         param "hmi_element";
       
   301         |     on_click: function(evt) {
       
   302         |         switch_page(this.args[0], this.indexes[0]);
       
   303         |     },
       
   304         |     init: function() {
       
   305         /* registering event this way doies not "click" through svg:use 
       
   306         |     this.element.onclick = evt => switch_page(this.args[0]);
       
   307         event must be registered by adding attribute to element instead
       
   308         TODO : generalize mouse event handling by global event capture + getElementsAtPoint()
       
   309         */
       
   310         |         this.element.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_click(evt)");
       
   311         |     },
       
   312     }
   124     }
   313 }
   125 }