edouard@2884: // widgets_common.ysl2 edouard@2884: Edouard@2808: in xsl decl labels(*ptr, name="defs_by_labels") alias call-template { Edouard@2808: with "hmi_element", "$hmi_element"; Edouard@2810: with "labels"{text *ptr}; edouard@2937: content; Edouard@2808: }; Edouard@2808: edouard@2937: decl optional_labels(*ptr) alias - { edouard@2937: /* TODO add some per label xslt variable to check if exist */ edouard@2937: labels(*ptr){ edouard@2937: with "mandatory","'no'"; edouard@2937: content; edouard@2937: } Edouard@2836: }; Edouard@2836: edouard@2937: decl activable_labels(*ptr) alias - { edouard@2937: optional_labels(*ptr) { edouard@2937: with "subelements","'active inactive'"; edouard@2937: content; edouard@2937: } edouard@2920: }; edouard@2920: edouard@2955: template "svg:*", mode="hmi_widgets" { edouard@2886: const "widget", "func:widget(@id)"; Edouard@2881: const "eltid","@id"; edouard@2950: const "args" foreach "$widget/arg" > "«@value»"`if "position()!=last()" > ,` edouard@2950: const "indexes" foreach "$widget/path" { Edouard@2881: choose { Edouard@2881: when "not(@index)" { Edouard@2881: warning > Widget «$widget/@type» id="«$eltid»" : No match for path "«@value»" in HMI tree Edouard@2881: } Edouard@2881: otherwise { edouard@2950: > «@index»`if "position()!=last()" > ,` Edouard@2792: } Edouard@2792: } Edouard@2792: } edouard@2950: edouard@2950: | "«@id»": new «$widget/@type»Widget ("«@id»",[«$args»],[«$indexes»],{ Edouard@2881: apply "$widget", mode="widget_defs" with "hmi_element","."; edouard@2949: | })`if "position()!=last()" > ,` edouard@2949: } edouard@2948: edouard@2948: def "func:unique_types" { edouard@2948: param "elts_with_type"; edouard@2948: choose { edouard@2948: when "count($elts_with_type) > 1" { edouard@2948: const "prior_results","func:unique_types($elts_with_type[position()!=last()])"; edouard@2948: choose { edouard@2948: when "$elts_with_type[last()][@type = $prior_results/@type]"{ edouard@2948: // type already in edouard@2948: result "$prior_results"; edouard@2948: } edouard@2948: otherwise { edouard@2948: result "$prior_results | $elts_with_type[last()]"; edouard@2948: } edouard@2948: } edouard@2948: } edouard@2948: otherwise { edouard@2948: result "$elts_with_type"; edouard@2948: } edouard@2948: } edouard@2948: } edouard@2948: edouard@2949: emit "preamble:widget-base-class" { edouard@2949: || edouard@2949: class Widget { edouard@2963: offset = 0; edouard@2963: frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */ Edouard@2980: unsubscribable = false; edouard@2950: constructor(elt_id,args,indexes,members){ edouard@2958: this.element_id = elt_id; edouard@2950: this.element = id(elt_id); edouard@2950: this.args = args; edouard@2950: this.indexes = indexes; edouard@2949: Object.keys(members).forEach(prop => this[prop]=members[prop]); edouard@2949: } edouard@2958: edouard@2951: unsub(){ edouard@2951: /* remove subsribers */ Edouard@2980: if(!this.unsubscribable) for(let index of this.indexes){ edouard@2951: let idx = index + this.offset; edouard@2951: subscribers[idx].delete(this); edouard@2951: } edouard@2951: this.offset = 0; edouard@2951: } edouard@2951: edouard@2951: sub(new_offset=0){ edouard@2951: /* set the offset because relative */ edouard@2951: this.offset = new_offset; edouard@2951: /* add this's subsribers */ Edouard@2980: if(!this.unsubscribable) for(let index of this.indexes){ edouard@2951: subscribers[index + new_offset].add(this); edouard@2951: } edouard@2951: need_cache_apply.push(this); edouard@2951: } edouard@2951: edouard@2951: apply_cache() { Edouard@2980: if(!this.unsubscribable) for(let index of this.indexes){ edouard@2951: /* dispatch current cache in newly opened page widgets */ edouard@2951: let realindex = index+this.offset; edouard@2951: let cached_val = cache[realindex]; edouard@2951: if(cached_val != undefined) edouard@2951: dispatch_value_to_widget(this, realindex, cached_val, cached_val); edouard@2951: } edouard@2951: } edouard@2951: edouard@2949: } edouard@2949: || edouard@2949: } edouard@2949: edouard@2948: emit "preamble:hmi-classes" { edouard@2948: const "used_widget_types", "func:unique_types($parsed_widgets/widget)"; edouard@2948: apply "$used_widget_types", mode="widget_class"; Edouard@2881: } Edouard@2810: edouard@2949: template "widget", mode="widget_class" edouard@2949: || edouard@2949: class «@type»Widget extends Widget{ edouard@2949: /* empty class, as «@type» widget didn't provide any */ edouard@2949: } edouard@2949: || edouard@2949: edouard@2955: const "excluded_types", "str:split('Page Lang List')"; edouard@2955: const "excluded_ids","$parsed_widgets/widget[not(@type = $excluded_types)]/@id"; edouard@2955: edouard@2941: emit "preamble:hmi-elements" { edouard@2941: | var hmi_widgets = { edouard@2955: apply "$hmi_elements[@id = $excluded_ids]", mode="hmi_widgets"; edouard@2941: | } edouard@2941: } edouard@2941: Edouard@2881: function "defs_by_labels" { Edouard@2881: param "labels","''"; Edouard@2881: param "mandatory","'yes'"; edouard@2920: param "subelements","/.."; Edouard@2881: param "hmi_element"; Edouard@2881: const "widget_type","@type"; Edouard@2881: foreach "str:split($labels)" { Edouard@2881: const "name","."; edouard@2920: const "elt","$result_svg_ns//*[@id = $hmi_element/@id]//*[@inkscape:label=$name][1]"; Edouard@2881: choose { edouard@2920: when "not($elt/@id)" { Edouard@2881: if "$mandatory='yes'" { edouard@2920: error > «$widget_type» widget must have a «$name» element Edouard@2834: } Edouard@2881: // otherwise produce nothing Edouard@2797: } Edouard@2881: otherwise { edouard@2920: | «$name»_elt: id("«$elt/@id»"), edouard@2920: if "$subelements" { edouard@2920: | «$name»_sub: { edouard@2920: foreach "str:split($subelements)" { edouard@2920: const "subname","."; edouard@2920: const "subelt","$elt/*[@inkscape:label=$subname][1]"; edouard@2920: choose { edouard@2920: when "not($subelt/@id)" { edouard@2920: if "$mandatory='yes'" { edouard@2920: error > «$widget_type» widget must have a «$name»/«$subname» element edouard@2920: } edouard@2920: | /* missing «$name»/«$subname» element */ edouard@2920: } edouard@2920: otherwise { edouard@2920: | "«$subname»": id("«$subelt/@id»")`if "position()!=last()" > ,` edouard@2920: } edouard@2920: } edouard@2920: } edouard@2920: | }, edouard@2920: } Edouard@2836: } Edouard@2808: } Edouard@2808: } Edouard@2881: } Edouard@2808: edouard@2883: def "func:escape_quotes" { edouard@2883: param "txt"; edouard@2883: // have to use a python string to enter escaped quote edouard@2883: const "frst", !"substring-before($txt,'\"')"!; edouard@2883: const "frstln", "string-length($frst)"; edouard@2883: choose { edouard@2883: when "$frstln > 0 and string-length($txt) > $frstln" { edouard@2883: result !"concat($frst,'\\\"',func:escape_quotes(substring-after($txt,'\"')))"!; edouard@2883: } edouard@2883: otherwise { edouard@2883: result "$txt"; edouard@2883: } edouard@2883: } edouard@2883: } edouard@2883: