svghmi/gen_index_xhtml.xslt
branchsvghmi
changeset 3022 f6fe42b7ce60
parent 3017 15e2df3e5610
child 3024 0a9f6f29b7dd
equal deleted inserted replaced
3017:15e2df3e5610 3022:f6fe42b7ce60
     1 <?xml version="1.0"?>
     1 <?xml version="1.0"?>
     2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:str="http://exslt.org/strings" xmlns:func="http://exslt.org/functions" 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: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:xhtml="http://www.w3.org/1999/xhtml" xmlns:debug="debug" xmlns:preamble="preamble" xmlns:declarations="declarations" xmlns:definitions="definitions" xmlns:epilogue="epilogue" xmlns:ns="beremiz" 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">
     2 <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">
     3   <xsl:output cdata-section-elements="xhtml:script" method="xml"/>
     3   <xsl:output method="xml" cdata-section-elements="xhtml:script"/>
     4   <xsl:variable name="svg" select="/svg:svg"/>
     4   <xsl:variable name="svg" select="/svg:svg"/>
     5   <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/>
     5   <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/>
     6   <xsl:variable name="hmitree" select="ns:GetHMITree()"/>
     6   <xsl:variable name="hmitree" select="ns:GetHMITree()"/>
     7   <xsl:variable name="_categories">
     7   <xsl:variable name="_categories">
     8     <noindex>
     8     <noindex>
   873                   <xsl:text>" in HMI tree</xsl:text>
   873                   <xsl:text>" in HMI tree</xsl:text>
   874                 </xsl:message>
   874                 </xsl:message>
   875               </xsl:when>
   875               </xsl:when>
   876               <xsl:when test="@type = 'PAGE_LOCAL'">
   876               <xsl:when test="@type = 'PAGE_LOCAL'">
   877                 <xsl:text>"</xsl:text>
   877                 <xsl:text>"</xsl:text>
   878                 <xsl:value-of select="substring(1,@value)"/>
   878                 <xsl:value-of select="substring(@value, 1)"/>
   879                 <xsl:text>"</xsl:text>
   879                 <xsl:text>"</xsl:text>
   880                 <xsl:if test="position()!=last()">
   880                 <xsl:if test="position()!=last()">
   881                   <xsl:text>,</xsl:text>
   881                   <xsl:text>,</xsl:text>
   882                 </xsl:if>
   882                 </xsl:if>
   883               </xsl:when>
   883               </xsl:when>
   957 </xsl:text>
   957 </xsl:text>
   958     <xsl:text>var next_available_index = hmitree_types.length;
   958     <xsl:text>var next_available_index = hmitree_types.length;
   959 </xsl:text>
   959 </xsl:text>
   960     <xsl:text>
   960     <xsl:text>
   961 </xsl:text>
   961 </xsl:text>
       
   962     <xsl:text>var cache = hmitree_types.map(_ignored =&gt; undefined);
       
   963 </xsl:text>
       
   964     <xsl:text>
       
   965 </xsl:text>
   962     <xsl:text>function page_local_index(varname, pagename){
   966     <xsl:text>function page_local_index(varname, pagename){
   963 </xsl:text>
   967 </xsl:text>
   964     <xsl:text>    let pagevars = hmi_locals[pagename];
   968     <xsl:text>    let pagevars = hmi_locals[pagename];
   965 </xsl:text>
   969 </xsl:text>
       
   970     <xsl:text>    let new_index;
       
   971 </xsl:text>
   966     <xsl:text>    if(pagevars == undefined){
   972     <xsl:text>    if(pagevars == undefined){
   967 </xsl:text>
   973 </xsl:text>
   968     <xsl:text>        let new_index = next_available_index++;
   974     <xsl:text>        new_index = next_available_index++;
   969 </xsl:text>
   975 </xsl:text>
   970     <xsl:text>        hmi_locals[pagename] = {varname:new_index}
   976     <xsl:text>        hmi_locals[pagename] = {[varname]:new_index}
   971 </xsl:text>
   977 </xsl:text>
   972     <xsl:text>        return new_index;
   978     <xsl:text>        console.log("pagelocalindex insert",varname, pagename, new_index);
   973 </xsl:text>
   979 </xsl:text>
   974     <xsl:text>    } else {
   980     <xsl:text>    } else {
   975 </xsl:text>
   981 </xsl:text>
       
   982     <xsl:text>
       
   983 </xsl:text>
       
   984     <xsl:text>        console.log("pagevars",pagevars);
       
   985 </xsl:text>
   976     <xsl:text>        let result = pagevars[varname];
   986     <xsl:text>        let result = pagevars[varname];
   977 </xsl:text>
   987 </xsl:text>
   978     <xsl:text>        if(result==undefined){
   988     <xsl:text>        if(result != undefined) {
   979 </xsl:text>
   989 </xsl:text>
   980     <xsl:text>            let new_index = next_available_index++;
   990     <xsl:text>            console.log("pagelocalindex reuse",varname, pagename, result);
   981 </xsl:text>
   991 </xsl:text>
   982     <xsl:text>            pagevars[varname] = new_index;
   992     <xsl:text>            return result;
   983 </xsl:text>
       
   984     <xsl:text>            return new_index;
       
   985 </xsl:text>
   993 </xsl:text>
   986     <xsl:text>        }
   994     <xsl:text>        }
   987 </xsl:text>
   995 </xsl:text>
   988     <xsl:text>        return result;
   996     <xsl:text>
       
   997 </xsl:text>
       
   998     <xsl:text>        new_index = next_available_index++;
       
   999 </xsl:text>
       
  1000     <xsl:text>        pagevars[varname] = new_index;
       
  1001 </xsl:text>
       
  1002     <xsl:text>        console.log("pagelocalindex addwidget",varname, pagename, new_index);
   989 </xsl:text>
  1003 </xsl:text>
   990     <xsl:text>    }
  1004     <xsl:text>    }
       
  1005 </xsl:text>
       
  1006     <xsl:text>    cache[new_index] = "";
       
  1007 </xsl:text>
       
  1008     <xsl:text>    return new_index;
   991 </xsl:text>
  1009 </xsl:text>
   992     <xsl:text>}
  1010     <xsl:text>}
   993 </xsl:text>
  1011 </xsl:text>
   994     <xsl:text>
  1012     <xsl:text>
   995 </xsl:text>
  1013 </xsl:text>
  1048 </xsl:text>
  1066 </xsl:text>
  1049     <xsl:text>                if(this.relativeness[i])
  1067     <xsl:text>                if(this.relativeness[i])
  1050 </xsl:text>
  1068 </xsl:text>
  1051     <xsl:text>                    index += this.offset;
  1069     <xsl:text>                    index += this.offset;
  1052 </xsl:text>
  1070 </xsl:text>
  1053     <xsl:text>                subscribers[index].delete(this);
  1071     <xsl:text>                subscribers(index).delete(this);
  1054 </xsl:text>
  1072 </xsl:text>
  1055     <xsl:text>            }
  1073     <xsl:text>            }
  1056 </xsl:text>
  1074 </xsl:text>
  1057     <xsl:text>        this.offset = 0;
  1075     <xsl:text>        this.offset = 0;
  1058 </xsl:text>
  1076 </xsl:text>
  1076 </xsl:text>
  1094 </xsl:text>
  1077     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1095     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1078 </xsl:text>
  1096 </xsl:text>
  1079     <xsl:text>                let index = this.get_variable_index(i);
  1097     <xsl:text>                let index = this.get_variable_index(i);
  1080 </xsl:text>
  1098 </xsl:text>
  1081     <xsl:text>                if(index &gt; last_remote_index) return;
  1099     <xsl:text>                subscribers(index).add(this);
  1082 </xsl:text>
       
  1083     <xsl:text>                subscribers[index].add(this);
       
  1084 </xsl:text>
  1100 </xsl:text>
  1085     <xsl:text>            }
  1101     <xsl:text>            }
  1086 </xsl:text>
  1102 </xsl:text>
  1087     <xsl:text>        need_cache_apply.push(this); 
  1103     <xsl:text>        need_cache_apply.push(this); 
  1088 </xsl:text>
  1104 </xsl:text>
  1114 </xsl:text>
  1130 </xsl:text>
  1115     <xsl:text>        let index = this.indexes[varnum];
  1131     <xsl:text>        let index = this.indexes[varnum];
  1116 </xsl:text>
  1132 </xsl:text>
  1117     <xsl:text>        if(typeof(index) == "string"){
  1133     <xsl:text>        if(typeof(index) == "string"){
  1118 </xsl:text>
  1134 </xsl:text>
  1119     <xsl:text>            let page = this.relativeness[varnum];
       
  1120 </xsl:text>
       
  1121     <xsl:text>            index = page_local_index(index, this.container_id);
  1135     <xsl:text>            index = page_local_index(index, this.container_id);
  1122 </xsl:text>
  1136 </xsl:text>
  1123     <xsl:text>        } else {
  1137     <xsl:text>        } else {
  1124 </xsl:text>
  1138 </xsl:text>
  1125     <xsl:text>            if(this.relativeness[varnum]){
  1139     <xsl:text>            if(this.relativeness[varnum]){
  1150 </xsl:text>
  1164 </xsl:text>
  1151     <xsl:text>
  1165     <xsl:text>
  1152 </xsl:text>
  1166 </xsl:text>
  1153     <xsl:text>    new_hmi_value(index, value, oldval) {
  1167     <xsl:text>    new_hmi_value(index, value, oldval) {
  1154 </xsl:text>
  1168 </xsl:text>
  1155     <xsl:text>        try {
  1169     <xsl:text>    /*  try {*/
  1156 </xsl:text>
  1170 </xsl:text>
  1157     <xsl:text>            // TODO avoid searching, store index at sub()
  1171     <xsl:text>            // TODO avoid searching, store index at sub()
  1158 </xsl:text>
  1172 </xsl:text>
  1159     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1173     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1160 </xsl:text>
  1174 </xsl:text>
  1190 </xsl:text>
  1204 </xsl:text>
  1191     <xsl:text>                }
  1205     <xsl:text>                }
  1192 </xsl:text>
  1206 </xsl:text>
  1193     <xsl:text>            }
  1207     <xsl:text>            }
  1194 </xsl:text>
  1208 </xsl:text>
  1195     <xsl:text>        } catch(err) {
  1209     <xsl:text>    /*    } catch(err) {
  1196 </xsl:text>
  1210 </xsl:text>
  1197     <xsl:text>            console.log(err);
  1211     <xsl:text>            console.log(err);
  1198 </xsl:text>
  1212 </xsl:text>
  1199     <xsl:text>        }
  1213     <xsl:text>        }*/
  1200 </xsl:text>
  1214 </xsl:text>
  1201     <xsl:text>    }
  1215     <xsl:text>    }
  1202 </xsl:text>
  1216 </xsl:text>
  1203     <xsl:text>}
  1217     <xsl:text>}
  1204 </xsl:text>
  1218 </xsl:text>
  1555         <xsl:text>Display Widget id="</xsl:text>
  1569         <xsl:text>Display Widget id="</xsl:text>
  1556         <xsl:value-of select="$hmi_element/@id"/>
  1570         <xsl:value-of select="$hmi_element/@id"/>
  1557         <xsl:text>" is not a svg::text element</xsl:text>
  1571         <xsl:text>" is not a svg::text element</xsl:text>
  1558       </xsl:message>
  1572       </xsl:message>
  1559     </xsl:if>
  1573     </xsl:if>
  1560     <xsl:text>    fields: [],
  1574     <xsl:variable name="field_initializer">
       
  1575       <xsl:for-each select="path">
       
  1576         <xsl:choose>
       
  1577           <xsl:when test="@type='HMI_STRING'">
       
  1578             <xsl:text>""</xsl:text>
       
  1579           </xsl:when>
       
  1580           <xsl:otherwise>0</xsl:otherwise>
       
  1581         </xsl:choose>
       
  1582         <xsl:if test="position()!=last()">
       
  1583           <xsl:text>,</xsl:text>
       
  1584         </xsl:if>
       
  1585       </xsl:for-each>
       
  1586     </xsl:variable>
       
  1587     <xsl:text>    fields: [</xsl:text>
       
  1588     <xsl:value-of select="$field_initializer"/>
       
  1589     <xsl:text>],
  1561 </xsl:text>
  1590 </xsl:text>
  1562   </xsl:template>
  1591   </xsl:template>
  1563   <preamble:display/>
  1592   <preamble:display/>
  1564   <xsl:template match="preamble:display">
  1593   <xsl:template match="preamble:display">
  1565     <xsl:text>
  1594     <xsl:text>
  2953         <xsl:text>Clones (svg:use) in JsonTable Widget must point to a valid HMI:List widget or HMI:List item. Reference "</xsl:text>
  2982         <xsl:text>Clones (svg:use) in JsonTable Widget must point to a valid HMI:List widget or HMI:List item. Reference "</xsl:text>
  2954         <xsl:value-of select="@xlink:href"/>
  2983         <xsl:value-of select="@xlink:href"/>
  2955         <xsl:text>" is not valid.</xsl:text>
  2984         <xsl:text>" is not valid.</xsl:text>
  2956       </xsl:message>
  2985       </xsl:message>
  2957     </xsl:if>
  2986     </xsl:if>
  2958     <xsl:text>        console.log("</xsl:text>
       
  2959     <xsl:value-of select="@id"/>
       
  2960     <xsl:text>", "</xsl:text>
       
  2961     <xsl:value-of select="$value_expr"/>
       
  2962     <xsl:text>", </xsl:text>
       
  2963     <xsl:value-of select="$value_expr"/>
       
  2964     <xsl:text>);
       
  2965 </xsl:text>
       
  2966     <xsl:text>        id("</xsl:text>
  2987     <xsl:text>        id("</xsl:text>
  2967     <xsl:value-of select="@id"/>
  2988     <xsl:value-of select="@id"/>
  2968     <xsl:text>").setAttribute("xlink:href", 
  2989     <xsl:text>").setAttribute("xlink:href", 
  2969 </xsl:text>
  2990 </xsl:text>
  2970     <xsl:text>            "#"+hmi_widgets["</xsl:text>
  2991     <xsl:text>            "#"+hmi_widgets["</xsl:text>
  2974     <xsl:text>]);
  2995     <xsl:text>]);
  2975 </xsl:text>
  2996 </xsl:text>
  2976   </xsl:template>
  2997   </xsl:template>
  2977   <xsl:template mode="json_table_elt_render" match="svg:text">
  2998   <xsl:template mode="json_table_elt_render" match="svg:text">
  2978     <xsl:param name="value_expr"/>
  2999     <xsl:param name="value_expr"/>
  2979     <xsl:text>        console.log("</xsl:text>
       
  2980     <xsl:value-of select="@id"/>
       
  2981     <xsl:text>", "</xsl:text>
       
  2982     <xsl:value-of select="$value_expr"/>
       
  2983     <xsl:text>", </xsl:text>
       
  2984     <xsl:value-of select="$value_expr"/>
       
  2985     <xsl:text>);
       
  2986 </xsl:text>
       
  2987     <xsl:text>        id("</xsl:text>
  3000     <xsl:text>        id("</xsl:text>
  2988     <xsl:value-of select="@id"/>
  3001     <xsl:value-of select="@id"/>
  2989     <xsl:text>").textContent = String(</xsl:text>
  3002     <xsl:text>").textContent = String(</xsl:text>
  2990     <xsl:value-of select="$value_expr"/>
  3003     <xsl:value-of select="$value_expr"/>
  2991     <xsl:text>);
  3004     <xsl:text>);
  3031       </xsl:with-param>
  3044       </xsl:with-param>
  3032       <xsl:with-param name="mandatory" select="'no'"/>
  3045       <xsl:with-param name="mandatory" select="'no'"/>
  3033     </xsl:call-template>
  3046     </xsl:call-template>
  3034     <xsl:variable name="data_elt" select="$result_svg_ns//*[@id = $hmi_element/@id]/*[@inkscape:label = 'data']"/>
  3047     <xsl:variable name="data_elt" select="$result_svg_ns//*[@id = $hmi_element/@id]/*[@inkscape:label = 'data']"/>
  3035     <xsl:text>    spread_json_data: function(jdata) {
  3048     <xsl:text>    spread_json_data: function(jdata) {
  3036 </xsl:text>
       
  3037     <xsl:text>        console.log(jdata);
       
  3038 </xsl:text>
  3049 </xsl:text>
  3039     <xsl:apply-templates mode="json_table_render" select="$data_elt/*">
  3050     <xsl:apply-templates mode="json_table_render" select="$data_elt/*">
  3040       <xsl:with-param name="objname" select="'jdata'"/>
  3051       <xsl:with-param name="objname" select="'jdata'"/>
  3041     </xsl:apply-templates>
  3052     </xsl:apply-templates>
  3042     <xsl:text>    }
  3053     <xsl:text>    }
  3702       <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
  3713       <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
  3703     </xsl:comment>
  3714     </xsl:comment>
  3704     <xsl:comment>
  3715     <xsl:comment>
  3705       <xsl:apply-templates select="document('')/*/debug:*"/>
  3716       <xsl:apply-templates select="document('')/*/debug:*"/>
  3706     </xsl:comment>
  3717     </xsl:comment>
  3707     <html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  3718     <html xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/1999/xhtml">
  3708       <head/>
  3719       <head/>
  3709       <body style="margin:0;overflow:hidden;">
  3720       <body style="margin:0;overflow:hidden;">
  3710         <xsl:copy-of select="$result_svg"/>
  3721         <xsl:copy-of select="$result_svg"/>
  3711         <script>
  3722         <script>
  3712           <xsl:text>
  3723           <xsl:text>
  3743           <xsl:apply-templates select="document('')/*/epilogue:*"/>
  3754           <xsl:apply-templates select="document('')/*/epilogue:*"/>
  3744           <xsl:text>// svghmi.js
  3755           <xsl:text>// svghmi.js
  3745 </xsl:text>
  3756 </xsl:text>
  3746           <xsl:text>
  3757           <xsl:text>
  3747 </xsl:text>
  3758 </xsl:text>
  3748           <xsl:text>var cache = hmitree_types.map(_ignored =&gt; undefined);
       
  3749 </xsl:text>
       
  3750           <xsl:text>var updates = {};
  3759           <xsl:text>var updates = {};
  3751 </xsl:text>
  3760 </xsl:text>
  3752           <xsl:text>var need_cache_apply = []; 
  3761           <xsl:text>var need_cache_apply = []; 
  3753 </xsl:text>
  3762 </xsl:text>
  3754           <xsl:text>
  3763           <xsl:text>
  3755 </xsl:text>
  3764 </xsl:text>
  3756           <xsl:text>
  3765           <xsl:text>
  3757 </xsl:text>
  3766 </xsl:text>
  3758           <xsl:text>function dispatch_value(index, value) {
  3767           <xsl:text>function dispatch_value(index, value) {
  3759 </xsl:text>
  3768 </xsl:text>
  3760           <xsl:text>    let widgets = subscribers[index];
  3769           <xsl:text>    let widgets = subscribers(index);
  3761 </xsl:text>
  3770 </xsl:text>
  3762           <xsl:text>
  3771           <xsl:text>
  3763 </xsl:text>
  3772 </xsl:text>
  3764           <xsl:text>    let oldval = cache[index];
  3773           <xsl:text>    let oldval = cache[index];
  3765 </xsl:text>
  3774 </xsl:text>
  3855 </xsl:text>
  3864 </xsl:text>
  3856           <xsl:text>        // serving as a key, index becomes a string
  3865           <xsl:text>        // serving as a key, index becomes a string
  3857 </xsl:text>
  3866 </xsl:text>
  3858           <xsl:text>        // -&gt; pass Number(index) instead
  3867           <xsl:text>        // -&gt; pass Number(index) instead
  3859 </xsl:text>
  3868 </xsl:text>
       
  3869           <xsl:text>        console.log("apply updated local variable ",index, updates[index]);
       
  3870 </xsl:text>
  3860           <xsl:text>        dispatch_value(Number(index), updates[index]);
  3871           <xsl:text>        dispatch_value(Number(index), updates[index]);
  3861 </xsl:text>
  3872 </xsl:text>
  3862           <xsl:text>        delete updates[index];
  3873           <xsl:text>        delete updates[index];
  3863 </xsl:text>
  3874 </xsl:text>
  3864           <xsl:text>    }
  3875           <xsl:text>    }
  4055 </xsl:text>
  4066 </xsl:text>
  4056           <xsl:text>};
  4067           <xsl:text>};
  4057 </xsl:text>
  4068 </xsl:text>
  4058           <xsl:text>
  4069           <xsl:text>
  4059 </xsl:text>
  4070 </xsl:text>
  4060           <xsl:text>// subscription state, as it should be in hmi server
  4071           <xsl:text>var subscriptions = [];
  4061 </xsl:text>
  4072 </xsl:text>
  4062           <xsl:text>// hmitree indexed array of integers
  4073           <xsl:text>
  4063 </xsl:text>
  4074 </xsl:text>
  4064           <xsl:text>var subscriptions =  hmitree_types.map(_ignored =&gt; 0);
  4075           <xsl:text>function subscribers(index) {
  4065 </xsl:text>
  4076 </xsl:text>
  4066           <xsl:text>
  4077           <xsl:text>    let entry = subscriptions[index];
  4067 </xsl:text>
  4078 </xsl:text>
  4068           <xsl:text>// subscription state as needed by widget now
  4079           <xsl:text>    let res;
  4069 </xsl:text>
  4080 </xsl:text>
  4070           <xsl:text>// hmitree indexed array of Sets of widgets objects
  4081           <xsl:text>    if(entry == undefined){
  4071 </xsl:text>
  4082 </xsl:text>
  4072           <xsl:text>var subscribers = hmitree_types.map(_ignored =&gt; new Set());
  4083           <xsl:text>        res = new Set();
       
  4084 </xsl:text>
       
  4085           <xsl:text>        subscriptions[index] = [res,0];
       
  4086 </xsl:text>
       
  4087           <xsl:text>    }else{
       
  4088 </xsl:text>
       
  4089           <xsl:text>        [res, _ign] = entry;
       
  4090 </xsl:text>
       
  4091           <xsl:text>    }
       
  4092 </xsl:text>
       
  4093           <xsl:text>    return res
       
  4094 </xsl:text>
       
  4095           <xsl:text>}
       
  4096 </xsl:text>
       
  4097           <xsl:text>
       
  4098 </xsl:text>
       
  4099           <xsl:text>function get_subscription_period(index) {
       
  4100 </xsl:text>
       
  4101           <xsl:text>    let entry = subscriptions[index];
       
  4102 </xsl:text>
       
  4103           <xsl:text>    if(entry == undefined)
       
  4104 </xsl:text>
       
  4105           <xsl:text>        return 0;
       
  4106 </xsl:text>
       
  4107           <xsl:text>    let [_ign, period] = entry;
       
  4108 </xsl:text>
       
  4109           <xsl:text>    return period;
       
  4110 </xsl:text>
       
  4111           <xsl:text>}
       
  4112 </xsl:text>
       
  4113           <xsl:text>
       
  4114 </xsl:text>
       
  4115           <xsl:text>function set_subscription_period(index, period) {
       
  4116 </xsl:text>
       
  4117           <xsl:text>    let entry = subscriptions[index];
       
  4118 </xsl:text>
       
  4119           <xsl:text>    if(entry == undefined){
       
  4120 </xsl:text>
       
  4121           <xsl:text>        subscriptions[index] = [new Set(), period];
       
  4122 </xsl:text>
       
  4123           <xsl:text>    } else {
       
  4124 </xsl:text>
       
  4125           <xsl:text>        entry[1] = period;
       
  4126 </xsl:text>
       
  4127           <xsl:text>    }
       
  4128 </xsl:text>
       
  4129           <xsl:text>}
  4073 </xsl:text>
  4130 </xsl:text>
  4074           <xsl:text>
  4131           <xsl:text>
  4075 </xsl:text>
  4132 </xsl:text>
  4076           <xsl:text>// artificially subscribe the watchdog widget to "/heartbeat" hmi variable
  4133           <xsl:text>// artificially subscribe the watchdog widget to "/heartbeat" hmi variable
  4077 </xsl:text>
  4134 </xsl:text>
  4078           <xsl:text>// Since dispatch directly calls change_hmi_value,
  4135           <xsl:text>// Since dispatch directly calls change_hmi_value,
  4079 </xsl:text>
  4136 </xsl:text>
  4080           <xsl:text>// PLC will periodically send variable at given frequency
  4137           <xsl:text>// PLC will periodically send variable at given frequency
  4081 </xsl:text>
  4138 </xsl:text>
  4082           <xsl:text>subscribers[heartbeat_index].add({
  4139           <xsl:text>subscribers(heartbeat_index).add({
  4083 </xsl:text>
  4140 </xsl:text>
  4084           <xsl:text>    /* type: "Watchdog", */
  4141           <xsl:text>    /* type: "Watchdog", */
  4085 </xsl:text>
  4142 </xsl:text>
  4086           <xsl:text>    frequency: 1,
  4143           <xsl:text>    frequency: 1,
  4087 </xsl:text>
  4144 </xsl:text>
  4095 </xsl:text>
  4152 </xsl:text>
  4096           <xsl:text>});
  4153           <xsl:text>});
  4097 </xsl:text>
  4154 </xsl:text>
  4098           <xsl:text>
  4155           <xsl:text>
  4099 </xsl:text>
  4156 </xsl:text>
       
  4157           <xsl:text>
       
  4158 </xsl:text>
  4100           <xsl:text>function update_subscriptions() {
  4159           <xsl:text>function update_subscriptions() {
  4101 </xsl:text>
  4160 </xsl:text>
  4102           <xsl:text>    let delta = [];
  4161           <xsl:text>    let delta = [];
  4103 </xsl:text>
  4162 </xsl:text>
  4104           <xsl:text>    for(let index = 0; index &lt; subscribers.length; index++){
  4163           <xsl:text>    for(let index in subscriptions){
  4105 </xsl:text>
  4164 </xsl:text>
  4106           <xsl:text>        let widgets = subscribers[index];
  4165           <xsl:text>        let widgets = subscribers(index);
  4107 </xsl:text>
  4166 </xsl:text>
  4108           <xsl:text>
  4167           <xsl:text>
  4109 </xsl:text>
  4168 </xsl:text>
  4110           <xsl:text>        // periods are in ms
  4169           <xsl:text>        // periods are in ms
  4111 </xsl:text>
  4170 </xsl:text>
  4112           <xsl:text>        let previous_period = subscriptions[index];
  4171           <xsl:text>        let previous_period = get_subscription_period(index);
  4113 </xsl:text>
  4172 </xsl:text>
  4114           <xsl:text>
  4173           <xsl:text>
  4115 </xsl:text>
  4174 </xsl:text>
  4116           <xsl:text>        // subscribing with a zero period is unsubscribing
  4175           <xsl:text>        // subscribing with a zero period is unsubscribing
  4117 </xsl:text>
  4176 </xsl:text>
  4141 </xsl:text>
  4200 </xsl:text>
  4142           <xsl:text>
  4201           <xsl:text>
  4143 </xsl:text>
  4202 </xsl:text>
  4144           <xsl:text>        if(previous_period != new_period) {
  4203           <xsl:text>        if(previous_period != new_period) {
  4145 </xsl:text>
  4204 </xsl:text>
  4146           <xsl:text>            subscriptions[index] = new_period;
  4205           <xsl:text>            set_subscription_period(index, new_period);
  4147 </xsl:text>
  4206 </xsl:text>
  4148           <xsl:text>            delta.push(
  4207           <xsl:text>            if(index &lt;= last_remote_index){
  4149 </xsl:text>
  4208 </xsl:text>
  4150           <xsl:text>                new Uint8Array([2]), /* subscribe = 2 */
  4209           <xsl:text>                delta.push(
  4151 </xsl:text>
  4210 </xsl:text>
  4152           <xsl:text>                new Uint32Array([index]),
  4211           <xsl:text>                    new Uint8Array([2]), /* subscribe = 2 */
  4153 </xsl:text>
  4212 </xsl:text>
  4154           <xsl:text>                new Uint16Array([new_period]));
  4213           <xsl:text>                    new Uint32Array([index]),
       
  4214 </xsl:text>
       
  4215           <xsl:text>                    new Uint16Array([new_period]));
       
  4216 </xsl:text>
       
  4217           <xsl:text>            }
  4155 </xsl:text>
  4218 </xsl:text>
  4156           <xsl:text>        }
  4219           <xsl:text>        }
  4157 </xsl:text>
  4220 </xsl:text>
  4158           <xsl:text>    }
  4221           <xsl:text>    }
  4159 </xsl:text>
  4222 </xsl:text>
  4165 </xsl:text>
  4228 </xsl:text>
  4166           <xsl:text>function send_hmi_value(index, value) {
  4229           <xsl:text>function send_hmi_value(index, value) {
  4167 </xsl:text>
  4230 </xsl:text>
  4168           <xsl:text>    if(index &gt; last_remote_index){
  4231           <xsl:text>    if(index &gt; last_remote_index){
  4169 </xsl:text>
  4232 </xsl:text>
  4170           <xsl:text>        cache[index] = value;
       
  4171 </xsl:text>
       
  4172           <xsl:text>        console.log("updated local variable ",index,value);
  4233           <xsl:text>        console.log("updated local variable ",index,value);
  4173 </xsl:text>
  4234 </xsl:text>
  4174           <xsl:text>        /* TODO : dispatch value ASAP */
  4235           <xsl:text>        updates[index] = value;
       
  4236 </xsl:text>
       
  4237           <xsl:text>        requestHMIAnimation();
  4175 </xsl:text>
  4238 </xsl:text>
  4176           <xsl:text>        return;
  4239           <xsl:text>        return;
  4177 </xsl:text>
  4240 </xsl:text>
  4178           <xsl:text>    }
  4241           <xsl:text>    }
  4179 </xsl:text>
  4242 </xsl:text>
  4373 </xsl:text>
  4436 </xsl:text>
  4374           <xsl:text>    var new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
  4437           <xsl:text>    var new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
  4375 </xsl:text>
  4438 </xsl:text>
  4376           <xsl:text>
  4439           <xsl:text>
  4377 </xsl:text>
  4440 </xsl:text>
  4378           <xsl:text>    container_id = String([page_name, page_index]);
  4441           <xsl:text>    container_id = page_name + (page_index != undefined ? page_index : "");
  4379 </xsl:text>
  4442 </xsl:text>
  4380           <xsl:text>
  4443           <xsl:text>
  4381 </xsl:text>
  4444 </xsl:text>
  4382           <xsl:text>    new_desc.widgets.map(([widget,relativeness])=&gt;widget.sub(new_offset,relativeness,container_id));
  4445           <xsl:text>    new_desc.widgets.map(([widget,relativeness])=&gt;widget.sub(new_offset,relativeness,container_id));
  4383 </xsl:text>
  4446 </xsl:text>