# HG changeset patch # User Laurent Bessard # Date 1381348823 -7200 # Node ID aee0a7eb833af5d26d11fc7fd97794a9913864fd # Parent 533741e5075c49f802d3fc6104401e0b5ce44ce1 Fixed pou variables instance information loading stylesheet diff -r 533741e5075c -r aee0a7eb833a PLCControler.py --- a/PLCControler.py Wed Oct 09 10:57:20 2013 +0200 +++ b/PLCControler.py Wed Oct 09 22:00:23 2013 +0200 @@ -189,85 +189,54 @@ # Helpers object for generating pou variable instance list #------------------------------------------------------------------------------- -def class_extraction(el, prt): - if prt in ["pou", "variable"]: - pou_type = POU_TYPES.get(el.text) - if pou_type is not None: - return pou_type - return VAR_CLASS_INFOS[el.text][1] - return { +def class_extraction(value): + class_type = { "configuration": ITEM_CONFIGURATION, "resource": ITEM_RESOURCE, "action": ITEM_ACTION, "transition": ITEM_TRANSITION, - "program": ITEM_PROGRAM}.get(prt) - -PARAM_VALUE_EXTRACTION = { - "name": lambda el, prt: el.text, - "class": class_extraction, - "type": lambda el, prt: None if el.text == "None" else el.text, - "edit": lambda el, prt: el.text == "True", - "debug": lambda el, prt: el.text == "True", - "variables": lambda el, prt: [ - compute_instance_tree(chld) - for chld in el]} - -def compute_instance_tree(tree): - return {el.tag: - PARAM_VALUE_EXTRACTION[el.tag](el, tree.tag) - for el in tree} - -class IsEdited(etree.XSLTExtension): - - def __init__(self, controller, debug): - etree.XSLTExtension.__init__(self) - self.Controller = controller - self.Debug = debug - - def execute(self, context, self_node, input_node, output_parent): - typename = input_node.get("name") - project = self.Controller.GetProject(self.Debug) - output_parent.text = str(project.getpou(typename) is not None) - -class IsDebugged(etree.XSLTExtension): - - def __init__(self, controller, debug): - etree.XSLTExtension.__init__(self) - self.Controller = controller - self.Debug = debug - - def execute(self, context, self_node, input_node, output_parent): - typename = input_node.get("name") - project = self.Controller.GetProject(self.Debug) - pou_infos = project.getpou(typename) - if pou_infos is not None: - self.apply_templates(context, pou_infos, output_parent) - return - - datatype_infos = self.Controller.GetDataType(typename, self.Debug) - if datatype_infos is not None: - self.apply_templates(context, datatype_infos, output_parent) - return - - output_parent.text = "False" - -class PouVariableClass(etree.XSLTExtension): - - def __init__(self, controller, debug): - etree.XSLTExtension.__init__(self) - self.Controller = controller - self.Debug = debug - - def execute(self, context, self_node, input_node, output_parent): - pou_infos = self.Controller.GetPou(input_node.get("name"), self.Debug) - if pou_infos is not None: - self.apply_templates(context, pou_infos, output_parent) - return - - self.process_children(context, output_parent) - -pou_variables_xslt = etree.parse( - os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt")) + "program": ITEM_PROGRAM}.get(value) + if class_type is not None: + return class_type + + pou_type = POU_TYPES.get(value) + if pou_type is not None: + return pou_type + + var_type = VAR_CLASS_INFOS.get(value) + if var_type is not None: + return var_type[1] + + return None + +class _VariablesTreeItemInfos(object): + __slots__ = ["name", "var_class", "type", "edit", "debug", "variables"] + def __init__(self, *args): + for attr, value in zip(self.__slots__, args): + setattr(self, attr, value if value is not None else "") + def copy(self): + return _VariableTreeItem(*[getattr(self, attr) for attr in self.__slots__]) + +class VariablesTreeInfosFactory: + + def __init__(self): + self.Root = None + + def GetRoot(self): + return self.Root + + def SetRoot(self, context, *args): + self.Root = _VariablesTreeItemInfos( + *([''] + _translate_args( + [class_extraction, str] + [_BoolValue] * 2, + args) + [[]])) + + def AddVariable(self, context, *args): + if self.Root is not None: + self.Root.variables.append(_VariablesTreeItemInfos( + *(_translate_args( + [str, class_extraction, str] + [_BoolValue] * 2, + args) + [[]]))) #------------------------------------------------------------------------------- # Helpers object for generating instances path list @@ -799,20 +768,28 @@ pou_type = None project = self.GetProject(debug) if project is not None: + factory = VariablesTreeInfosFactory() + + parser = etree.XMLParser() + parser.resolvers.add(LibraryResolver(self, debug)) + pou_variable_xslt_tree = etree.XSLT( - pou_variables_xslt, extensions = { - ("pou_vars_ns", "is_edited"): IsEdited(self, debug), - ("pou_vars_ns", "is_debugged"): IsDebugged(self, debug), - ("pou_vars_ns", "pou_class"): PouVariableClass(self, debug)}) + etree.parse( + os.path.join(ScriptDirectory, "plcopen", "pou_variables.xslt"), + parser), + extensions = {("pou_vars_ns", name): getattr(factory, name) + for name in ["SetRoot", "AddVariable"]}) + obj = None words = tagname.split("::") if words[0] == "P": obj = self.GetPou(words[1], debug) - else: + elif words[0] != "D": obj = self.GetEditedElement(tagname, debug) if obj is not None: - return compute_instance_tree( - pou_variable_xslt_tree(obj).getroot()) + pou_variable_xslt_tree(obj) + return factory.GetRoot() + return None def GetInstanceList(self, root, name, debug = False): diff -r 533741e5075c -r aee0a7eb833a controls/PouInstanceVariablesPanel.py --- a/controls/PouInstanceVariablesPanel.py Wed Oct 09 10:57:20 2013 +0200 +++ b/controls/PouInstanceVariablesPanel.py Wed Oct 09 22:00:23 2013 +0200 @@ -244,27 +244,27 @@ self.PouInfos = None if self.PouInfos is not None: root = self.VariablesList.AddRoot("") - for var_infos in self.PouInfos["variables"]: - if var_infos.get("type", None) is not None: - text = "%(name)s (%(type)s)" % var_infos + for var_infos in self.PouInfos.variables: + if var_infos.type is not None: + text = "%s (%s)" % (var_infos.name, var_infos.type) else: - text = var_infos["name"] + text = var_infos.name right_images = [] - if var_infos["class"] in ITEMS_VARIABLE: - if (not USE_MPL and var_infos["debug"] and self.Debug and - (self.Controller.IsOfType(var_infos["type"], "ANY_NUM", True) or - self.Controller.IsOfType(var_infos["type"], "ANY_BIT", True))): + if var_infos.var_class in ITEMS_VARIABLE: + if (not USE_MPL and var_infos.debug and self.Debug and + (self.Controller.IsOfType(var_infos.type, "ANY_NUM", True) or + self.Controller.IsOfType(var_infos.type, "ANY_BIT", True))): right_images.append(self.InstanceGraphImage) - elif var_infos["edit"]: + elif var_infos.edit: right_images.append(self.EditImage) - if var_infos["debug"] and self.Debug: + if var_infos.debug and self.Debug: right_images.append(self.DebugInstanceImage) item = self.VariablesList.AppendItem(root, text) item.SetRightImages(right_images) - self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos["class"])) + self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos.var_class)) self.VariablesList.SetPyData(item, var_infos) self.RefreshInstanceChoice() @@ -281,7 +281,7 @@ self.InstanceChoice.Append(instance) if len(instances) == 1: self.PouInstance = instances[0] - if self.PouInfos["class"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]: + if self.PouInfos.var_class in [ITEM_CONFIGURATION, ITEM_RESOURCE]: self.PouInstance = None self.InstanceChoice.SetSelection(0) elif self.PouInstance in instances: @@ -292,8 +292,8 @@ def RefreshButtons(self): enabled = self.InstanceChoice.GetSelection() != -1 - self.ParentButton.Enable(enabled and self.PouInfos["class"] != ITEM_CONFIGURATION) - self.DebugButton.Enable(enabled and self.PouInfos["debug"] and self.Debug) + self.ParentButton.Enable(enabled and self.PouInfos.var_class != ITEM_CONFIGURATION) + self.DebugButton.Enable(enabled and self.PouInfos.debug and self.Debug) root = self.VariablesList.GetRootItem() if root is not None and root.IsOk(): @@ -307,29 +307,29 @@ item, item_cookie = self.VariablesList.GetNextChild(root, item_cookie) def EditButtonCallback(self, infos): - var_class = infos["class"] + var_class = infos.var_class if var_class == ITEM_RESOURCE: tagname = self.Controller.ComputeConfigurationResourceName( self.InstanceChoice.GetStringSelection(), - infos["name"]) + infos.name) elif var_class == ITEM_TRANSITION: tagname = self.Controller.ComputePouTransitionName( self.PouTagName.split("::")[1], - infos["name"]) + infos.name) elif var_class == ITEM_ACTION: tagname = self.Controller.ComputePouActionName( self.PouTagName.split("::")[1], - infos["name"]) + infos.name) else: var_class = ITEM_POU - tagname = self.Controller.ComputePouName(infos["type"]) + tagname = self.Controller.ComputePouName(infos.type) self.ParentWindow.EditProjectElement(var_class, tagname) def DebugButtonCallback(self, infos): if self.InstanceChoice.GetSelection() != -1: - var_class = infos["class"] + var_class = infos.var_class var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), - infos["name"]) + infos.name) if var_class in ITEMS_VARIABLE: self.ParentWindow.AddDebugVariable(var_path, force=True) elif var_class == ITEM_TRANSITION: @@ -338,35 +338,35 @@ var_path, self.Controller.ComputePouTransitionName( self.PouTagName.split("::")[1], - infos["name"])) + infos.name)) elif var_class == ITEM_ACTION: self.ParentWindow.OpenDebugViewer( var_class, var_path, self.Controller.ComputePouActionName( self.PouTagName.split("::")[1], - infos["name"])) + infos.name)) else: self.ParentWindow.OpenDebugViewer( var_class, var_path, - self.Controller.ComputePouName(infos["type"])) + self.Controller.ComputePouName(infos.type)) def DebugButtonDClickCallback(self, infos): if self.InstanceChoice.GetSelection() != -1: - if infos["class"] in ITEMS_VARIABLE: + if infos.var_class in ITEMS_VARIABLE: self.ParentWindow.AddDebugVariable( "%s.%s" % (self.InstanceChoice.GetStringSelection(), - infos["name"]), + infos.name), force=True, graph=True) def GraphButtonCallback(self, infos): if self.InstanceChoice.GetSelection() != -1: - if infos["class"] in ITEMS_VARIABLE: + if infos.var_class in ITEMS_VARIABLE: var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), - infos["name"]) - self.ParentWindow.OpenDebugViewer(infos["class"], var_path, infos["type"]) + infos.name) + self.ParentWindow.OpenDebugViewer(infos.var_class, var_path, infos.type) def ShowInstanceChoicePopup(self): self.InstanceChoice.SetFocusFromKbd() @@ -395,7 +395,7 @@ def OnDebugButtonClick(self, event): if self.InstanceChoice.GetSelection() != -1: self.ParentWindow.OpenDebugViewer( - self.PouInfos["class"], + self.PouInfos.var_class, self.InstanceChoice.GetStringSelection(), self.PouTagName) event.Skip() @@ -413,20 +413,20 @@ if callback is not None: callback(item_infos) - elif item_infos["class"] not in ITEMS_VARIABLE: + elif item_infos.var_class not in ITEMS_VARIABLE: instance_path = self.InstanceChoice.GetStringSelection() - if item_infos["class"] == ITEM_RESOURCE: + if item_infos.var_class == ITEM_RESOURCE: if instance_path != "": tagname = self.Controller.ComputeConfigurationResourceName( instance_path, - item_infos["name"]) + item_infos.name) else: tagname = None else: - tagname = self.Controller.ComputePouName(item_infos["type"]) + tagname = self.Controller.ComputePouName(item_infos.type) if tagname is not None: if instance_path != "": - item_path = "%s.%s" % (instance_path, item_infos["name"]) + item_path = "%s.%s" % (instance_path, item_infos.name) else: item_path = None self.SetPouType(tagname, item_path) @@ -450,10 +450,10 @@ if callback is not None: callback(item_infos) - elif flags & CT.TREE_HITTEST_ONITEMLABEL and item_infos["class"] in ITEMS_VARIABLE: + elif flags & CT.TREE_HITTEST_ONITEMLABEL and item_infos.var_class in ITEMS_VARIABLE: self.ParentWindow.EnsureTabVisible( self.ParentWindow.DebugVariablePanel) - item_path = "%s.%s" % (instance_path, item_infos["name"]) + item_path = "%s.%s" % (instance_path, item_infos.name) data = wx.TextDataObject(str((item_path, "debug"))) dragSource = wx.DropSource(self.VariablesList) dragSource.SetData(data) diff -r 533741e5075c -r aee0a7eb833a plcopen/pou_variables.xslt --- a/plcopen/pou_variables.xslt Wed Oct 09 10:57:20 2013 +0200 +++ b/plcopen/pou_variables.xslt Wed Oct 09 22:00:23 2013 +0200 @@ -1,174 +1,299 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + - - - - True - True - - - - - + + + + + + + + + + + + + + + - - - None - True - True - - - - + + + + action + + + + + - - - None - True - True - - - - + + + + transition + + + + + - - - None - True - False - - - - - + + + + configuration + + + false + + + + + + + + - - - None - True - False - - - - - + + + + resource + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + Local + - - + + + + Global + - - + + + + External + - - + + + + Temp + - - + + + + Input + - - + + + + Output + - - - - - - - - - - - - - - - - - - - - - - - - - - - None - True - True - - - - - - - None - True - True - - - - - - - None - True - False - - - - - - - - True - True - - - + + + + InOut + + + + + + + + + + true + + + true + + + + + + + + + + + action + + + + + + + + + + + transition + + + + + + + + + + + resource + + + false + + + + + + + + + + + program + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + - + + - + + - + + ARRAY [ @@ -176,44 +301,78 @@ ] OF - - - + + + + + + STRING - + + WSTRING - + + - - - - - - - - False - - - - - - True - - - False - - - False - - - True - - - - - - - \ No newline at end of file + + + + + + + + + true + + + false + + + + + + + + + + + + false + + + + + + + + + + + + + + + false + + + + + + true + + + + false + + + + false + + + + true + + diff -r 533741e5075c -r aee0a7eb833a plcopen/pou_variables.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plcopen/pou_variables.ysl2 Wed Oct 09 22:00:23 2013 +0200 @@ -0,0 +1,279 @@ +include yslt.yml2 +estylesheet xmlns:ppx="http://www.plcopen.org/xml/tc6_0201" + xmlns:xhtml="http://www.w3.org/1999/xhtml" + xmlns:ns="pou_vars_ns" + extension-element-prefixes="ns" + exclude-result-prefixes="ns" { + + template "text()"; + template "text()", mode="var_class"; + template "text()", mode="var_type"; + template "text()", mode="var_edit"; + template "text()", mode="var_debug"; + + variable "project" { + copy "document('project')/project/*"; + } + + variable "stdlib" { + copy "document('stdlib')/stdlib/*"; + } + variable "extensions" { + copy "document('extensions')/extensions/*"; + } + + function "add_root" { + param "class"; + param "type"; + param "edit" > true + param "debug" > true + value "ns:SetRoot($class, $type, $edit, $debug)"; + } + + template "ppx:pou" { + call "add_root" { + with "class" > «@pouType» + with "type" > «@name» + } + apply "ppx:interface"; + apply "ppx:actions/ppx:action | ppx:transitions/ppx:transition", mode="variable_list"; + } + + template "ppx:action" { + call "add_root" { + with "class" > action + } + apply "ancestor::ppx:pou/child::ppx:interface"; + } + + template "ppx:transition" { + call "add_root" { + with "class" > transition + } + apply "ancestor::ppx:pou/child::ppx:interface"; + } + + template "ppx:configuration" { + call "add_root" { + with "class" > configuration + with "debug" > false + } + apply "ppx:resource", mode="variable_list"; + apply "ppx:globalVars"; + } + + template "ppx:resource" { + call "add_root" { + with "class" > resource + with "debug" > false + } + apply "ppx:pouInstance | ppx:task/ppx:pouInstance", mode="variable_list"; + apply "ppx:globalVars"; + } + + function "variables_infos" { + param "var_class"; + foreach "ppx:variable" { + variable "class" { + apply "ppx:type", mode="var_class" { + with "default_class" > «$var_class» + } + } + variable "type" { + apply"ppx:type", mode="var_type"; + } + variable "edit" { + apply "ppx:type", mode="var_edit"; + } + variable "debug" { + apply "ppx:type", mode="var_debug"; + } + value "ns:AddVariable(@name, $class, $type, $edit, $debug)"; + } + } + + template "ppx:localVars" { + call "variables_infos" { + with "var_class" > Local + } + } + + template "ppx:globalVars" { + call "variables_infos" { + with "var_class" > Global + } + } + + template "ppx:externalVars" { + call "variables_infos" { + with "var_class" > External + } + } + + template "ppx:tempVars" { + call "variables_infos" { + with "var_class" > Temp + } + } + + template "ppx:inputVars" { + call "variables_infos" { + with "var_class" > Input + } + } + + template "ppx:outputVars" { + call "variables_infos" { + with "var_class" > Output + } + } + + template "ppx:inOutVars" { + call "variables_infos" { + with "var_class" > InOut + } + } + + function "add_variable" { + param "name"; + param "class"; + param "type"; + param "edit" > true + param "debug" > true + value "ns:AddVariable($name, $class, $type, $edit, $debug)"; + } + + template "ppx:action", mode="variable_list" { + call "add_variable" { + with "name" > «@name» + with "class" > action + } + } + + template "ppx:transition", mode="variable_list" { + call "add_variable" { + with "name" > «@name» + with "class" > transition + } + } + + template "ppx:resource", mode="variable_list" { + call "add_variable" { + with "name" > «@name» + with "class" > resource + with "debug" > false + } + } + + template "ppx:pouInstance", mode="variable_list" { + call "add_variable" { + with "name" > «@name» + with "class" > program + with "type" > «@typeName» + } + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_class" { + param "default_class"; + variable "type_name", "@name"; + variable "pou_infos" { + copy """exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] | + exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] | + exsl:node-set($extensions)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]"""; + } + choose { + when "$pou_infos != ''" { + apply "exsl:node-set($pou_infos)", mode="var_class"; + } + otherwise { + value "$default_class" + } + } + } + + template "ppx:pou", mode="var_class" { + value "@pouType"; + } + + template "*[self::ppx:type or self::ppx:baseType]/*" mode="var_class" { + param "default_class"; + value "$default_class"; + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_type" { + > «@name» + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:array", mode="var_type" { + > ARRAY [ + foreach "ppx:dimension" { + > «@lower»..«@upper» + } + > ] OF + apply "ppx:baseType", mode="var_type"; + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:string", mode="var_type" { + > STRING + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:wstring", mode="var_type" { + > WSTRING + } + + template "*[self::ppx:type or self::ppx:baseType]/*", mode="var_type" { + > «local-name()» + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_edit" { + variable "type_name", "@name"; + variable "pou_infos" { + copy "exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name]"; + } + choose { + when "$pou_infos != ''" > true + otherwise > false + } + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:array", mode="var_edit" { + apply "ppx:baseType", mode="var_edit"; + } + + template "*[self::ppx:type or self::ppx:baseType]/*", mode="var_edit" { + > false + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:derived", mode="var_debug" { + variable "type_name", "@name"; + variable "datatype_infos" { + copy """exsl:node-set($project)/ppx:project/ppx:types/ppx:pous/ppx:pou[@name=$type_name] | + exsl:node-set($project)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] | + exsl:node-set($stdlib)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name] | + exsl:node-set($extensions)/ppx:project/ppx:types/ppx:dataTypes/ppx:dataType[@name=$type_name]"""; + } + choose { + when "$datatype_infos != ''" { + apply "exsl:node-set($datatype_infos)", mode="var_debug"; + } + otherwise > false + } + } + + template "ppx:pou", mode="var_debug" { + > true + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:array", mode="var_debug" { + > false + } + + template "*[self::ppx:type or self::ppx:baseType]/ppx:struct", mode="var_debug" { + > false + } + + template "*[self::ppx:type or self::ppx:baseType]/*", mode="var_debug" { + > true + } + +}