RUNTIME: Variable trace now uses limited list and buffer instead of flags in instance tree that was requiring systematical instance tree traversal, and worst size buffer. Forcing and retain still use tree traversal.
// hmi_tree.ysl2
// Location identifies uniquely SVGHMI instance
param "instance_name";
// HMI Tree computed from VARIABLES.CSV in svghmi.py
const "hmitree", "ns:GetHMITree()";
const "_categories" {
noindex > HMI_PLC_STATUS
noindex > HMI_CURRENT_PAGE
}
const "categories", "exsl:node-set($_categories)";
// HMI Tree Index
const "_indexed_hmitree" apply "$hmitree", mode="index";
const "indexed_hmitree", "exsl:node-set($_indexed_hmitree)";
emit "preamble:hmi-tree" {
| var hmi_hash = [«$hmitree/@hash»];
|
| var heartbeat_index = «$indexed_hmitree/*[@hmipath = '/HEARTBEAT']/@index»;
|
| var current_page_var_index = «$indexed_hmitree/*[@hmipath = concat('/CURRENT_PAGE_', $instance_name)]/@index»;
|
| var hmitree_types = [
foreach "$indexed_hmitree/*"
| "«substring(local-name(), 5)»"`if "position()!=last()" > ,`
| ];
|
| var hmitree_paths = [
foreach "$indexed_hmitree/*"
| "«@hmipath»"`if "position()!=last()" > ,`
| ];
|
| var hmitree_nodes = {
foreach "$indexed_hmitree/*[local-name() = 'HMI_NODE']"
| "«@hmipath»" : [«@index», "«@class»"]`if "position()!=last()" > ,`
| };
|
}
template "*", mode="index" {
param "index", "0";
param "parentpath", "''";
const "content" {
const "path"
choose {
when "count(ancestor::*)=0" > /
when "count(ancestor::*)=1" > /«@name»
otherwise > «$parentpath»/«@name»
}
choose {
when "not(local-name() = $categories/noindex)" {
xsl:copy {
attrib "index" > «$index»
attrib "hmipath" > «$path»
foreach "@*" xsl:copy;
}
apply "*[1]", mode="index"{
with "index", "$index + 1";
with "parentpath" > «$path»
}
}
otherwise {
apply "*[1]", mode="index"{
with "index", "$index";
with "parentpath" > «$path»
}
}
}
}
copy "$content";
apply "following-sibling::*[1]", mode="index" {
with "index", "$index + count(exsl:node-set($content)/*)";
with "parentpath" > «$parentpath»
}
}
include parse_labels.ysl2
const "_parsed_widgets" {
widget type="VarInitPersistent" {
arg value="0";
path value="lang";
}
apply "$hmi_elements", mode="parselabel";
}
const "parsed_widgets","exsl:node-set($_parsed_widgets)";
def "func:widget" {
param "id";
result "$parsed_widgets/widget[@id = $id]";
}
def "func:is_descendant_path" {
param "descend";
param "ancest";
// TODO : use HMI tree to answer more accurately
result "string-length($ancest) > 0 and starts-with($descend,$ancest)";
}
def "func:same_class_paths" {
param "a";
param "b";
const "class_a", "$indexed_hmitree/*[@hmipath = $a]/@class";
const "class_b", "$indexed_hmitree/*[@hmipath = $b]/@class";
result "$class_a and $class_b and $class_a = $class_b";
}
// Debug data
template "*", mode="testtree"{
param "indent", "''";
> «$indent» «local-name()»
foreach "@*" > «local-name()»="«.»"
> \n
apply "*", mode="testtree" {
with "indent" value "concat($indent,'>')"
};
}
emit "debug:hmi-tree" {
| Raw HMI tree
apply "$hmitree", mode="testtree";
|
| Indexed HMI tree
apply "$indexed_hmitree", mode="testtree";
|
| Parsed Widgets
copy "_parsed_widgets";
apply "$parsed_widgets", mode="testtree";
}