# HG changeset patch # User laurent # Date 1337359789 -7200 # Node ID f10449b18dbed636b27a7e7b8891d6f5193ab44f # Parent 37882f34f9cbf8b84d42875d5586b9512067b218 refactoring diff -r 37882f34f9cb -r f10449b18dbe Images/custom_tree_background.png Binary file Images/custom_tree_background.png has changed diff -r 37882f34f9cb -r f10449b18dbe Images/debug.png Binary file Images/debug.png has changed diff -r 37882f34f9cb -r f10449b18dbe Images/edit.png Binary file Images/edit.png has changed diff -r 37882f34f9cb -r f10449b18dbe Images/graph.png Binary file Images/graph.png has changed diff -r 37882f34f9cb -r f10449b18dbe Images/icons.svg --- a/Images/icons.svg Sat May 12 12:33:17 2012 +0200 +++ b/Images/icons.svg Fri May 18 18:49:49 2012 +0200 @@ -23,2498 +23,6524 @@ sodipodi:docname="icons.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="defs4"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %%custom_tree_background%% + + + + + + + + + + + %%up%% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %%edit%% + + + + + + + + + + + + + + + + + + + + %%debug%% + + + + + + + + + + + + + + + + + + + + + + + + + %%graph%% diff -r 37882f34f9cb -r f10449b18dbe Images/up.png Binary file Images/up.png has changed diff -r 37882f34f9cb -r f10449b18dbe PLCControler.py --- a/PLCControler.py Sat May 12 12:33:17 2012 +0200 +++ b/PLCControler.py Fri May 18 18:49:49 2012 +0200 @@ -75,6 +75,11 @@ "InOut" : (plcopen.interface_inOutVars, ITEM_VAR_INOUT) } +POU_TYPES = {"program": ITEM_PROGRAM, + "functionBlock": ITEM_FUNCTIONBLOCK, + "function": ITEM_FUNCTION, + } + LOCATIONS_ITEMS = [LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, @@ -376,12 +381,259 @@ resources["values"].append(resource_infos) config_infos["values"] = [resources] configurations["values"].append(config_infos) - infos["values"] = [{"name": PROPERTIES, "type": ITEM_PROPERTIES, "values": []}, - datatypes, pou_types["function"], pou_types["functionBlock"], + infos["values"] = [datatypes, pou_types["function"], pou_types["functionBlock"], pou_types["program"], configurations] return infos return None + def GetPouVariableInfos(self, project, variable, var_class, debug=False): + vartype_content = variable.gettype().getcontent() + if vartype_content["name"] == "derived": + var_type = vartype_content["value"].getname() + pou_type = None + pou = project.getpou(var_type) + if pou is not None: + pou_type = pou.getpouType() + edit = debug = pou_type is not None + if pou_type is None: + block_infos = self.GetBlockType(var_type, debug = debug) + pou_type = block_infos["type"] + if pou_type is not None: + var_class = None + if pou_type == "program": + var_class = ITEM_PROGRAM + elif pou_type != "function": + var_class = ITEM_FUNCTIONBLOCK + if var_class is not None: + return {"name": variable.getname(), + "type": var_type, + "class": var_class, + "edit": edit, + "debug": debug} + elif var_type in self.GetDataTypes(debug = debug): + return {"name": variable.getname(), + "type": var_type, + "class": var_class, + "edit": False, + "debug": False} + elif vartype_content["name"] in ["string", "wstring"]: + return {"name": variable.getname(), + "type": vartype_content["name"].upper(), + "class": var_class, + "edit": False, + "debug": True} + else: + return {"name": variable.getname(), + "type": vartype_content["name"], + "class": var_class, + "edit": False, + "debug": True} + return None + + def GetPouVariables(self, tagname, debug = False): + vars = [] + pou_type = None + project = self.GetProject(debug) + if project is not None: + words = tagname.split("::") + if words[0] == "P": + pou = project.getpou(words[1]) + if pou is not None: + pou_type = pou.getpouType() + if (pou_type in ["program", "functionBlock"] and + pou.interface is not None): + # Extract variables from every varLists + for varlist_type, varlist in pou.getvars(): + var_infos = VAR_CLASS_INFOS.get(varlist_type, None) + if var_infos is not None: + var_class = var_infos[1] + else: + var_class = ITEM_VAR_LOCAL + for variable in varlist.getvariable(): + var_infos = self.GetPouVariableInfos(project, variable, var_class, debug) + if var_infos is not None: + vars.append(var_infos) + return {"class": POU_TYPES[pou_type], + "type": words[1], + "variables": vars, + "edit": True, + "debug": True} + else: + block_infos = self.GetBlockType(words[1], debug = debug) + if (block_infos is not None and + block_infos["type"] in ["program", "functionBlock"]): + for varname, vartype, varmodifier in block_infos["inputs"]: + vars.append({"name" : varname, + "type" : vartype, + "class" : ITEM_VAR_INPUT, + "edit": False, + "debug": True}) + for varname, vartype, varmodifier in block_infos["outputs"]: + vars.append({"name" : varname, + "type" : vartype, + "class" : ITEM_VAR_OUTPUT, + "edit": False, + "debug": True}) + return {"class": POU_TYPES[block_infos["type"]], + "type": None, + "variables": vars, + "edit": False, + "debug": False} + elif words[0] in ['C', 'R']: + if words[0] == 'C': + pou_type = ITEM_CONFIGURATION + element = project.getconfiguration(words[1]) + for resource in element.getresource(): + vars.append({"name": resource.getname(), + "type": None, + "class": ITEM_RESOURCE, + "edit": True, + "debug": False}) + elif words[0] == 'R': + pou_type = ITEM_RESOURCE + element = project.getconfigurationResource(words[1], words[2]) + for task in element.gettask(): + for pou in task.getpouInstance(): + vars.append({"name": pou.getname(), + "type": pou.gettypeName(), + "class": ITEM_PROGRAM, + "edit": True, + "debug": True}) + for pou in element.getpouInstance(): + vars.append({"name": pou.getname(), + "type": pou.gettypeName(), + "class": ITEM_PROGRAM, + "edit": True, + "debug": True}) + for varlist in element.getglobalVars(): + for variable in varlist.getvariable(): + var_infos = self.GetPouVariableInfos(project, variable, ITEM_VAR_GLOBAL, debug) + if var_infos is not None: + vars.append(var_infos) + return {"class": pou_type, + "type": None, + "variables": vars, + "edit": True, + "debug": False} + return None + + def RecursiveSearchPouInstances(self, project, pou_type, parent_path, varlists, debug = False): + instances = [] + for varlist in varlists: + for variable in varlist.getvariable(): + vartype_content = variable.gettype().getcontent() + if vartype_content["name"] == "derived": + var_path = "%s.%s" % (parent_path, variable.getname()) + var_type = vartype_content["value"].getname() + if var_type == pou_type: + instances.append(var_path) + else: + pou = project.getpou(var_type) + if pou is not None: + instances.extend( + self.RecursiveSearchPouInstances( + project, pou_type, var_path, + [varlist for type, varlist in pou.getvars()], + debug)) + return instances + + def SearchPouInstances(self, tagname, debug = False): + project = self.GetProject(debug) + if project is not None: + words = tagname.split("::") + if words[0] == "P": + instances = [] + for config in project.getconfigurations(): + config_name = config.getname() + instances.extend( + self.RecursiveSearchPouInstances( + project, words[1], config_name, + config.getglobalVars(), debug)) + for resource in config.getresource(): + res_path = "%s.%s" % (config_name, resource.getname()) + instances.extend( + self.RecursiveSearchPouInstances( + project, words[1], res_path, + resource.getglobalVars(), debug)) + pou_instances = resource.getpouInstance()[:] + for task in resource.gettask(): + pou_instances.extend(task.getpouInstance()) + for pou_instance in pou_instances: + pou_path = "%s.%s" % (res_path, pou_instance.getname()) + pou_type = pou_instance.gettypeName() + if pou_type == words[1]: + instances.append(pou_path) + pou = project.getpou(pou_type) + if pou is not None: + instances.extend( + self.RecursiveSearchPouInstances( + project, words[1], pou_path, + [varlist for type, varlist in pou.getvars()], + debug)) + return instances + elif words[0] == 'C': + return [words[1]] + elif words[0] == 'R': + return ["%s.%s" % (words[1], words[2])] + return [] + + def RecursiveGetPouInstanceTagname(self, project, pou_type, parts): + pou = project.getpou(pou_type) + if pou is not None: + if len(parts) == 0: + return self.ComputePouName(pou_type) + + for varlist_type, varlist in pou.getvars(): + for variable in varlist.getvariable(): + vartype_content = variable.gettype().getcontent() + if vartype_content["name"] == "derived": + return self.RecursiveGetPouInstanceTagname( + project, + vartype_content["value"].getname(), + parts[1:]) + return None + + def GetPouInstanceTagname(self, instance_path, debug = False): + parts = instance_path.split(".") + if len(parts) == 1: + return self.ComputeConfigurationName(parts[0]) + elif len(parts) == 2: + return self.ComputeConfigurationResourceName(parts[0], parts[1]) + else: + project = self.GetProject(debug) + for config in project.getconfigurations(): + if config.getname() == parts[0]: + for resource in config.getresource(): + if resource.getname() == parts[1]: + pou_instances = resource.getpouInstance()[:] + for task in resource.gettask(): + pou_instances.extend(task.getpouInstance()) + for pou_instance in pou_instances: + if pou_instance.getname() == parts[2]: + if len(parts) == 3: + return self.ComputePouName( + pou_instance.gettypeName()) + else: + return self.RecursiveGetPouInstanceTagname( + project, + pou_instance.gettypeName(), + parts[3:]) + return None + + def GetInstanceInfos(self, instance_path): + tagname = self.GetPouInstanceTagName(instance_path) + if tagname is not None: + return self.Controler.GetPouVariables(tagname, self.Debug) + else: + pou_path, var_name = tagname.rsplit(".", 1) + tagname = self.Controler.GetPouInstanceTagName(pou_path) + if tagname is not None: + pou_infos = self.Controler.GetPouVariables(tagname, self.Debug) + for var_infos in pou_infos["variables"]: + if var_infos["name"] == var_name: + return var_infos + return None + # Return project topology informations def GetProjectTopology(self, debug = False): project = self.GetProject(debug) @@ -495,7 +747,7 @@ for varname, vartype, varmodifier in block_infos["inputs"]: pou_infos["values"].append({"name" : varname, "elmt_type" : vartype, "type" : ITEM_VAR_INPUT, "values" : []}) for varname, vartype, varmodifier in block_infos["outputs"]: - pou_infos["values"].append({"name" : varname, "elmt_type" : vartype, "type" : ITEM_VAR_INPUT, "values" : []}) + pou_infos["values"].append({"name" : varname, "elmt_type" : vartype, "type" : ITEM_VAR_OUTPUT, "values" : []}) return pou_infos if type in self.GetDataTypes(debug = debug): @@ -2739,7 +2991,7 @@ for child in tree.childNodes: if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "project": try: - result = self.Project.loadXMLTree(child, ["xmlns", "xmlns:xhtml", "xmlns:xsi", "xsi:schemaLocation"]) + result = self.Project.loadXMLTree(child) except ValueError, e: return _("Project file syntax error:\n\n") + str(e) self.SetFilePath(filepath) diff -r 37882f34f9cb -r f10449b18dbe PLCGenerator.py --- a/PLCGenerator.py Sat May 12 12:33:17 2012 +0200 +++ b/PLCGenerator.py Fri May 18 18:49:49 2012 +0200 @@ -821,6 +821,7 @@ otherInstances["outVariables&coils"].append(instance) orderedInstances.sort() otherInstances["outVariables&coils"].sort(SortInstances) + otherInstances["blocks"].sort(SortInstances) instances = [instance for (executionOrderId, instance) in orderedInstances] instances.extend(otherInstances["connectors"] + otherInstances["outVariables&coils"] + otherInstances["blocks"]) for instance in instances: diff -r 37882f34f9cb -r f10449b18dbe PLCOpenEditor.py --- a/PLCOpenEditor.py Sat May 12 12:33:17 2012 +0200 +++ b/PLCOpenEditor.py Fri May 18 18:49:49 2012 +0200 @@ -114,18 +114,18 @@ from DataTypeEditor import * from PLCControler import * from SearchResultPanel import SearchResultPanel -from controls import CustomGrid, CustomTable, LibraryPanel +from controls import CustomGrid, CustomTable, CustomTree, LibraryPanel, PouInstanceVariablesPanel # Define PLCOpenEditor controls id [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, - ID_PLCOPENEDITORTYPESTREE, ID_PLCOPENEDITORINSTANCESTREE, - ID_PLCOPENEDITORMAINSPLITTER, ID_PLCOPENEDITORSECONDSPLITTER, - ID_PLCOPENEDITORTHIRDSPLITTER, ID_PLCOPENEDITORLIBRARYPANEL, - ID_PLCOPENEDITORLIBRARYSEARCHCTRL, ID_PLCOPENEDITORLIBRARYTREE, - ID_PLCOPENEDITORLIBRARYCOMMENT, ID_PLCOPENEDITORTABSOPENED, - ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITOREDITORMENUTOOLBAR, - ID_PLCOPENEDITOREDITORTOOLBAR, + ID_PLCOPENEDITORPROJECTTREE, ID_PLCOPENEDITORMAINSPLITTER, + ID_PLCOPENEDITORSECONDSPLITTER, ID_PLCOPENEDITORTHIRDSPLITTER, + ID_PLCOPENEDITORLIBRARYPANEL, ID_PLCOPENEDITORLIBRARYSEARCHCTRL, + ID_PLCOPENEDITORLIBRARYTREE, ID_PLCOPENEDITORLIBRARYCOMMENT, + ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTABSOPENED, + ID_PLCOPENEDITOREDITORMENUTOOLBAR, ID_PLCOPENEDITOREDITORTOOLBAR, + ID_PLCOPENEDITORPROJECTPANEL, ] = [wx.NewId() for _init_ctrls in range(17)] # Define PLCOpenEditor FileMenu extra items id @@ -270,8 +270,8 @@ else: parent.Append(helpString=help, id=id, kind=kind, item=text) -[TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, - INSTANCESTREE, LIBRARYTREE, SCALING, PAGETITLES +[TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, + POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES ] = range(10) def GetShortcutKeyCallbackFunction(viewer_function): @@ -295,10 +295,10 @@ def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None): def DeleteElementFunction(self, selected): - name = self.TypesTree.GetItemText(selected) + name = self.ProjectTree.GetItemText(selected) if check_function is None or not check_function(self.Controler, name): if parent_type is not None: - parent_name = GetParentName(self.TypesTree, selected, parent_type) + parent_name = GetParentName(self.ProjectTree, selected, parent_type) remove_function(self.Controler, parent_name, name) else: remove_function(self.Controler, name) @@ -412,6 +412,18 @@ def _init_coll_FileMenu_Items(self, parent): pass + def _init_coll_AddMenu_Items(self, parent): + AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE, + kind=wx.ITEM_NORMAL, text=_(u'&Data Type')) + AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION, + kind=wx.ITEM_NORMAL, text=_(u'&Function')) + AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, + kind=wx.ITEM_NORMAL, text=_(u'Function &Block')) + AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM, + kind=wx.ITEM_NORMAL, text=_(u'&Program')) + AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION, + kind=wx.ITEM_NORMAL, text=_(u'&Configuration')) + def _init_coll_EditMenu_Items(self, parent): AppendMenu(parent, help='', id=wx.ID_UNDO, kind=wx.ITEM_NORMAL, text=_(u'Undo\tCTRL+Z')) @@ -431,18 +443,9 @@ AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, kind=wx.ITEM_NORMAL, text=_(u'Search in Project\tCTRL+F')) parent.AppendSeparator() - addmenu = wx.Menu(title='') - parent.AppendMenu(wx.ID_ADD, _(u"&Add Element"), addmenu) - AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE, - kind=wx.ITEM_NORMAL, text=_(u'&Data Type')) - AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION, - kind=wx.ITEM_NORMAL, text=_(u'&Function')) - AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, - kind=wx.ITEM_NORMAL, text=_(u'Function &Block')) - AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM, - kind=wx.ITEM_NORMAL, text=_(u'&Program')) - AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION, - kind=wx.ITEM_NORMAL, text=_(u'&Configuration')) + add_menu = wx.Menu(title='') + self._init_coll_AddMenu_Items(add_menu) + parent.AppendMenu(wx.ID_ADD, _(u"&Add Element"), add_menu) AppendMenu(parent, help='', id=wx.ID_SELECTALL, kind=wx.ITEM_NORMAL, text=_(u'Select All\tCTRL+A')) AppendMenu(parent, help='', id=wx.ID_DELETE, @@ -546,7 +549,7 @@ self.OnAllowNotebookDnD) self.AUIManager.AddPane(self.LeftNoteBook, wx.aui.AuiPaneInfo().Name("ProjectPane"). - Caption(_("Project")).Left().Layer(1). + Left().Layer(1). BestSize(wx.Size(300, 500)).CloseButton(False)) self.BottomNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORBOTTOMNOTEBOOK, @@ -638,56 +641,52 @@ self.MainTabs = {} - self.TypesTree = wx.TreeCtrl(id=ID_PLCOPENEDITORTYPESTREE, - name='TypesTree', parent=self.LeftNoteBook, + self.ProjectPanel = wx.SplitterWindow(id=ID_PLCOPENEDITORPROJECTPANEL, + name='ProjectPanel', parent=self.LeftNoteBook, point=wx.Point(0, 0), + size=wx.Size(0, 0), style=wx.SP_3D) + + self.ProjectTree = CustomTree(id=ID_PLCOPENEDITORPROJECTTREE, + name='ProjectTree', parent=self.ProjectPanel, pos=wx.Point(0, 0), size=wx.Size(0, 0), style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_EDIT_LABELS) + self.ProjectTree.SetBackgroundBitmap(wx.Bitmap(os.path.join(CWD, 'Images', 'custom_tree_background.png')), + wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM) + add_menu = wx.Menu() + self._init_coll_AddMenu_Items(add_menu) + self.ProjectTree.SetAddMenu(add_menu) if wx.Platform == '__WXMSW__': - self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnTypesTreeRightUp, - id=ID_PLCOPENEDITORTYPESTREE) - self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTypesTreeItemSelected, - id=ID_PLCOPENEDITORTYPESTREE) + self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnProjectTreeRightUp, + id=ID_PLCOPENEDITORPROJECTTREE) + self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnProjectTreeItemSelected, + id=ID_PLCOPENEDITORPROJECTTREE) else: if wx.VERSION >= (2, 6, 0): - self.TypesTree.Bind(wx.EVT_RIGHT_UP, self.OnTypesTreeRightUp) - self.TypesTree.Bind(wx.EVT_LEFT_UP, self.OnTypesTreeLeftUp) + self.ProjectTree.Bind(wx.EVT_RIGHT_UP, self.OnProjectTreeRightUp) + self.ProjectTree.Bind(wx.EVT_LEFT_UP, self.OnProjectTreeLeftUp) else: - wx.EVT_RIGHT_UP(self.TypesTree, self.OnTypesTreeRightUp) - wx.EVT_LEFT_UP(self.TypesTree, self.OnTypesTreeLeftUp) - self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnTypesTreeItemChanging, - id=ID_PLCOPENEDITORTYPESTREE) - self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnTypesTreeBeginDrag, - id=ID_PLCOPENEDITORTYPESTREE) - self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTypesTreeItemBeginEdit, - id=ID_PLCOPENEDITORTYPESTREE) - self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTypesTreeItemEndEdit, - id=ID_PLCOPENEDITORTYPESTREE) - self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTypesTreeItemActivated, - id=ID_PLCOPENEDITORTYPESTREE) - - self.MainTabs["TypesTree"] = (self.TypesTree, _("Types")) - self.LeftNoteBook.AddPage(*self.MainTabs["TypesTree"]) + wx.EVT_RIGHT_UP(self.ProjectTree, self.OnProjectTreeRightUp) + wx.EVT_LEFT_UP(self.ProjectTree, self.OnProjectTreeLeftUp) + self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnProjectTreeItemChanging, + id=ID_PLCOPENEDITORPROJECTTREE) + self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnProjectTreeBeginDrag, + id=ID_PLCOPENEDITORPROJECTTREE) + self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnProjectTreeItemBeginEdit, + id=ID_PLCOPENEDITORPROJECTTREE) + self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnProjectTreeItemEndEdit, + id=ID_PLCOPENEDITORPROJECTTREE) + self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnProjectTreeItemActivated, + id=ID_PLCOPENEDITORPROJECTTREE) #----------------------------------------------------------------------- - # Creating PLCopen Project Instances Tree + # Creating PLCopen Project POU Instance Variables Panel #----------------------------------------------------------------------- - self.InstancesTree = wx.TreeCtrl(id=ID_PLCOPENEDITORINSTANCESTREE, - name='InstancesTree', parent=self.LeftNoteBook, - pos=wx.Point(0, 0), size=wx.Size(0, 0), - style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) - if self.EnableDebug: - if wx.VERSION >= (2, 6, 0): - self.InstancesTree.Bind(wx.EVT_RIGHT_UP, self.OnInstancesTreeRightUp) - else: - wx.EVT_RIGHT_UP(self.InstancesTree, self.OnInstancesTreeRightUp) - self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnInstancesTreeBeginDrag, - id=ID_PLCOPENEDITORINSTANCESTREE) - self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnInstancesTreeItemActivated, - id=ID_PLCOPENEDITORINSTANCESTREE) - - self.MainTabs["InstancesTree"] = (self.InstancesTree, _("Instances")) - self.LeftNoteBook.AddPage(*self.MainTabs["InstancesTree"]) + self.PouInstanceVariablesPanel = PouInstanceVariablesPanel(self.ProjectPanel, self, self.Controler, self.EnableDebug) + + self.MainTabs["ProjectPanel"] = (self.ProjectPanel, _("Project")) + self.LeftNoteBook.AddPage(*self.MainTabs["ProjectPanel"]) + + self.ProjectPanel.SplitHorizontally(self.ProjectTree, self.PouInstanceVariablesPanel, 300) #----------------------------------------------------------------------- # Creating Tool Bar @@ -805,8 +804,8 @@ self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname))) # Assign icon list to TreeCtrls - self.TypesTree.SetImageList(self.TreeImageList) - self.InstancesTree.SetImageList(self.TreeImageList) + self.ProjectTree.SetImageList(self.TreeImageList) + self.PouInstanceVariablesPanel.SetTreeImageList(self.TreeImageList) self.CurrentEditorToolBar = [] self.CurrentMenu = None @@ -928,13 +927,9 @@ return notebook.GetPageIndex(page_ref) elif page_infos[0] == "debug": instance_path = page_infos[1] - item = self.GetInstancesTreeItem(self.InstancesTree.GetRootItem(), instance_path) - item_infos = self.InstancesTree.GetPyData(item) - if item_infos[1] is not None: - instance_type = item_infos[1] - else: - instance_type = self.InstancesTree.GetItemText(item).split(" (")[1].split(")")[0] - return notebook.GetPageIndex(self.OpenDebugViewer(item_infos[0], instance_path, instance_type)) + instance_infos = self.Controler.GetInstanceInfos(instance_path) + if instance_infos is not None: + return notebook.GetPageIndex(self.OpenDebugViewer(instance_infos["class"], instance_path, instance_infos["type"])) return None def LoadTabOrganization(self, notebook, tabs, mode="all", first_index=None): @@ -1093,8 +1088,8 @@ FILEMENU : self.RefreshFileMenu, EDITMENU : self.RefreshEditMenu, DISPLAYMENU : self.RefreshDisplayMenu, - TYPESTREE : self.RefreshTypesTree, - INSTANCESTREE : self.RefreshInstancesTree, + PROJECTTREE : self.RefreshProjectTree, + POUINSTANCEVARIABLESPANEL : self.RefreshPouInstanceVariablesPanel, LIBRARYTREE : self.RefreshLibraryPanel, SCALING : self.RefreshScaling, PAGETITLES: self.RefreshPageTitles} @@ -1149,7 +1144,7 @@ editor = self.TabsOpened.GetPage(i) editor.RefreshScaling() - def ShowProperties(self): + def EditProjectSettings(self): old_values = self.Controler.GetProjectProperties() dialog = ProjectDialog(self) dialog.SetValues(old_values) @@ -1159,7 +1154,7 @@ if new_values != old_values: self.Controler.SetProjectProperties(None, new_values) self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, - TYPESTREE, INSTANCESTREE, SCALING) + PROJECTTREE, POUINSTANCEVARIABLESPANEL, SCALING) dialog.Destroy() #------------------------------------------------------------------------------- @@ -1281,8 +1276,8 @@ def ResetView(self): self.DeleteAllPages() - self.TypesTree.DeleteAllItems() - self.InstancesTree.DeleteAllItems() + self.ProjectTree.DeleteAllItems() + self.PouInstanceVariablesPanel.ResetView() self.LibraryPanel.ResetTree() self.LibraryPanel.SetControler(None) self.Controler = None @@ -1429,7 +1424,7 @@ window.Undo() else: self.Controler.LoadPrevious() - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES) def OnRedoMenu(self, event): @@ -1439,7 +1434,7 @@ window.Redo() else: self.Controler.LoadNext() - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES) def OnEnableUndoRedoMenu(self, event): @@ -1472,16 +1467,16 @@ def OnDeleteMenu(self, event): window = self.FindFocus() - if window == self.TypesTree or window is None: - selected = self.TypesTree.GetSelection() + if window == self.ProjectTree or window is None: + selected = self.ProjectTree.GetSelection() if selected.IsOk(): - type = self.TypesTree.GetPyData(selected) + type = self.ProjectTree.GetPyData(selected) function = self.DeleteFunctions.get(type, None) if function is not None: function(self, selected) self.CloseTabsWithoutModel() - self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, TYPESTREE, - INSTANCESTREE, LIBRARYTREE) + self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, + POUINSTANCEVARIABLESPANEL, LIBRARYTREE) elif isinstance(window, (Viewer, TextViewer)): event = wx.KeyEvent(wx.EVT_CHAR._getEvtType()) event.m_keyCode = wx.WXK_DELETE @@ -1587,11 +1582,14 @@ selected = self.TabsOpened.GetSelection() if selected >= 0: window = self.TabsOpened.GetPage(selected) + tagname = window.GetTagName() if not window.IsDebugging(): - wx.CallAfter(self.SelectTypesTreeItem, window.GetTagName()) + wx.CallAfter(self.SelectProjectTreeItem, tagname) + wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname) window.RefreshView() else: - wx.CallAfter(self.SelectInstancesTreeItem, window.GetInstancePath()) + instance_path = window.GetInstancePath() + wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname, instance_path) wx.CallAfter(self._Refresh, FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR) event.Skip() @@ -1600,9 +1598,9 @@ if selected >= 0: window = self.TabsOpened.GetPage(selected) if not window.IsDebugging(): - self.SelectTypesTreeItem(window.GetTagName()) + self.SelectProjectTreeItem(window.GetTagName()) else: - self.SelectInstancesTreeItem(window.GetInstancePath()) + self.PouInstanceVariablesPanel.SetPouType(window.GetTagName(), window.GetInstancePath()) if USE_AUI: for child in self.TabsOpened.GetChildren(): if isinstance(child, wx.aui.AuiTabCtrl): @@ -1651,109 +1649,112 @@ # Types Tree Management Functions #------------------------------------------------------------------------------- - def RefreshTypesTree(self): + def RefreshProjectTree(self): infos = self.Controler.GetProjectInfos() - root = self.TypesTree.GetRootItem() + root = self.ProjectTree.GetRootItem() if not root.IsOk(): - root = self.TypesTree.AddRoot(infos["name"]) - self.GenerateTypesTreeBranch(root, infos) - self.TypesTree.Expand(root) + root = self.ProjectTree.AddRoot(infos["name"]) + self.GenerateProjectTreeBranch(root, infos) + self.ProjectTree.Expand(root) def ResetSelectedItem(self): self.SelectedItem = None - def GenerateTypesTreeBranch(self, root, infos, topology=False): + def GenerateProjectTreeBranch(self, root, infos): to_delete = [] item_name = infos["name"] if infos["type"] in ITEMS_UNEDITABLE: - item_name = _(item_name) - self.TypesTree.SetItemText(root, item_name) - self.TypesTree.SetPyData(root, infos["type"]) + if len(infos["values"]) == 1: + return self.GenerateProjectTreeBranch(root, infos["values"][0]) + item_name = _(item_name) + self.ProjectTree.SetItemText(root, item_name) + self.ProjectTree.SetPyData(root, infos["type"]) highlight_colours = self.Highlights.get(infos.get("tagname", None), (wx.WHITE, wx.BLACK)) - self.TypesTree.SetItemBackgroundColour(root, highlight_colours[0]) - self.TypesTree.SetItemTextColour(root, highlight_colours[1]) + self.ProjectTree.SetItemBackgroundColour(root, highlight_colours[0]) + self.ProjectTree.SetItemTextColour(root, highlight_colours[1]) if infos["type"] == ITEM_POU: - self.TypesTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])]) + self.ProjectTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])]) else: - self.TypesTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) + self.ProjectTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) if wx.VERSION >= (2, 6, 0): - item, root_cookie = self.TypesTree.GetFirstChild(root) + item, root_cookie = self.ProjectTree.GetFirstChild(root) else: - item, root_cookie = self.TypesTree.GetFirstChild(root, 0) + item, root_cookie = self.ProjectTree.GetFirstChild(root, 0) for values in infos["values"]: - if not item.IsOk(): - item = self.TypesTree.AppendItem(root, "") - if wx.Platform != '__WXMSW__': - item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) - self.GenerateTypesTreeBranch(item, values) - item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) + if values["type"] not in ITEMS_UNEDITABLE or len(values["values"]) > 0: + if not item.IsOk(): + item = self.ProjectTree.AppendItem(root, "") + if wx.Platform != '__WXMSW__': + item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie) + self.GenerateProjectTreeBranch(item, values) + item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie) while item.IsOk(): to_delete.append(item) - item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) + item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie) for item in to_delete: - self.TypesTree.Delete(item) - - def SelectTypesTreeItem(self, tagname): - if self.TypesTree is not None: - root = self.TypesTree.GetRootItem() + self.ProjectTree.Delete(item) + + def SelectProjectTreeItem(self, tagname): + if self.ProjectTree is not None: + root = self.ProjectTree.GetRootItem() if root.IsOk(): words = tagname.split("::") if words[0] == "D": - return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_DATATYPE)]) + return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_DATATYPE)]) elif words[0] == "P": - return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU)]) + return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU)]) elif words[0] == "T": - return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)]) + return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)]) elif words[0] == "A": - return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)]) + return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)]) elif words[0] == "C": - return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)]) + return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)]) elif words[0] == "R": - return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)]) + return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)]) return False - def RecursiveTypesTreeItemSelection(self, root, items): + def RecursiveProjectTreeItemSelection(self, root, items): found = False if wx.VERSION >= (2, 6, 0): - item, root_cookie = self.TypesTree.GetFirstChild(root) + item, root_cookie = self.ProjectTree.GetFirstChild(root) else: - item, root_cookie = self.TypesTree.GetFirstChild(root, 0) + item, root_cookie = self.ProjectTree.GetFirstChild(root, 0) while item.IsOk() and not found: - if (self.TypesTree.GetItemText(item), self.TypesTree.GetPyData(item)) == items[0]: + if (self.ProjectTree.GetItemText(item), self.ProjectTree.GetPyData(item)) == items[0]: if len(items) == 1: self.SelectedItem = item - self.TypesTree.SelectItem(item) + self.ProjectTree.SelectItem(item) wx.CallAfter(self.ResetSelectedItem) return True else: - found = self.RecursiveTypesTreeItemSelection(item, items[1:]) + found = self.RecursiveProjectTreeItemSelection(item, items[1:]) else: - found = self.RecursiveTypesTreeItemSelection(item, items) - item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) + found = self.RecursiveProjectTreeItemSelection(item, items) + item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie) return found - def OnTypesTreeBeginDrag(self, event): + def OnProjectTreeBeginDrag(self, event): if wx.Platform == '__WXMSW__': self.SelectedItem = event.GetItem() - if self.SelectedItem is not None and self.TypesTree.GetPyData(self.SelectedItem) == ITEM_POU: - block_name = self.TypesTree.GetItemText(self.SelectedItem) + if self.SelectedItem is not None and self.ProjectTree.GetPyData(self.SelectedItem) == ITEM_POU: + block_name = self.ProjectTree.GetItemText(self.SelectedItem) block_type = self.Controler.GetPouType(block_name) if block_type != "program": data = wx.TextDataObject(str((block_name, block_type, ""))) - dragSource = wx.DropSource(self.TypesTree) + dragSource = wx.DropSource(self.ProjectTree) dragSource.SetData(data) dragSource.DoDragDrop() self.ResetSelectedItem() - def OnTypesTreeItemBeginEdit(self, event): + def OnProjectTreeItemBeginEdit(self, event): selected = event.GetItem() - if self.TypesTree.GetPyData(selected) in ITEMS_UNEDITABLE: + if self.ProjectTree.GetPyData(selected) in ITEMS_UNEDITABLE: event.Veto() else: event.Skip() - def OnTypesTreeItemEndEdit(self, event): + def OnProjectTreeItemEndEdit(self, event): message = None abort = False new_name = event.GetLabel() @@ -1764,8 +1765,8 @@ message = _("\"%s\" is a keyword. It can't be used!")%new_name else: item = event.GetItem() - old_name = self.TypesTree.GetItemText(item) - itemtype = self.TypesTree.GetPyData(item) + old_name = self.ProjectTree.GetItemText(item) + itemtype = self.ProjectTree.GetPyData(item) if itemtype == ITEM_PROJECT: self.Controler.SetProjectProperties(name = new_name) elif itemtype == ITEM_DATATYPE: @@ -1793,7 +1794,7 @@ self.RefreshLibraryPanel() self.RefreshPageTitles() elif itemtype == ITEM_TRANSITION: - pou_name = GetParentName(self.TypesTree, item, ITEM_POU) + pou_name = GetParentName(self.ProjectTree, item, ITEM_POU) if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: message = _("A POU named \"%s\" already exists!")%new_name elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]: @@ -1804,7 +1805,7 @@ self.Controler.ComputePouTransitionName(pou_name, new_name)) self.RefreshPageTitles() elif itemtype == ITEM_ACTION: - pou_name = GetParentName(self.TypesTree, item, ITEM_POU) + pou_name = GetParentName(self.ProjectTree, item, ITEM_POU) if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: message = _("A POU named \"%s\" already exists!")%new_name elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]: @@ -1834,7 +1835,7 @@ self.Controler.ComputeConfigurationName(new_name)) self.RefreshPageTitles() elif itemtype == ITEM_RESOURCE: - config_name = GetParentName(self.TypesTree, item, ITEM_CONFIGURATION) + config_name = GetParentName(self.ProjectTree, item, ITEM_CONFIGURATION) if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]: message = _("\"%s\" config already exists!")%new_name abort = True @@ -1857,31 +1858,31 @@ if message: self.ShowErrorMessage(message) item = event.GetItem() - wx.CallAfter(self.TypesTree.EditLabel, item) + wx.CallAfter(self.ProjectTree.EditLabel, item) event.Veto() else: - wx.CallAfter(self.RefreshTypesTree) + wx.CallAfter(self.RefreshProjectTree) self.RefreshEditor() self._Refresh(TITLE, FILEMENU, EDITMENU) event.Skip() - def OnTypesTreeItemActivated(self, event): + def OnProjectTreeItemActivated(self, event): selected = event.GetItem() - name = self.TypesTree.GetItemText(selected) - data = self.TypesTree.GetPyData(selected) - if UNEDITABLE_NAMES_DICT.get(name, name) == "Properties": - self.ShowProperties() - if data == ITEM_DATATYPE: + name = self.ProjectTree.GetItemText(selected) + data = self.ProjectTree.GetPyData(selected) + if data == ITEM_PROJECT: + self.EditProjectSettings() + elif data == ITEM_DATATYPE: self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name)) elif data == ITEM_POU: self.EditProjectElement(data, self.Controler.ComputePouName(name)) elif data == ITEM_CONFIGURATION: self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name)) elif data == ITEM_RESOURCE: - config_name = GetParentName(self.TypesTree, selected, ITEM_CONFIGURATION) + config_name = GetParentName(self.ProjectTree, selected, ITEM_CONFIGURATION) self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name)) elif data in [ITEM_TRANSITION, ITEM_ACTION]: - pou_name = GetParentName(self.TypesTree, selected, ITEM_POU) + pou_name = GetParentName(self.ProjectTree, selected, ITEM_POU) if data == ITEM_TRANSITION: tagname = self.Controler.ComputePouTransitionName(pou_name, name) elif data == ITEM_ACTION: @@ -1889,39 +1890,42 @@ self.EditProjectElement(data, tagname) event.Skip() - def TypesTreeItemSelect(self, select_item): - name = self.TypesTree.GetItemText(select_item) - data = self.TypesTree.GetPyData(select_item) + def ProjectTreeItemSelect(self, select_item): + name = self.ProjectTree.GetItemText(select_item) + data = self.ProjectTree.GetPyData(select_item) + tagname = None if data == ITEM_DATATYPE: - self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name), True) + tagname = self.Controler.ComputeDataTypeName(name) elif data == ITEM_POU: - self.EditProjectElement(data, self.Controler.ComputePouName(name), True) + tagname = self.Controler.ComputePouName(name) elif data == ITEM_CONFIGURATION: - self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name), True) + tagname = self.Controler.ComputeConfigurationName(name) elif data == ITEM_RESOURCE: - config_name = GetParentName(self.TypesTree, select_item, ITEM_CONFIGURATION) - self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name), True) + config_name = GetParentName(self.ProjectTree, select_item, ITEM_CONFIGURATION) + tagname = self.Controler.ComputeConfigurationResourceName(config_name, name) elif data in [ITEM_TRANSITION, ITEM_ACTION]: - pou_name = GetParentName(self.TypesTree, select_item, ITEM_POU) + pou_name = GetParentName(self.ProjectTree, select_item, ITEM_POU) if data == ITEM_TRANSITION: tagname = self.Controler.ComputePouTransitionName(pou_name, name) elif data == ITEM_ACTION: tagname = self.Controler.ComputePouActionName(pou_name, name) + if tagname is not None: self.EditProjectElement(data, tagname, True) - - def OnTypesTreeLeftUp(self, event): + self.PouInstanceVariablesPanel.SetPouType(tagname) + + def OnProjectTreeLeftUp(self, event): if self.SelectedItem is not None: - self.TypesTree.SelectItem(self.SelectedItem) - self.TypesTreeItemSelect(self.SelectedItem) + self.ProjectTree.SelectItem(self.SelectedItem) + self.ProjectTreeItemSelect(self.SelectedItem) wx.CallAfter(self.ResetSelectedItem) event.Skip() - def OnTypesTreeItemSelected(self, event): - self.TypesTreeItemSelect(event.GetItem()) + def OnProjectTreeItemSelected(self, event): + self.ProjectTreeItemSelect(event.GetItem()) event.Skip() - def OnTypesTreeItemChanging(self, event): - if self.TypesTree.GetPyData(event.GetItem()) not in ITEMS_UNEDITABLE and self.SelectedItem is None: + def OnProjectTreeItemChanging(self, event): + if self.ProjectTree.GetPyData(event.GetItem()) not in ITEMS_UNEDITABLE and self.SelectedItem is None: self.SelectedItem = event.GetItem() event.Veto() else: @@ -2000,15 +2004,15 @@ self.RefreshPageTitles() return new_window - def OnTypesTreeRightUp(self, event): + def OnProjectTreeRightUp(self, event): if wx.Platform == '__WXMSW__': item = event.GetItem() else: - item, flags = self.TypesTree.HitTest(wx.Point(event.GetX(), event.GetY())) - self.TypesTree.SelectItem(item) - self.TypesTreeItemSelect(item) - name = self.TypesTree.GetItemText(item) - type = self.TypesTree.GetPyData(item) + item, flags = self.ProjectTree.HitTest(wx.Point(event.GetX(), event.GetY())) + self.ProjectTree.SelectItem(item) + self.ProjectTreeItemSelect(item) + name = self.ProjectTree.GetItemText(item) + type = self.ProjectTree.GetPyData(item) menu = None if type in ITEMS_UNEDITABLE: @@ -2043,34 +2047,34 @@ menu = wx.Menu(title='') new_id = wx.NewId() AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition")) - parent = self.TypesTree.GetItemParent(item) - parent_type = self.TypesTree.GetPyData(parent) + parent = self.ProjectTree.GetItemParent(item) + parent_type = self.ProjectTree.GetPyData(parent) while parent_type != ITEM_POU: - parent = self.TypesTree.GetItemParent(parent) - parent_type = self.TypesTree.GetPyData(parent) - self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.TypesTree.GetItemText(parent)), id=new_id) + parent = self.ProjectTree.GetItemParent(parent) + parent_type = self.ProjectTree.GetPyData(parent) + self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.ProjectTree.GetItemText(parent)), id=new_id) elif name == "Actions": menu = wx.Menu(title='') new_id = wx.NewId() AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action")) - parent = self.TypesTree.GetItemParent(item) - parent_type = self.TypesTree.GetPyData(parent) + parent = self.ProjectTree.GetItemParent(item) + parent_type = self.ProjectTree.GetPyData(parent) while parent_type != ITEM_POU: - parent = self.TypesTree.GetItemParent(parent) - parent_type = self.TypesTree.GetPyData(parent) - self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.TypesTree.GetItemText(parent)), id=new_id) + parent = self.ProjectTree.GetItemParent(parent) + parent_type = self.ProjectTree.GetPyData(parent) + self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.ProjectTree.GetItemText(parent)), id=new_id) elif name == "Resources": menu = wx.Menu(title='') new_id = wx.NewId() AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource")) - parent = self.TypesTree.GetItemParent(item) - parent_type = self.TypesTree.GetPyData(parent) + parent = self.ProjectTree.GetItemParent(item) + parent_type = self.ProjectTree.GetPyData(parent) while parent_type != ITEM_CONFIGURATION: - parent = self.TypesTree.GetItemParent(parent) - parent_type = self.TypesTree.GetPyData(parent) - self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(self.TypesTree.GetItemText(parent)), id=new_id) + parent = self.ProjectTree.GetItemParent(parent) + parent_type = self.ProjectTree.GetPyData(parent) + self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(self.ProjectTree.GetItemText(parent)), id=new_id) else: if type == ITEM_POU: @@ -2128,83 +2132,11 @@ # Instances Tree Management Functions #------------------------------------------------------------------------------- - def RefreshInstancesTree(self): - infos = self.Controler.GetProjectTopology(self.EnableDebug) - root = self.InstancesTree.GetRootItem() - if not root.IsOk(): - root = self.InstancesTree.AddRoot(infos["name"]) - self.GenerateInstancesTreeBranch(root, infos) - self.InstancesTree.Expand(root) - - def GenerateInstancesTreeBranch(self, root, infos): - to_delete = [] - if infos.get("elmt_type", None) is not None: - self.InstancesTree.SetItemText(root, "%s (%s)"%(infos["name"], infos["elmt_type"])) - else: - self.InstancesTree.SetItemText(root, infos["name"]) - self.InstancesTree.SetPyData(root, (infos["type"], infos.get("tagname", None))) - self.InstancesTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) - - if wx.VERSION >= (2, 6, 0): - item, root_cookie = self.InstancesTree.GetFirstChild(root) - else: - item, root_cookie = self.InstancesTree.GetFirstChild(root, 0) - for values in infos["values"]: - if not item.IsOk(): - item = self.InstancesTree.AppendItem(root, "") - if wx.Platform != '__WXMSW__': - item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) - self.GenerateInstancesTreeBranch(item, values) - item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) - while item.IsOk(): - to_delete.append(item) - item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) - for item in to_delete: - self.InstancesTree.Delete(item) - if infos["type"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]: - self.InstancesTree.Expand(root) - - def OnInstancesTreeBeginDrag(self, event): - if self.Controler.DebugAvailable(): - selected_item = event.GetItem() - selected_infos = self.InstancesTree.GetPyData(selected_item) - if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: - var_path = self.InstancesTree.GetItemText(selected_item).split(" (")[0] - parent_item = self.InstancesTree.GetItemParent(selected_item) - while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: - parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] - var_path = "%s.%s"%(parent_name, var_path) - parent_item = self.InstancesTree.GetItemParent(parent_item) - data = wx.TextDataObject(str((var_path, "debug"))) - dragSource = wx.DropSource(self.InstancesTree) - dragSource.SetData(data) - dragSource.DoDragDrop() - event.Skip() - else: - event.Veto() - - def OnInstancesTreeItemActivated(self, event): - if self.Controler.DebugAvailable(): - selected_item = event.GetItem() - selected_infos = self.InstancesTree.GetPyData(selected_item) - if selected_item is not None and ( - selected_infos[0] in [ITEM_FUNCTIONBLOCK, ITEM_PROGRAM, ITEM_TRANSITION, ITEM_ACTION] or - selected_infos[0] in ITEMS_VARIABLE): - - instance_path, var_type = self.InstancesTree.GetItemText(selected_item).split(" (") - if selected_infos[1] is not None: - instance_type = selected_infos[1] - else: - instance_type = var_type.split(")")[0] - parent_item = self.InstancesTree.GetItemParent(selected_item) - while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: - parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] - instance_path = "%s.%s"%(parent_name, instance_path) - parent_item = self.InstancesTree.GetItemParent(parent_item) - - self.OpenDebugViewer(selected_infos[0], instance_path, instance_type) - - event.Skip() + def GetTreeImage(self, var_class): + return self.TreeImageDict[var_class] + + def RefreshPouInstanceVariablesPanel(self): + self.PouInstanceVariablesPanel.RefreshView() def OpenDebugViewer(self, instance_category, instance_path, instance_type): openedidx = self.IsOpened(instance_path) @@ -2271,66 +2203,6 @@ self.RefreshPageTitles() return new_window - def OnInstancesTreeRightUp(self, event): - if self.Controler.DebugAvailable(): - if wx.Platform == '__WXMSW__': - selected_item = event.GetItem() - else: - selected_item = self.InstancesTree.GetSelection() - selected_infos = self.InstancesTree.GetPyData(selected_item) - if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: - var_path, var_type = self.InstancesTree.GetItemText(selected_item).split(" (") - var_type = var_type.split(")")[0] - - if self.Controler.IsOfType(var_type, "ANY_NUM", True) or\ - self.Controler.IsOfType(var_type, "ANY_BIT", True): - parent_item = self.InstancesTree.GetItemParent(selected_item) - while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: - parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] - var_path = "%s.%s"%(parent_name, var_path) - parent_item = self.InstancesTree.GetItemParent(parent_item) - - menu = wx.Menu(title='') - new_id = wx.NewId() - AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Graphic Panel")) - self.Bind(wx.EVT_MENU, self.AddVariableGraphicFunction(var_path), id=new_id) - new_id = wx.NewId() - AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("CSV Log")) - self.PopupMenu(menu) - event.Skip() - - def AddVariableGraphicFunction(self, iec_path): - def AddVariableGraphic(event): - self.OpenGraphicViewer(iec_path) - event.Skip() - return AddVariableGraphic - - def GetInstancesTreeItem(self, root, instancepath): - paths = instancepath.split(".", 1) - if wx.VERSION >= (2, 6, 0): - item, root_cookie = self.InstancesTree.GetFirstChild(root) - else: - item, root_cookie = self.InstancesTree.GetFirstChild(root, 0) - while item.IsOk(): - name = self.InstancesTree.GetItemText(item).split(" (")[0] - if name == paths[0]: - if len(paths) == 1: - return item - else: - return self.GetInstancesTreeItem(item, paths[1]) - item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) - return None - - def SelectInstancesTreeItem(self, instancepath): - if self.InstancesTree is not None: - root = self.InstancesTree.GetRootItem() - if root.IsOk(): - item = self.GetInstancesTreeItem(root, instancepath) - if item is not None: - self.InstancesTree.SelectItem(item) - return True - return False - def ResetGraphicViewers(self): for i in xrange(self.TabsOpened.GetPageCount()): editor = self.TabsOpened.GetPage(i) @@ -2341,18 +2213,11 @@ if self.EnableDebug: idxs = range(self.TabsOpened.GetPageCount()) idxs.reverse() - root = None - if self.InstancesTree is not None: - root = self.InstancesTree.GetRootItem() - if not root.IsOk(): - root = None for idx in idxs: editor = self.TabsOpened.GetPage(idx) if editor.IsDebugging(): - item = None - if root is not None: - item = self.GetInstancesTreeItem(root, editor.GetInstancePath()) - if item is None: + instance_infos = self.Controler.GetInstanceInfos(editor.GetInstancePath()) + if instance_infos is None: self.TabsOpened.DeletePage(idx) elif isinstance(editor, GraphicViewer): editor.ResetView(True) @@ -2360,9 +2225,9 @@ editor.RefreshView() self.DebugVariablePanel.UnregisterObsoleteData() - def AddDebugVariable(self, iec_path): + def AddDebugVariable(self, iec_path, force=False): if self.EnableDebug: - self.DebugVariablePanel.InsertValue(iec_path) + self.DebugVariablePanel.InsertValue(iec_path, force=force) #------------------------------------------------------------------------------- # Library Panel Management Function @@ -2603,7 +2468,7 @@ if dialog.ShowModal() == wx.ID_OK: tagname = self.Controler.ProjectAddDataType(dialog.GetValue()) if tagname is not None: - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE) self.EditProjectElement(ITEM_DATATYPE, tagname) dialog.Destroy() @@ -2616,7 +2481,7 @@ values = dialog.GetValues() tagname = self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"]) if tagname is not None: - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, LIBRARYTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE) self.EditProjectElement(ITEM_POU, tagname) dialog.Destroy() return OnAddPouMenu @@ -2630,7 +2495,7 @@ values = dialog.GetValues() tagname = self.Controler.ProjectAddPouTransition(pou_name, values["transitionName"], values["language"]) if tagname is not None: - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE) self.EditProjectElement(ITEM_TRANSITION, tagname) dialog.Destroy() return OnAddTransitionMenu @@ -2644,7 +2509,7 @@ values = dialog.GetValues() tagname = self.Controler.ProjectAddPouAction(pou_name, values["actionName"], values["language"]) if tagname is not None: - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE) self.EditProjectElement(ITEM_ACTION, tagname) dialog.Destroy() return OnAddActionMenu @@ -2657,7 +2522,7 @@ value = dialog.GetValue() tagname = self.Controler.ProjectAddConfiguration(value) if tagname is not None: - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL) self.EditProjectElement(ITEM_CONFIGURATION, tagname) dialog.Destroy() @@ -2670,22 +2535,22 @@ value = dialog.GetValue() tagname = self.Controler.ProjectAddConfigurationResource(config_name, value) if tagname is not None: - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL) self.EditProjectElement(ITEM_RESOURCE, tagname) dialog.Destroy() return OnAddResourceMenu def GenerateChangePouTypeFunction(self, name, new_type): def OnChangePouTypeMenu(event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_POU: + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_POU: self.Controler.ProjectChangePouType(name, new_type) - self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, TYPESTREE, LIBRARYTREE) + self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE) return OnChangePouTypeMenu def OnCopyPou(self, event): - selected = self.TypesTree.GetSelection() - pou_name = self.TypesTree.GetItemText(selected) + selected = self.ProjectTree.GetSelection() + pou_name = self.ProjectTree.GetItemText(selected) pou_xml = self.Controler.GetPouXml(pou_name) if pou_xml is not None: @@ -2693,9 +2558,9 @@ self._Refresh(EDITMENU) def OnPastePou(self, event): - selected = self.TypesTree.GetSelection() - - pou_type = self.TypesTree.GetItemText(selected) + selected = self.ProjectTree.GetSelection() + + pou_type = self.ProjectTree.GetItemText(selected) pou_type = UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs' pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type] @@ -2708,106 +2573,106 @@ message.ShowModal() message.Destroy() else: - self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, TYPESTREE, LIBRARYTREE) + self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE) #------------------------------------------------------------------------------- # Remove Project Elements Functions #------------------------------------------------------------------------------- def OnRemoveDataTypeMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_DATATYPE: - name = self.TypesTree.GetItemText(selected) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_DATATYPE: + name = self.ProjectTree.GetItemText(selected) if not self.Controler.DataTypeIsUsed(name): self.Controler.ProjectRemoveDataType(name) tagname = self.Controler.ComputeDataTypeName(name) idx = self.IsOpened(tagname) if idx is not None: self.TabsOpened.DeletePage(idx) - self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, TYPESTREE) + self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE) else: self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")) def OnRenamePouMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_POU: - wx.CallAfter(self.TypesTree.EditLabel, selected) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_POU: + wx.CallAfter(self.ProjectTree.EditLabel, selected) def OnRemovePouMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_POU: - name = self.TypesTree.GetItemText(selected) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_POU: + name = self.ProjectTree.GetItemText(selected) if not self.Controler.PouIsUsed(name): self.Controler.ProjectRemovePou(name) tagname = self.Controler.ComputePouName(name) idx = self.IsOpened(tagname) if idx is not None: self.TabsOpened.DeletePage(idx) - self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE) + self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) else: self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")) def OnRemoveTransitionMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_TRANSITION: - transition = self.TypesTree.GetItemText(selected) - item = self.TypesTree.GetItemParent(selected) - item_type = self.TypesTree.GetPyData(item) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_TRANSITION: + transition = self.ProjectTree.GetItemText(selected) + item = self.ProjectTree.GetItemParent(selected) + item_type = self.ProjectTree.GetPyData(item) while item_type != ITEM_POU: - item = self.TypesTree.GetItemParent(item) - item_type = self.TypesTree.GetPyData(item) - pou_name = self.TypesTree.GetItemText(item) + item = self.ProjectTree.GetItemParent(item) + item_type = self.ProjectTree.GetPyData(item) + pou_name = self.ProjectTree.GetItemText(item) self.Controler.ProjectRemovePouTransition(pou_name, transition) tagname = self.Controler.ComputePouTransitionName(pou_name, transition) idx = self.IsOpened(tagname) if idx is not None: self.TabsOpened.DeletePage(idx) - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE) def OnRemoveActionMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_ACTION: - action = self.TypesTree.GetItemText(selected) - item = self.TypesTree.GetItemParent(selected) - item_type = self.TypesTree.GetPyData(item) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_ACTION: + action = self.ProjectTree.GetItemText(selected) + item = self.ProjectTree.GetItemParent(selected) + item_type = self.ProjectTree.GetPyData(item) while item_type != ITEM_POU: - item = self.TypesTree.GetItemParent(item) - item_type = self.TypesTree.GetPyData(item) - pou_name = self.TypesTree.GetItemText(item) + item = self.ProjectTree.GetItemParent(item) + item_type = self.ProjectTree.GetPyData(item) + pou_name = self.ProjectTree.GetItemText(item) self.Controler.ProjectRemovePouAction(pou_name, action) tagname = self.Controler.ComputePouActionName(pou_name, action) idx = self.IsOpened(tagname) if idx is not None: self.TabsOpened.DeletePage(idx) - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE) def OnRemoveConfigurationMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_CONFIGURATION: - name = self.TypesTree.GetItemText(selected) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_CONFIGURATION: + name = self.ProjectTree.GetItemText(selected) self.Controler.ProjectRemoveConfiguration(name) tagname = self.Controler.ComputeConfigurationName(name) idx = self.IsOpened(tagname) if idx is not None: self.TabsOpened.DeletePage(idx) - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL) def OnRemoveResourceMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_RESOURCE: - resource = self.TypesTree.GetItemText(selected) - item = self.TypesTree.GetItemParent(selected) - item_type = self.TypesTree.GetPyData(item) + selected = self.ProjectTree.GetSelection() + if self.ProjectTree.GetPyData(selected) == ITEM_RESOURCE: + resource = self.ProjectTree.GetItemText(selected) + item = self.ProjectTree.GetItemParent(selected) + item_type = self.ProjectTree.GetPyData(item) while item_type != ITEM_CONFIGURATION: - item = self.TypesTree.GetItemParent(item) - item_type = self.TypesTree.GetPyData(item) - config_name = self.TypesTree.GetItemText(item) + item = self.ProjectTree.GetItemParent(item) + item_type = self.ProjectTree.GetPyData(item) + config_name = self.ProjectTree.GetItemText(item) self.Controler.ProjectRemoveConfigurationResource(config_name, resource) tagname = self.Controler.ComputeConfigurationResourceName(config_name, selected) idx = self.IsOpened(tagname) if idx is not None: self.TabsOpened.DeletePage(idx) - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL) def OnPLCOpenEditorMenu(self, event): wx.MessageBox(_("No documentation available.\nComing soon.")) @@ -2824,11 +2689,11 @@ #------------------------------------------------------------------------------- def ShowHighlight(self, infos, start, end, highlight_type): - self.SelectTypesTreeItem(infos[0]) + self.SelectProjectTreeItem(infos[0]) if infos[1] == "name": self.Highlights[infos[0]] = highlight_type - self.RefreshTypesTree() - self.TypesTree.Unselect() + self.RefreshProjectTree() + self.ProjectTree.Unselect() else: self.EditProjectElement(self.Controler.GetElementType(infos[0]), infos[0]) selected = self.TabsOpened.GetSelection() @@ -2847,7 +2712,7 @@ self.Highlights = {} else: self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.iteritems() if highlight != highlight_type]) - self.RefreshTypesTree() + self.RefreshProjectTree() for i in xrange(self.TabsOpened.GetPageCount()): viewer = self.TabsOpened.GetPage(i) viewer.ClearHighlights(highlight_type) @@ -2952,7 +2817,8 @@ result = self.Controler.OpenXMLFile(fileOpen) if result is None: self.LibraryPanel.SetControler(self.Controler) - self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE) + self.PouInstanceVariablesPanel.SetController(self.Controler) + self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) # Define PLCOpenEditor icon self.SetIcon(wx.Icon(os.path.join(CWD,"Images", "poe.ico"),wx.BITMAP_TYPE_ICO)) @@ -3042,7 +2908,7 @@ self.Controler = PLCControler() self.Controler.CreateNewProject(properties) self.LibraryPanel.SetControler(self.Controler) - self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, + self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) def OnOpenProjectMenu(self, event): @@ -3067,8 +2933,9 @@ result = self.Controler.OpenXMLFile(filepath) if result is None: self.LibraryPanel.SetControler(self.Controler) + self.PouInstanceVariablesPanel.SetController(self.Controler) self.LoadProjectOrganization() - self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE) + self._Refresh(PROJECTTREE, LIBRARYTREE) self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU) dialog.Destroy() diff -r 37882f34f9cb -r f10449b18dbe RessourceEditor.py --- a/RessourceEditor.py Sat May 12 12:33:17 2012 +0200 +++ b/RessourceEditor.py Fri May 18 18:49:49 2012 +0200 @@ -502,7 +502,7 @@ def OnInstancesGridCellChange(self, event): self.RefreshModel() - self.ParentWindow.RefreshInstancesTree() + self.ParentWindow.RefreshPouInstanceVariablesPanel() self.InstancesGrid.RefreshButtons() event.Skip() diff -r 37882f34f9cb -r f10449b18dbe TextViewer.py --- a/TextViewer.py Sat May 12 12:33:17 2012 +0200 +++ b/TextViewer.py Fri May 18 18:49:49 2012 +0200 @@ -247,7 +247,7 @@ return {"cursor_pos": self.Editor.GetCurrentPos()} def SetState(self, state): - self.Editor.GotoPos(state["cursor_pos"]) + self.Editor.GotoPos(state.get("cursor_pos", 0)) def OnModification(self, event): if not self.DisableEvents: diff -r 37882f34f9cb -r f10449b18dbe Viewer.py --- a/Viewer.py Sat May 12 12:33:17 2012 +0200 +++ b/Viewer.py Fri May 18 18:49:49 2012 +0200 @@ -1966,7 +1966,7 @@ self.RefreshScrollBars() self.RefreshVisibleElements() self.RefreshVariablePanel() - self.ParentWindow.RefreshInstancesTree() + self.ParentWindow.RefreshPouInstanceVariablesPanel() block.Refresh() dialog.Destroy() @@ -2277,7 +2277,7 @@ self.RefreshScrollBars() self.RefreshVisibleElements() self.RefreshVariablePanel() - self.ParentWindow.RefreshInstancesTree() + self.ParentWindow.RefreshPouInstanceVariablesPanel() if old_values["executionOrder"] != new_values["executionOrder"]: self.RefreshView() else: @@ -2690,7 +2690,7 @@ for element in elements: element.RefreshModel() wx.CallAfter(self.RefreshVariablePanel) - wx.CallAfter(self.ParentWindow.RefreshInstancesTree) + wx.CallAfter(self.ParentWindow.RefreshPouInstanceVariablesPanel) def DeleteVariable(self, variable): connectors = variable.GetConnectors() @@ -2828,7 +2828,7 @@ self.RefreshBuffer() self.RefreshScrollBars() self.RefreshVariablePanel() - self.ParentWindow.RefreshInstancesTree() + self.ParentWindow.RefreshPouInstanceVariablesPanel() self.RefreshRect(self.GetScrolledRect(rect), False) def Copy(self): @@ -2856,7 +2856,7 @@ self.RefreshBuffer() self.RefreshView(selection=result) self.RefreshVariablePanel() - self.ParentWindow.RefreshInstancesTree() + self.ParentWindow.RefreshPouInstanceVariablesPanel() else: message = wx.MessageDialog(self.Editor, result, "Error", wx.OK|wx.ICON_ERROR) message.ShowModal() diff -r 37882f34f9cb -r f10449b18dbe controls/CustomTable.py --- a/controls/CustomTable.py Sat May 12 12:33:17 2012 +0200 +++ b/controls/CustomTable.py Fri May 18 18:49:49 2012 +0200 @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + #This library is free software; you can redistribute it and/or #modify it under the terms of the GNU General Public #License as published by the Free Software Foundation; either diff -r 37882f34f9cb -r f10449b18dbe controls/CustomTree.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/controls/CustomTree.py Fri May 18 18:49:49 2012 +0200 @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +# +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#General Public License for more details. +# +#You should have received a copy of the GNU General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import wx + +class CustomTree(wx.TreeCtrl): + + def __init__(self, *args, **kwargs): + wx.TreeCtrl.__init__(self, *args, **kwargs) + self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) + + self.BackgroundBitmap = None + self.BackgroundAlign = wx.ALIGN_LEFT|wx.ALIGN_TOP + + self.AddMenu = None + + if wx.Platform == '__WXMSW__': + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) + else: + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_SIZE, self.OnResize) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + + def SetBackgroundBitmap(self, bitmap, align): + self.BackgroundBitmap = bitmap + self.BackgroundAlign = align + + def SetAddMenu(self, add_menu): + self.AddMenu = add_menu + + def GetBitmapRect(self): + client_size = self.GetClientSize() + bitmap_size = self.BackgroundBitmap.GetSize() + + if self.BackgroundAlign & wx.ALIGN_RIGHT: + x = client_size[0] - bitmap_size[0] + elif self.BackgroundAlign & wx.ALIGN_CENTER_HORIZONTAL: + x = (client_size[0] - bitmap_size[0]) / 2 + else: + x = 0 + + if self.BackgroundAlign & wx.ALIGN_BOTTOM: + y = client_size[1] - bitmap_size[1] + elif self.BackgroundAlign & wx.ALIGN_CENTER_VERTICAL: + y = (client_size[1] - bitmap_size[1]) / 2 + else: + y = 0 + + return wx.Rect(x, y, bitmap_size[0], bitmap_size[1]) + + def RefreshBackground(self, refresh_base=False): + dc = wx.ClientDC(self) + dc.Clear() + + bitmap_rect = self.GetBitmapRect() + dc.DrawBitmap(self.BackgroundBitmap, bitmap_rect.x, bitmap_rect.y) + + if refresh_base: + self.Refresh(False) + + def OnEraseBackground(self, event): + self.RefreshBackground(True) + + def OnLeftUp(self, event): + pos = event.GetPosition() + item, flags = self.HitTest(pos) + + bitmap_rect = self.GetBitmapRect() + if (bitmap_rect.InsideXY(pos.x, pos.y) or + flags & wx.TREE_HITTEST_NOWHERE) and self.AddMenu is not None: + self.PopupMenuXY(self.AddMenu, pos.x, pos.y) + event.Skip() + + def OnResize(self, event): + self.RefreshBackground(True) + event.Skip() + + def OnPaint(self, event): + self.RefreshBackground() + event.Skip() \ No newline at end of file diff -r 37882f34f9cb -r f10449b18dbe controls/PouInstanceVariablesPanel.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/controls/PouInstanceVariablesPanel.py Fri May 18 18:49:49 2012 +0200 @@ -0,0 +1,289 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor +#based on the plcopen standard. +# +#Copyright (C) 2012: Edouard TISSERANT and Laurent BESSARD +# +#See COPYING file for copyrights details. +# +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +# +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#General Public License for more details. +# +#You should have received a copy of the GNU General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import wx +import wx.lib.buttons +import wx.lib.agw.customtreectrl as CT + +from PLCControler import ITEMS_VARIABLE, ITEM_CONFIGURATION, ITEM_RESOURCE, ITEM_POU + +class PouInstanceVariablesPanel(wx.Panel): + + def __init__(self, parent, window, controller, debug): + wx.Panel.__init__(self, name='PouInstanceTreePanel', + parent=parent, pos=wx.Point(0, 0), + size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) + + self.ParentButton = wx.lib.buttons.GenBitmapButton( + name='ParentButton', parent=self, + bitmap=window.GenerateBitmap("up"), + pos=wx.Point(0, 0), size=wx.Size(28, 28), + style=wx.NO_BORDER) + self.Bind(wx.EVT_BUTTON, self.OnParentButtonClick, + self.ParentButton) + + self.InstanceChoice = wx.ComboBox(name='InstanceChoice', + parent=self, pos=wx.Point(0, 0), + size=wx.Size(0, 28), style=wx.CB_READONLY) + self.Bind(wx.EVT_COMBOBOX, self.OnInstanceChoiceChanged, + self.InstanceChoice) + + self.DebugButton = wx.lib.buttons.GenBitmapButton( + name='DebugButton', parent=self, + bitmap=window.GenerateBitmap("debug"), + pos=wx.Point(0, 0), size=wx.Size(28, 28), + style=wx.NO_BORDER) + self.Bind(wx.EVT_BUTTON, self.OnDebugButtonClick, + self.DebugButton) + + self.VariablesList = CT.CustomTreeCtrl( + name='VariablesList', parent=self, + pos=wx.Point(0, 0), size=wx.Size(0, 0), + style=wx.SUNKEN_BORDER, + agwStyle=CT.TR_NO_BUTTONS| + CT.TR_SINGLE| + CT.TR_HAS_VARIABLE_ROW_HEIGHT| + CT.TR_HIDE_ROOT| + CT.TR_LINES_AT_ROOT| + CT.TR_NO_LINES) + self.VariablesList.Bind(CT.EVT_TREE_ITEM_ACTIVATED, + self.OnVariablesListItemActivated) + + buttons_sizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0) + buttons_sizer.AddWindow(self.ParentButton, 0, border=0, flag=0) + buttons_sizer.AddWindow(self.InstanceChoice, 0, border=0, flag=wx.GROW) + buttons_sizer.AddWindow(self.DebugButton, 0, border=0, flag=0) + buttons_sizer.AddGrowableCol(1) + buttons_sizer.AddGrowableRow(0) + + main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + main_sizer.AddSizer(buttons_sizer, 0, border=0, flag=wx.GROW) + main_sizer.AddWindow(self.VariablesList, 0, border=0, flag=wx.GROW) + main_sizer.AddGrowableCol(0) + main_sizer.AddGrowableRow(1) + + self.SetSizer(main_sizer) + + self.ParentWindow = window + self.Controller = controller + self.Debug = debug + if not self.Debug: + self.DebugButton.Hide() + + self.PouTagName = None + self.PouInfos = None + self.PouInstance = None + + def __del__(self): + self.Controller = None + + def SetTreeImageList(self, tree_image_list): + self.VariablesList.SetImageList(tree_image_list) + + def SetController(self, controller): + self.Controller = controller + + def SetPouType(self, tagname, pou_instance=None): + self.PouTagName = tagname + if pou_instance is not None: + self.PouInstance = pou_instance + + self.RefreshView() + + def ResetView(self): + self.PouTagName = None + self.PouInfos = None + self.PouInstance = None + + self.RefreshView() + + def RefreshView(self): + self.VariablesList.DeleteAllItems() + self.InstanceChoice.Clear() + + if self.PouTagName is not None: + self.PouInfos = self.Controller.GetPouVariables(self.PouTagName, self.Debug) + else: + 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 + else: + text = var_infos["name"] + + panel = wx.Panel(self.VariablesList) + + buttons = [] + if var_infos["class"] in ITEMS_VARIABLE: + if (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))): + graph_button = wx.lib.buttons.GenBitmapButton(name="graph", + parent=panel, bitmap=self.ParentWindow.GenerateBitmap("graph"), + pos=wx.Point(0, 0), size=wx.Size(28, 28), style=wx.NO_BORDER) + self.Bind(wx.EVT_BUTTON, self.GenGraphButtonCallback(var_infos), graph_button) + buttons.append(graph_button) + elif var_infos["edit"]: + edit_button = wx.lib.buttons.GenBitmapButton(name="edit", + parent=panel, bitmap=self.ParentWindow.GenerateBitmap("edit"), + pos=wx.Point(0, 0), size=wx.Size(28, 28), style=wx.NO_BORDER) + self.Bind(wx.EVT_BUTTON, self.GenEditButtonCallback(var_infos), edit_button) + buttons.append(edit_button) + + if var_infos["debug"] and self.Debug: + debug_button = wx.lib.buttons.GenBitmapButton(name="debug", + parent=panel, bitmap=self.ParentWindow.GenerateBitmap("debug"), + pos=wx.Point(0, 0), size=wx.Size(28, 28), style=wx.NO_BORDER) + self.Bind(wx.EVT_BUTTON, self.GenDebugButtonCallback(var_infos), debug_button) + buttons.append(debug_button) + + button_num = len(buttons) + if button_num > 0: + panel.SetSize(wx.Size(button_num * 32, 28)) + panel.SetBackgroundColour(self.VariablesList.GetBackgroundColour()) + panel_sizer = wx.BoxSizer(wx.HORIZONTAL) + panel.SetSizer(panel_sizer) + + for button in buttons: + panel_sizer.AddWindow(button, 0, border=4, flag=wx.LEFT) + else: + panel.Destroy() + panel = None + + item = self.VariablesList.AppendItem(root, text, wnd=panel) + self.VariablesList.SetItemImage(item, self.ParentWindow.GetTreeImage(var_infos["class"])) + self.VariablesList.SetPyData(item, var_infos) + + instances = self.Controller.SearchPouInstances(self.PouTagName, self.Debug) + for instance in instances: + self.InstanceChoice.Append(instance) + if self.PouInfos["class"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]: + self.PouInstance = None + self.InstanceChoice.SetSelection(0) + elif self.PouInstance in instances: + self.InstanceChoice.SetStringSelection(self.PouInstance) + else: + self.PouInstance = None + self.InstanceChoice.SetValue(_("Select an instance")) + + self.RefreshButtons() + + 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) + + root = self.VariablesList.GetRootItem() + if root is not None and root.IsOk(): + item, item_cookie = self.VariablesList.GetFirstChild(root) + while item is not None and item.IsOk(): + panel = self.VariablesList.GetItemWindow(item) + if panel is not None: + for child in panel.GetChildren(): + if child.GetName() != "edit": + child.Enable(enabled) + item, item_cookie = self.VariablesList.GetNextChild(root, item_cookie) + + def GenEditButtonCallback(self, infos): + def EditButtonCallback(event): + var_class = infos["class"] + if var_class == ITEM_RESOURCE: + tagname = self.Controller.ComputeConfigurationResourceName( + self.InstanceChoice.GetStringSelection(), + infos["name"]) + else: + var_class = ITEM_POU + tagname = self.Controller.ComputePouName(infos["type"]) + self.ParentWindow.EditProjectElement(var_class, tagname) + event.Skip() + return EditButtonCallback + + def GenDebugButtonCallback(self, infos): + def DebugButtonCallback(event): + if self.InstanceChoice.GetSelection() != -1: + var_class = infos["class"] + var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), + infos["name"]) + if var_class in ITEMS_VARIABLE: + self.ParentWindow.AddDebugVariable(var_path, force=True) + else: + self.ParentWindow.OpenDebugViewer( + infos["class"], + var_path, + self.Controller.ComputePouName(infos["type"])) + event.Skip() + return DebugButtonCallback + + def GenGraphButtonCallback(self, infos): + def GraphButtonCallback(event): + if self.InstanceChoice.GetSelection() != -1: + if infos["class"] in ITEMS_VARIABLE: + var_path = "%s.%s" % (self.InstanceChoice.GetStringSelection(), + infos["name"]) + self.ParentWindow.OpenGraphicViewer(var_path) + event.Skip() + return GraphButtonCallback + + def OnParentButtonClick(self, event): + if self.InstanceChoice.GetSelection() != -1: + parent_path = self.InstanceChoice.GetStringSelection().rsplit(".", 1)[0] + tagname = self.Controller.GetPouInstanceTagname(parent_path, self.Debug) + if tagname is not None: + wx.CallAfter(self.SetPouType, tagname, parent_path) + wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, tagname) + event.Skip() + + def OnInstanceChoiceChanged(self, event): + self.RefreshButtons() + event.Skip() + + def OnDebugButtonClick(self, event): + if self.InstanceChoice.GetSelection() != -1: + self.ParentWindow.OpenDebugViewer( + self.PouInfos["class"], + self.InstanceChoice.GetStringSelection(), + self.PouTagName) + event.Skip() + + def OnVariablesListItemActivated(self, event): + if self.InstanceChoice.GetSelection() != -1: + instance_path = self.InstanceChoice.GetStringSelection() + selected_item = self.VariablesList.GetSelection() + if selected_item is not None and selected_item.IsOk(): + item_infos = self.VariablesList.GetPyData(selected_item) + if item_infos["class"] not in ITEMS_VARIABLE: + if item_infos["class"] == ITEM_RESOURCE: + tagname = self.Controller.ComputeConfigurationResourceName( + instance_path, + item_infos["name"]) + else: + tagname = self.Controller.ComputePouName(item_infos["type"]) + item_path = "%s.%s" % (instance_path, item_infos["name"]) + wx.CallAfter(self.SetPouType, tagname, item_path) + wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, tagname) + event.Skip() + + \ No newline at end of file diff -r 37882f34f9cb -r f10449b18dbe controls/VariablePanel.py --- a/controls/VariablePanel.py Sat May 12 12:33:17 2012 +0200 +++ b/controls/VariablePanel.py Fri May 18 18:49:49 2012 +0200 @@ -43,7 +43,7 @@ parent.Append(helpString=help, id=id, kind=kind, item=text) [TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, - INSTANCESTREE, LIBRARYTREE, SCALING + POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING ] = range(9) #------------------------------------------------------------------------------- @@ -644,7 +644,7 @@ self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection()) self.Controler.BufferProject() self.ParentWindow.RefreshView(variablepanel = False) - self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, INSTANCESTREE, LIBRARYTREE) + self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) event.Skip() def OnDescriptionChanged(self, event): @@ -653,7 +653,7 @@ new_description = self.Description.GetValue() if new_description != old_description: self.Controler.SetPouDescription(words[1], new_description) - self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, INSTANCESTREE, LIBRARYTREE) + self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) event.Skip() def OnClassFilter(self, event): @@ -695,7 +695,7 @@ self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_value, value) self.Controler.BufferProject() self.ParentWindow.RefreshView(variablepanel = False) - self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, INSTANCESTREE, LIBRARYTREE) + self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) event.Skip() else: self.SaveValues() @@ -789,7 +789,7 @@ self.SaveValues(False) self.ParentWindow.RefreshView(variablepanel = False) self.Controler.BufferProject() - self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, INSTANCESTREE, LIBRARYTREE) + self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) return VariableTypeFunction def VariableArrayTypeFunction(self, event): @@ -803,7 +803,7 @@ self.SaveValues(False) self.ParentWindow.RefreshView(variablepanel = False) self.Controler.BufferProject() - self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, INSTANCESTREE, LIBRARYTREE) + self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) dialog.Destroy() def OnVariablesGridCellLeftClick(self, event): @@ -840,7 +840,7 @@ self.Controler.SetPouInterfaceVars(words[1], self.Values) if buffer: self.Controler.BufferProject() - self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, INSTANCESTREE, LIBRARYTREE) + self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) #------------------------------------------------------------------------------- # Highlights showing functions diff -r 37882f34f9cb -r f10449b18dbe controls/__init__.py --- a/controls/__init__.py Sat May 12 12:33:17 2012 +0200 +++ b/controls/__init__.py Fri May 18 18:49:49 2012 +0200 @@ -32,3 +32,5 @@ from LocationCellEditor import LocationCellEditor from VariablePanel import VariablePanel from LibraryPanel import LibraryPanel +from PouInstanceVariablesPanel import PouInstanceVariablesPanel +from CustomTree import CustomTree diff -r 37882f34f9cb -r f10449b18dbe xmlclass/xmlclass.py --- a/xmlclass/xmlclass.py Sat May 12 12:33:17 2012 +0200 +++ b/xmlclass/xmlclass.py Fri May 18 18:49:49 2012 +0200 @@ -1238,15 +1238,16 @@ classmembers["setElementValue"] = generateSetElementValue(self, classinfos) classmembers["singleLineAttributes"] = True classmembers["compatibility"] = lambda x, y: None + classmembers["extraAttrs"] = {} class_definition = classobj(str(classname), bases, classmembers) setattr(class_definition, "__setattr__", generateSetattrMethod(self, class_definition, classinfos)) class_infos = {"type": COMPILEDCOMPLEXTYPE, - "name": classname, - "check": generateClassCheckFunction(class_definition), - "initial": generateClassCreateFunction(class_definition), - "extract": generateClassExtractFunction(class_definition), - "generate": class_definition.generateXMLText} + "name": classname, + "check": generateClassCheckFunction(class_definition), + "initial": generateClassCreateFunction(class_definition), + "extract": generateClassExtractFunction(class_definition), + "generate": class_definition.generateXMLText} if self.FileName is not None: self.ComputedClasses[self.FileName][classname] = class_definition @@ -1410,6 +1411,7 @@ elements = dict([(element["name"], element) for element in classinfos["elements"]]) def loadXMLTreeMethod(self, tree, extras=[], derived=False): + self.extraAttrs = {} self.compatibility(tree) if not derived: children_structure = "" @@ -1430,8 +1432,8 @@ if attributes.has_key(attrname): attributes[attrname]["attr_type"] = FindTypeInfos(factory, attributes[attrname]["attr_type"]) object.__setattr__(self, attrname, attributes[attrname]["attr_type"]["extract"](attr)) - elif not classinfos.has_key("base") and attrname not in extras: - raise ValueError("Invalid attribute \"%s\" for \"%s\" element!" % (attrname, tree.nodeName)) + elif not classinfos.has_key("base") and not attrname in extras and not self.extraAttrs.has_key(attrname): + self.extraAttrs[attrname] = GetAttributeValue(attr) required_attributes.pop(attrname, None) if len(required_attributes) > 0: raise ValueError("Required attributes %s missing for \"%s\" element!" % (", ".join(["\"%s\""%name for name in required_attributes]), tree.nodeName)) @@ -1489,8 +1491,10 @@ text = u'' first = True + if not classinfos.has_key("base"): - for attr, value in extras.items(): + extras.update(self.extraAttrs) + for attr, value in extras.iteritems(): if not first and not self.singleLineAttributes: text += u'\n%s' % (ind2) text += u' %s=%s' % (attr, quoteattr(value)) @@ -1643,7 +1647,7 @@ elif element["elmt_type"]["type"] == SIMPLETYPE: children.append({"name": element_name, "require": element["minOccurs"] != 0, "type": gettypeinfos(element["elmt_type"]["basename"], - element["elmt_type"]["facets"]), + element["elmt_type"]["facets"]), "value": getattr(self, element_name, None)}) else: instance = getattr(self, element_name, None) @@ -1677,6 +1681,9 @@ setattr(self, parts[0], elements[parts[0]]["elmt_type"]["extract"](value, False)) else: instance = getattr(self, parts[0], None) + if instance is None and elements[parts[0]]["minOccurs"] == 0: + instance = elements[parts[0]]["elmt_type"]["initial"]() + setattr(self, parts[0], instance) if instance != None: if len(parts) > 1: instance.setElementValue(parts[1], value) @@ -1702,6 +1709,7 @@ """ def generateInitMethod(factory, classinfos): def initMethod(self): + self.extraAttrs = {} if classinfos.has_key("base"): classinfos["base"].__init__(self) for attribute in classinfos["attributes"]: