refactoring
authorlaurent
Mon, 21 May 2012 09:59:44 +0200
changeset 687 629680fb0582
parent 686 3216bf5f711d
child 689 ce605c1a6d04
refactoring
GraphicViewer.py
PLCControler.py
PLCOpenEditor.py
TextViewer.py
Viewer.py
controls/CustomTree.py
controls/EditorPanel.py
controls/PouInstanceVariablesPanel.py
graphics/FBD_Objects.py
plcopen/plcopen.py
--- a/GraphicViewer.py	Sat May 19 12:40:53 2012 +0200
+++ b/GraphicViewer.py	Mon May 21 09:59:44 2012 +0200
@@ -507,14 +507,15 @@
     ## Refresh the variable cursor.
     #  @param dc The draw canvas
     def RefreshCursor(self, dc=None):
-        if dc is None:
-            dc = wx.BufferedDC(wx.ClientDC(self.Canvas.canvas), self.Canvas._Buffer)
-        
-        # Erase previous time cursor if drawn
-        if self.LastCursor is not None:
-            self.DrawCursor(dc, *self.LastCursor)
-        
-        # Draw new time cursor
-        if self.CursorIdx is not None:
-            self.LastCursor = self.Datas[self.CursorIdx]
-            self.DrawCursor(dc, *self.LastCursor)
+        if self:
+            if dc is None:
+                dc = wx.BufferedDC(wx.ClientDC(self.Canvas.canvas), self.Canvas._Buffer)
+            
+            # Erase previous time cursor if drawn
+            if self.LastCursor is not None:
+                self.DrawCursor(dc, *self.LastCursor)
+            
+            # Draw new time cursor
+            if self.CursorIdx is not None:
+                self.LastCursor = self.Datas[self.CursorIdx]
+                self.DrawCursor(dc, *self.LastCursor)
--- a/PLCControler.py	Sat May 19 12:40:53 2012 +0200
+++ b/PLCControler.py	Mon May 21 09:59:44 2012 +0200
@@ -577,7 +577,7 @@
                 return ["%s.%s" % (words[1], words[2])]
         return []
     
-    def RecursiveGetPouInstanceTagname(self, project, pou_type, parts):
+    def RecursiveGetPouInstanceTagName(self, project, pou_type, parts):
         pou = project.getpou(pou_type)
         if pou is not None:
             if len(parts) == 0:
@@ -587,13 +587,13 @@
                 for variable in varlist.getvariable():
                     vartype_content = variable.gettype().getcontent()
                     if vartype_content["name"] == "derived":
-                        return self.RecursiveGetPouInstanceTagname(
+                        return self.RecursiveGetPouInstanceTagName(
                                         project, 
                                         vartype_content["value"].getname(),
                                         parts[1:])
         return None
     
-    def GetPouInstanceTagname(self, instance_path, debug = False):
+    def GetPouInstanceTagName(self, instance_path, debug = False):
         parts = instance_path.split(".")
         if len(parts) == 1:
             return self.ComputeConfigurationName(parts[0])
@@ -614,149 +614,26 @@
                                         return self.ComputePouName(
                                                     pou_instance.gettypeName())
                                     else:
-                                        return self.RecursiveGetPouInstanceTagname(
+                                        return self.RecursiveGetPouInstanceTagName(
                                                     project,
                                                     pou_instance.gettypeName(),
                                                     parts[3:])
         return None
     
-    def GetInstanceInfos(self, instance_path):
+    def GetInstanceInfos(self, instance_path, debug = False):
         tagname = self.GetPouInstanceTagName(instance_path)
         if tagname is not None:
-            return self.Controler.GetPouVariables(tagname, self.Debug)
+            return self.GetPouVariables(tagname, debug)
         else:
-            pou_path, var_name = tagname.rsplit(".", 1)
-            tagname = self.Controler.GetPouInstanceTagName(pou_path)
+            pou_path, var_name = instance_path.rsplit(".", 1)
+            tagname = self.GetPouInstanceTagName(pou_path)
             if tagname is not None:
-                pou_infos = self.Controler.GetPouVariables(tagname, self.Debug)
+                pou_infos = self.GetPouVariables(tagname, 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)
-        if project is not None:
-            infos = {"name": project.getname(), "type": ITEM_PROJECT, "values" : []}
-            for config in project.getconfigurations():
-                config_infos = {"name" : config.getname(), "type": ITEM_CONFIGURATION, "values" : []}
-                for resource in config.getresource():
-                    resource_infos = {"name" : resource.getname(), "type": ITEM_RESOURCE, "values": []}
-                    for task in resource.gettask():
-                        for pou in task.getpouInstance():
-                            instance_infos = self.GetPouTopology(pou.getname(), pou.gettypeName(), debug=debug)
-                            if instance_infos is not None:
-                                resource_infos["values"].append(instance_infos)
-                    for pou in resource.getpouInstance():
-                        instance_infos = self.GetPouTopology(pou.getname(), pou.gettypeName(), debug=debug)
-                        if instance_infos is not None:
-                            resource_infos["values"].append(instance_infos)
-                    for varlist in resource.getglobalVars():
-                        for variable in varlist.getvariable():
-                            vartype_content = variable.gettype().getcontent()
-                            if vartype_content["name"] == "derived":
-                                var_infos = self.GetPouTopology(variable.getname(), vartype_content["value"].getname(), True, debug)
-                                if var_infos is not None:
-                                    resource_infos["values"].append(var_infos)
-                            elif vartype_content["name"] in ["string", "wstring"]:
-                                resource_infos["values"].append({"name" : variable.getname(), 
-                                                                 "elmt_type" : vartype_content["name"].upper(),
-                                                                 "type" : ITEM_VAR_GLOBAL, "values" : []})
-                            else:
-                                resource_infos["values"].append({"name" : variable.getname(), 
-                                                                 "elmt_type" : vartype_content["name"], 
-                                                                 "type" : ITEM_VAR_GLOBAL, "values" : []})
-                    config_infos["values"].append(resource_infos)
-                for varlist in config.getglobalVars():
-                    for variable in varlist.getvariable():
-                        vartype_content = variable.gettype().getcontent()
-                        if vartype_content["name"] == "derived":
-                            var_infos = self.GetPouTopology(variable.getname(), vartype_content["value"].getname(), True, debug)
-                            if var_infos is not None:
-                                config_infos["values"].append(var_infos)
-                        elif vartype_content["name"] in ["string", "wstring"]:
-                            config_infos["values"].append({"name" : variable.getname(), 
-                                                           "elmt_type" : vartype_content["name"].upper(), 
-                                                           "type" : ITEM_VAR_GLOBAL, "values" : []})
-                        else:
-                            config_infos["values"].append({"name" : variable.getname(),
-                                                           "elmt_type" : vartype_content["name"], 
-                                                           "type" : ITEM_VAR_GLOBAL, "values" : []})
-                infos["values"].append(config_infos)
-            return infos
-        return None
-    
-    # Return pou topology informations
-    def GetPouTopology(self, name, type, global_var = False, debug = False):
-        project = self.GetProject(debug)
-        if project is not None:
-            pou = project.getpou(type)
-            if pou is not None:
-                pou_type = pou.getpouType()
-                if pou_type == "function":
-                    return None
-                elif pou_type == "program":
-                    pou_infos = {"name" : name, "elmt_type" : type, "type" : ITEM_PROGRAM, 
-                                 "tagname" : self.ComputePouName(pou.getname()), "values" : []}
-                else:
-                    pou_infos = {"name" : name, "elmt_type" : type, "type" : ITEM_FUNCTIONBLOCK, 
-                                 "tagname" : self.ComputePouName(pou.getname()), "values" : []}
-                if pou.getbodyType() == "SFC":
-                    for transition in pou.gettransitionList():
-                        pou_infos["values"].append({"name" : transition.getname(), 
-                            "elmt_type" : "TRANSITION", "type" : ITEM_TRANSITION, 
-                            "tagname" : self.ComputePouActionName(pou.getname(), transition.getname()),
-                            "values" : []})
-                    for action in pou.getactionList():
-                        pou_infos["values"].append({"name": action.getname(), 
-                            "elmt_type" : "ACTION", "type": ITEM_ACTION, 
-                            "tagname" : self.ComputePouActionName(pou.getname(), action.getname()),
-                            "values" : []})
-                if pou.interface:
-                    # Extract variables from every varLists
-                    for type, varlist in pou.getvars():
-                        infos = VAR_CLASS_INFOS.get(type, None)
-                        if infos is not None:
-                            current_var_class = infos[1]
-                        else:
-                            current_var_class = ITEM_VAR_LOCAL
-                        for variable in varlist.getvariable():
-                            vartype_content = variable.gettype().getcontent()
-                            if vartype_content["name"] == "derived":
-                                var_infos = self.GetPouTopology(variable.getname(), vartype_content["value"].getname())
-                                if var_infos is not None:
-                                    pou_infos["values"].append(var_infos)
-                            elif vartype_content["name"] in ["string", "wstring"]:
-                                pou_infos["values"].append({"name" : variable.getname(), 
-                                                            "elmt_type" : vartype_content["name"].upper(), 
-                                                            "type" : current_var_class, "values" : []})
-                            else:
-                                pou_infos["values"].append({"name" : variable.getname(), 
-                                                            "elmt_type" : vartype_content["name"], 
-                                                            "type" : current_var_class, "values" : []})
-                return pou_infos
-            block_infos = self.GetBlockType(type, debug = debug)
-            if block_infos is not None:
-                if block_infos["type"] == "function":
-                    return None
-                elif block_infos["type"] == "program":
-                    pou_infos = {"name" : name, "elmt_type" : type, "type" : ITEM_PROGRAM, "values" : []}
-                else:
-                    pou_infos = {"name" : name, "elmt_type" : type, "type" : ITEM_FUNCTIONBLOCK, "values" : []}
-                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_OUTPUT, "values" : []})
-                return pou_infos
-            
-            if type in self.GetDataTypes(debug = debug):
-                if global_var:
-                    return {"name" : name, "elmt_type" : type, "type" : ITEM_VAR_GLOBAL, "values" : []}
-                else:
-                    return {"name" : name, "elmt_type" : type, "type" : ITEM_VAR_LOCAL, "values" : []}
-        return None
-
+    
     # Return if data type given by name is used by another data type or pou
     def DataTypeIsUsed(self, name, debug = False):
         project = self.GetProject(debug)
@@ -919,6 +796,15 @@
             self.Project.removepou(pou_name)
             self.BufferProject()
     
+    # Return the name of the configuration if only one exist
+    def GetProjectMainConfigurationName(self):
+        if self.Project is not None:
+            # Found the configuration corresponding to old name and change its name to new name
+            configurations = self.Project.getconfigurations()
+            if len(configurations) == 1:
+                return configurations[0].getname()
+        return None
+                
     # Add a configuration to Project
     def ProjectAddConfiguration(self, config_name):
         if self.Project is not None:
--- a/PLCOpenEditor.py	Sat May 19 12:40:53 2012 +0200
+++ b/PLCOpenEditor.py	Mon May 21 09:59:44 2012 +0200
@@ -279,20 +279,13 @@
             control.ProcessEvent(event)
     return ShortcutKeyFunction
 
-def GetParentName(tree, item, parent_type):
-    parent_item = tree.GetItemParent(item)
-    parent_item_type = tree.GetPyData(parent_item)
-    while parent_item_type != parent_type:
-        parent_item = tree.GetItemParent(parent_item)
-        parent_item_type = tree.GetPyData(parent_item)
-    return tree.GetItemText(parent_item)
-
 def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None):
     def DeleteElementFunction(self, 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.ProjectTree, selected, parent_type)
+                item_infos = self.ProjectTree.GetPyData(selected)
+                parent_name = item_infos["tagname"].split("::")[1]
                 remove_function(self.Controler, parent_name, name)
             else:
                 remove_function(self.Controler, name)
@@ -406,7 +399,7 @@
     def _init_coll_FileMenu_Items(self, parent):
         pass
     
-    def _init_coll_AddMenu_Items(self, parent):
+    def _init_coll_AddMenu_Items(self, parent, add_config=True):
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE,
               kind=wx.ITEM_NORMAL, text=_(u'&Data Type'))
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION,
@@ -415,8 +408,9 @@
               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'))
+        if add_config:
+            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,
@@ -854,11 +848,12 @@
         elif page_infos[0] == "editor":
             tagname = page_infos[1]
             page_ref = self.EditProjectElement(self.Controler.GetElementType(tagname), tagname)
-            page_ref.RefreshView()
-            return notebook.GetPageIndex(page_ref)
+            if page_ref is not None:
+                page_ref.RefreshView()
+                return notebook.GetPageIndex(page_ref)
         elif page_infos[0] == "debug":
             instance_path = page_infos[1]
-            instance_infos = self.Controler.GetInstanceInfos(instance_path)
+            instance_infos = self.Controler.GetInstanceInfos(instance_path, self.EnableDebug)
             if instance_infos is not None:
                 return notebook.GetPageIndex(self.OpenDebugViewer(instance_infos["class"], instance_path, instance_infos["type"]))
         return None
@@ -1194,6 +1189,7 @@
     def ResetView(self):
         self.DeleteAllPages()
         self.ProjectTree.DeleteAllItems()
+        self.ProjectTree.Enable(False)
         self.PouInstanceVariablesPanel.ResetView()
         self.LibraryPanel.ResetTree()
         self.LibraryPanel.SetControler(None)
@@ -1387,8 +1383,7 @@
         if window == self.ProjectTree or window is None:
             selected = self.ProjectTree.GetSelection()
             if selected.IsOk():
-                type = self.ProjectTree.GetPyData(selected)
-                function = self.DeleteFunctions.get(type, None)
+                function = self.DeleteFunctions.get(self.ProjectTree.GetPyData(selected)["type"], None)
                 if function is not None:
                     function(self, selected)
                     self.CloseTabsWithoutModel()
@@ -1484,6 +1479,10 @@
                 self.AUIManager.RestorePane(pane)
             self.AUIManager.Update()
     
+    def EnsureTabVisible(self, tab):
+        notebook = tab.GetParent()
+        notebook.SetSelection(notebook.GetPageIndex(tab))
+    
     def OnPouSelectedChanging(self, event):
         if not self.Starting:
             selected = self.TabsOpened.GetSelection()
@@ -1503,8 +1502,13 @@
                     wx.CallAfter(self.SelectProjectTreeItem, tagname)
                     wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname)
                     window.RefreshView()
+                    self.EnsureTabVisible(self.LibraryPanel)
                 else:
                     instance_path = window.GetInstancePath()
+                    if tagname == "":
+                        instance_path = instance_path.rsplit(".", 1)[0]
+                        tagname = self.Controler.GetPouInstanceTagName(instance_path, self.EnableDebug)
+                    self.EnsureTabVisible(self.DebugVariablePanel)
                     wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname, instance_path)
             wx.CallAfter(self._Refresh, FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
         event.Skip()
@@ -1581,15 +1585,20 @@
         		return self.GenerateProjectTreeBranch(root, infos["values"][0])
         	item_name = _(item_name)
         self.ProjectTree.SetItemText(root, item_name)
-        self.ProjectTree.SetPyData(root, infos["type"])
+        self.ProjectTree.SetPyData(root, infos)
         highlight_colours = self.Highlights.get(infos.get("tagname", None), (wx.WHITE, wx.BLACK))
         self.ProjectTree.SetItemBackgroundColour(root, highlight_colours[0])
         self.ProjectTree.SetItemTextColour(root, highlight_colours[1])
         if infos["type"] == ITEM_POU:
             self.ProjectTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])])
-        else:
+        elif infos.has_key("icon") and infos["icon"] is not None:
+            icon_path = infos["icon"]
+            if not self.TreeImageDict.has_key(icon_path):
+                self.TreeImageDict[icon_path] = self.TreeImageList.Add(wx.Bitmap(icon_path))
+            self.ProjectTree.SetItemImage(root, self.TreeImageDict[icon_path])
+        elif self.TreeImageDict.has_key(infos["type"]):
             self.ProjectTree.SetItemImage(root, self.TreeImageDict[infos["type"]])      
-            
+        
         if wx.VERSION >= (2, 6, 0):
             item, root_cookie = self.ProjectTree.GetFirstChild(root)
         else:
@@ -1634,7 +1643,8 @@
         else:
             item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
         while item.IsOk() and not found:
-            if (self.ProjectTree.GetItemText(item), self.ProjectTree.GetPyData(item)) == items[0]:
+            item_infos = self.ProjectTree.GetPyData(item)
+            if (item_infos["name"].split(":")[-1].strip(), item_infos["type"]) == items[0]:
                 if len(items) == 1:
                     self.SelectedItem = item
                     self.ProjectTree.SelectItem(item)
@@ -1650,7 +1660,7 @@
     def OnProjectTreeBeginDrag(self, event):
         if wx.Platform == '__WXMSW__':
             self.SelectedItem = event.GetItem()
-        if self.SelectedItem is not None and self.ProjectTree.GetPyData(self.SelectedItem) == ITEM_POU:
+        if self.SelectedItem is not None and self.ProjectTree.GetPyData(self.SelectedItem)["type"] == ITEM_POU:
             block_name = self.ProjectTree.GetItemText(self.SelectedItem)
             block_type = self.Controler.GetPouType(block_name)
             if block_type != "program":
@@ -1662,7 +1672,7 @@
 
     def OnProjectTreeItemBeginEdit(self, event):
         selected = event.GetItem()
-        if self.ProjectTree.GetPyData(selected) in ITEMS_UNEDITABLE:
+        if self.ProjectTree.GetPyData(selected)["type"] in ITEMS_UNEDITABLE:
             event.Veto()
         else:
             event.Skip()
@@ -1679,10 +1689,10 @@
             else:
                 item = event.GetItem()
                 old_name = self.ProjectTree.GetItemText(item)
-                itemtype = self.ProjectTree.GetPyData(item)
-                if itemtype == ITEM_PROJECT:
+                item_infos = self.ProjectTree.GetPyData(item)
+                if item_infos["type"] == ITEM_PROJECT:
                     self.Controler.SetProjectProperties(name = new_name)
-                elif itemtype == ITEM_DATATYPE:
+                elif item_infos["type"] == ITEM_DATATYPE:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectDataTypeNames() if name != old_name]:
                         message = _("\"%s\" data type already exists!")%new_name
                         abort = True
@@ -1691,7 +1701,7 @@
                         self.RefreshEditorNames(self.Controler.ComputeDataTypeName(old_name), 
                                                 self.Controler.ComputeDataTypeName(new_name))
                         self.RefreshPageTitles()
-                elif itemtype == ITEM_POU:
+                elif item_infos["type"] == ITEM_POU:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
                         message = _("\"%s\" pou already exists!")%new_name
                         abort = True
@@ -1706,29 +1716,29 @@
                                                 self.Controler.ComputePouName(new_name))
                         self.RefreshLibraryPanel()
                         self.RefreshPageTitles()
-                elif itemtype == ITEM_TRANSITION:
-                    pou_name = GetParentName(self.ProjectTree, item, ITEM_POU)
+                elif item_infos["type"] == ITEM_TRANSITION:
                     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]:
                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
                     else:
-                        self.Controler.ChangePouTransitionName(pou_name, old_name, new_name)
-                        self.RefreshEditorNames(self.Controler.ComputePouTransitionName(pou_name, old_name), 
-                                                self.Controler.ComputePouTransitionName(pou_name, new_name))
+                        words = item_infos["tagname"].split("::")
+                        self.Controler.ChangePouTransitionName(words[1], old_name, new_name)
+                        self.RefreshEditorNames(self.Controler.ComputePouTransitionName(words[1], old_name), 
+                                                self.Controler.ComputePouTransitionName(words[1], new_name))
                         self.RefreshPageTitles()
-                elif itemtype == ITEM_ACTION:
-                    pou_name = GetParentName(self.ProjectTree, item, ITEM_POU)
+                elif item_infos["type"] == ITEM_ACTION:
                     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]:
                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
                     else:
-                        self.Controler.ChangePouActionName(pou_name, old_name, new_name)
-                        self.RefreshEditorNames(self.Controler.ComputePouActionName(pou_name, old_name), 
-                                                self.Controler.ComputePouActionName(pou_name, new_name))
+                        words = item_infos["tagname"].split("::")
+                        self.Controler.ChangePouActionName(words[1], old_name, new_name)
+                        self.RefreshEditorNames(self.Controler.ComputePouActionName(words[1], old_name), 
+                                                self.Controler.ComputePouActionName(words[1], new_name))
                         self.RefreshPageTitles()
-                elif itemtype == ITEM_CONFIGURATION:
+                elif item_infos["type"] == ITEM_CONFIGURATION:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]:
                         message = _("\"%s\" config already exists!")%new_name
                         abort = True
@@ -1747,8 +1757,7 @@
                         self.RefreshEditorNames(self.Controler.ComputeConfigurationName(old_name), 
                                                 self.Controler.ComputeConfigurationName(new_name))
                         self.RefreshPageTitles()
-                elif itemtype == ITEM_RESOURCE:
-                    config_name = GetParentName(self.ProjectTree, item, ITEM_CONFIGURATION)
+                elif item_infos["type"] == ITEM_RESOURCE:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]:
                         message = _("\"%s\" config already exists!")%new_name
                         abort = True
@@ -1763,9 +1772,10 @@
                             abort = True
                         messageDialog.Destroy()
                     if not abort:
-                        self.Controler.ChangeConfigurationResourceName(config_name, old_name, new_name)
-                        self.RefreshEditorNames(self.Controler.ComputeConfigurationResourceName(config_name, old_name), 
-                                                self.Controler.ComputeConfigurationResourceName(config_name, new_name))
+                        words = item_infos["tagname"].split("::")
+                        self.Controler.ChangeConfigurationResourceName(words[1], old_name, new_name)
+                        self.RefreshEditorNames(self.Controler.ComputeConfigurationResourceName(words[1], old_name), 
+                                                self.Controler.ComputeConfigurationResourceName(words[1], new_name))
                         self.RefreshPageTitles()
             if message or abort:
                 if message:
@@ -1782,49 +1792,23 @@
     def OnProjectTreeItemActivated(self, event):
         selected = event.GetItem()
         name = self.ProjectTree.GetItemText(selected)
-        data = self.ProjectTree.GetPyData(selected)
-        if data == ITEM_PROJECT:
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == 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.ProjectTree, selected, ITEM_CONFIGURATION)
-            self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name))
-        elif data in [ITEM_TRANSITION, ITEM_ACTION]:
-            pou_name = GetParentName(self.ProjectTree, selected, ITEM_POU)
-            if data == ITEM_TRANSITION:
-                tagname = self.Controler.ComputePouTransitionName(pou_name, name)
-            elif data == ITEM_ACTION:
-                tagname = self.Controler.ComputePouActionName(pou_name, name)
-            self.EditProjectElement(data, tagname)
+        elif item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
+                                    ITEM_CONFIGURATION, ITEM_RESOURCE,
+                                    ITEM_TRANSITION, ITEM_ACTION]:
+            self.EditProjectElement(item_infos["type"], item_infos["tagname"])
         event.Skip()
     
     def ProjectTreeItemSelect(self, select_item):
         name = self.ProjectTree.GetItemText(select_item)
-        data = self.ProjectTree.GetPyData(select_item)
-        tagname = None
-        if data == ITEM_DATATYPE:
-            tagname = self.Controler.ComputeDataTypeName(name)
-        elif data == ITEM_POU:
-            tagname = self.Controler.ComputePouName(name)
-        elif data == ITEM_CONFIGURATION:
-            tagname = self.Controler.ComputeConfigurationName(name)
-        elif data == ITEM_RESOURCE:
-            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.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)
-        self.PouInstanceVariablesPanel.SetPouType(tagname)
+        item_infos = self.ProjectTree.GetPyData(select_item)
+        if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
+                                  ITEM_CONFIGURATION, ITEM_RESOURCE,
+                                  ITEM_TRANSITION, ITEM_ACTION]:
+            self.EditProjectElement(item_infos["type"], item_infos["tagname"], True)
+            self.PouInstanceVariablesPanel.SetPouType(item_infos["tagname"])
         
     def OnProjectTreeLeftUp(self, event):
         if self.SelectedItem is not None:
@@ -1838,7 +1822,7 @@
         event.Skip()
     
     def OnProjectTreeItemChanging(self, event):
-        if self.ProjectTree.GetPyData(event.GetItem()) not in ITEMS_UNEDITABLE and self.SelectedItem is None:
+        if self.ProjectTree.GetPyData(event.GetItem())["type"] not in ITEMS_UNEDITABLE and self.SelectedItem is None:
             self.SelectedItem = event.GetItem()
             event.Veto()
         else:
@@ -1925,10 +1909,10 @@
         self.ProjectTree.SelectItem(item)
         self.ProjectTreeItemSelect(item)
         name = self.ProjectTree.GetItemText(item)
-        type = self.ProjectTree.GetPyData(item)
+        item_infos = self.ProjectTree.GetPyData(item)
         
         menu = None
-        if type in ITEMS_UNEDITABLE:
+        if item_infos["type"] in ITEMS_UNEDITABLE:
             name = UNEDITABLE_NAMES_DICT[name]
             
             if name == "Data Types":
@@ -1960,11 +1944,11 @@
                 menu = wx.Menu(title='')
                 new_id = wx.NewId()
                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition"))
-                parent = self.ProjectTree.GetItemParent(item)
+                parent = self.ProjectTree.GetItemParent(item)["type"]
                 parent_type = self.ProjectTree.GetPyData(parent)
                 while parent_type != ITEM_POU:
                     parent = self.ProjectTree.GetItemParent(parent)
-                    parent_type = self.ProjectTree.GetPyData(parent)
+                    parent_type = self.ProjectTree.GetPyData(parent)["type"]
                 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.ProjectTree.GetItemText(parent)), id=new_id)
             
             elif name == "Actions":
@@ -1972,10 +1956,10 @@
                 new_id = wx.NewId()
                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action"))
                 parent = self.ProjectTree.GetItemParent(item)
-                parent_type = self.ProjectTree.GetPyData(parent)
+                parent_type = self.ProjectTree.GetPyData(parent)["type"]
                 while parent_type != ITEM_POU:
                     parent = self.ProjectTree.GetItemParent(parent)
-                    parent_type = self.ProjectTree.GetPyData(parent)
+                    parent_type = self.ProjectTree.GetPyData(parent)["type"]
                 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.ProjectTree.GetItemText(parent)), id=new_id)
             
             elif name == "Resources":
@@ -1983,14 +1967,18 @@
                 new_id = wx.NewId()
                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource"))
                 parent = self.ProjectTree.GetItemParent(item)
-                parent_type = self.ProjectTree.GetPyData(parent)
-                while parent_type != ITEM_CONFIGURATION:
+                parent_type = self.ProjectTree.GetPyData(parent)["type"]
+                while parent_type not in [ITEM_CONFIGURATION, ITEM_PROJECT]:
                     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)
+                    parent_type = self.ProjectTree.GetPyData(parent)["type"]
+                if parent_type == ITEM_PROJECT:
+                    parent_name = None
+                else:
+                    parent_name = self.ProjectTree.GetItemText(parent)
+                self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(parent_name), id=new_id)
             
         else:
-            if type == ITEM_POU:
+            if item_infos["type"] == ITEM_POU:
                 menu = wx.Menu(title='')
                 if self.Controler.GetPouBodyType(name) == "SFC":
                     new_id = wx.NewId()
@@ -2020,13 +2008,13 @@
                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Rename"))
                 self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, id=new_id)
             
-            elif type == ITEM_CONFIGURATION:
+            elif item_infos["type"] == ITEM_CONFIGURATION:
                 menu = wx.Menu(title='')
                 new_id = wx.NewId()
                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource"))
                 self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(name), id=new_id)
             
-            elif type in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]:
+            elif item_infos["type"] in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]:
                 menu = wx.Menu(title='')
                 
             if menu is not None:
@@ -2129,7 +2117,7 @@
             for idx in idxs:
                 editor = self.TabsOpened.GetPage(idx)
                 if editor.IsDebugging():
-                    instance_infos = self.Controler.GetInstanceInfos(editor.GetInstancePath())
+                    instance_infos = self.Controler.GetInstanceInfos(editor.GetInstancePath(), self.EnableDebug)
                     if instance_infos is None:
                         self.TabsOpened.DeletePage(idx)
                     elif isinstance(editor, GraphicViewer):
@@ -2141,6 +2129,7 @@
     def AddDebugVariable(self, iec_path, force=False):
         if self.EnableDebug:
             self.DebugVariablePanel.InsertValue(iec_path, force=force)
+            self.EnsureTabVisible(self.DebugVariablePanel)
             
 #-------------------------------------------------------------------------------
 #                         Library Panel Management Function
@@ -2441,7 +2430,7 @@
     def GenerateChangePouTypeFunction(self, name, new_type):
         def OnChangePouTypeMenu(event):
             selected = self.ProjectTree.GetSelection()
-            if self.ProjectTree.GetPyData(selected) == ITEM_POU: 
+            if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU: 
                 self.Controler.ProjectChangePouType(name, new_type)
                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
         return OnChangePouTypeMenu
@@ -2479,7 +2468,7 @@
 
     def OnRemoveDataTypeMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_DATATYPE:
+        if self.ProjectTree.GetPyData(selected)["type"] == ITEM_DATATYPE:
             name = self.ProjectTree.GetItemText(selected)
             if not self.Controler.DataTypeIsUsed(name):
                 self.Controler.ProjectRemoveDataType(name)
@@ -2493,12 +2482,12 @@
 
     def OnRenamePouMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_POU: 
+        if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU: 
             wx.CallAfter(self.ProjectTree.EditLabel, selected)
 
     def OnRemovePouMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_POU:
+        if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU:
             name = self.ProjectTree.GetItemText(selected)
             if not self.Controler.PouIsUsed(name):
                 self.Controler.ProjectRemovePou(name)
@@ -2512,14 +2501,10 @@
 
     def OnRemoveTransitionMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_TRANSITION: 
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == 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.ProjectTree.GetItemParent(item)
-                item_type = self.ProjectTree.GetPyData(item)
-            pou_name = self.ProjectTree.GetItemText(item)
+            pou_name = item_infos["tagname"].split("::")[1]
             self.Controler.ProjectRemovePouTransition(pou_name, transition)
             tagname = self.Controler.ComputePouTransitionName(pou_name, transition)
             idx = self.IsOpened(tagname)
@@ -2529,14 +2514,10 @@
 
     def OnRemoveActionMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_ACTION: 
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == 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.ProjectTree.GetItemParent(item)
-                item_type = self.ProjectTree.GetPyData(item)
-            pou_name = self.ProjectTree.GetItemText(item)
+            pou_name = item_infos["tagname"].split("::")[1]
             self.Controler.ProjectRemovePouAction(pou_name, action)
             tagname = self.Controler.ComputePouActionName(pou_name, action)
             idx = self.IsOpened(tagname)
@@ -2546,7 +2527,7 @@
 
     def OnRemoveConfigurationMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_CONFIGURATION: 
+        if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFIGURATION: 
             name = self.ProjectTree.GetItemText(selected)
             self.Controler.ProjectRemoveConfiguration(name)
             tagname = self.Controler.ComputeConfigurationName(name)
@@ -2557,14 +2538,10 @@
 
     def OnRemoveResourceMenu(self, event):
         selected = self.ProjectTree.GetSelection()
-        if self.ProjectTree.GetPyData(selected) == ITEM_RESOURCE:
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == 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.ProjectTree.GetItemParent(item)
-                item_type = self.ProjectTree.GetPyData(item)
-            config_name = self.ProjectTree.GetItemText(item)
+            config_name = item_infos["tagname"].split("::")[1]
             self.Controler.ProjectRemoveConfigurationResource(config_name, resource)
             tagname = self.Controler.ComputeConfigurationResourceName(config_name, selected)
             idx = self.IsOpened(tagname)
@@ -2711,11 +2688,13 @@
         # Open the filepath if defined
         if fileOpen is not None and os.path.isfile(fileOpen):
             # Create a new controller
-            self.Controler = PLCControler()
-            result = self.Controler.OpenXMLFile(fileOpen)
+            controler = PLCControler()
+            result = controler.OpenXMLFile(fileOpen)
             if result is None:
-            	self.LibraryPanel.SetControler(self.Controler)
-                self.PouInstanceVariablesPanel.SetController(self.Controler)
+                self.Controler = controler
+            	self.LibraryPanel.SetControler(controler)
+                self.ProjectTree.Enable(True)
+                self.PouInstanceVariablesPanel.SetController(controler)
                 self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
         
         # Define PLCOpenEditor icon
@@ -2826,11 +2805,13 @@
             filepath = dialog.GetPath()
             if os.path.isfile(filepath):
                 self.ResetView()
-                self.Controler = PLCControler()
-                result = self.Controler.OpenXMLFile(filepath)
+                controler = PLCControler()
+                result = controler.OpenXMLFile(filepath)
                 if result is None:
-                    self.LibraryPanel.SetControler(self.Controler)
-                    self.PouInstanceVariablesPanel.SetController(self.Controler)
+                    self.Controler = controler
+                    self.LibraryPanel.SetControler(controler)
+                    self.ProjectTree.Enable(True)
+                    self.PouInstanceVariablesPanel.SetController(controler)
                     self.LoadProjectOrganization()
                     self._Refresh(PROJECTTREE, LIBRARYTREE)
             self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
@@ -4254,11 +4235,12 @@
         items = [(idx, item) for idx, item in enumerate(self.Table.GetData())]
         items.reverse()
         for idx, item in items:
-            if self.GetDataType(item.GetVariable().upper()) is None:
+            iec_path = item.GetVariable().upper()
+            if self.GetDataType(iec_path) is None:
                 self.RemoveDataConsumer(item)
                 self.Table.RemoveItem(idx)
             else:
-                self.AddDataConsumer(iec_path.upper(), item)
+                self.AddDataConsumer(iec_path, item)
         self.Freeze()
         self.Table.ResetView(self.VariablesGrid)
         self.VariablesGrid.RefreshButtons()
--- a/TextViewer.py	Sat May 19 12:40:53 2012 +0200
+++ b/TextViewer.py	Mon May 21 09:59:44 2012 +0200
@@ -247,7 +247,8 @@
         return {"cursor_pos": self.Editor.GetCurrentPos()}
     
     def SetState(self, state):
-        self.Editor.GotoPos(state.get("cursor_pos", 0))
+        if self:
+            self.Editor.GotoPos(state.get("cursor_pos", 0))
         
     def OnModification(self, event):
         if not self.DisableEvents:
--- a/Viewer.py	Sat May 19 12:40:53 2012 +0200
+++ b/Viewer.py	Mon May 21 09:59:44 2012 +0200
@@ -691,9 +691,10 @@
                 "zoom": self.CurrentScale}
 
     def SetState(self, state):
-        self.SetScale(state["zoom"])
-        self.Scroll(*state["position"])
-        self.RefreshVisibleElements()
+        if self:
+            self.SetScale(state["zoom"])
+            self.Scroll(*state["position"])
+            self.RefreshVisibleElements()
         
     def GetLogicalDC(self, buffered=False):
         if buffered:
--- a/controls/CustomTree.py	Sat May 19 12:40:53 2012 +0200
+++ b/controls/CustomTree.py	Mon May 21 09:59:44 2012 +0200
@@ -27,12 +27,14 @@
         self.BackgroundAlign = wx.ALIGN_LEFT|wx.ALIGN_TOP
         
         self.AddMenu = None
+        self.Enabled = False
         
         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_SCROLL, self.OnScroll)
         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
     
     def SetBackgroundBitmap(self, bitmap, align):
@@ -42,6 +44,9 @@
     def SetAddMenu(self, add_menu):
         self.AddMenu = add_menu
     
+    def Enable(self, enabled):
+        self.Enabled = enabled
+    
     def GetBitmapRect(self):
         client_size = self.GetClientSize()
         bitmap_size = self.BackgroundBitmap.GetSize()
@@ -76,13 +81,19 @@
         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)
+        if self.Enabled:
+            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 OnScroll(self, event):
+        print "scroll event"
+        self.RefreshBackground(True)
         event.Skip()
 
     def OnResize(self, event):
--- a/controls/EditorPanel.py	Sat May 19 12:40:53 2012 +0200
+++ b/controls/EditorPanel.py	Mon May 21 09:59:44 2012 +0200
@@ -65,7 +65,7 @@
         elif self.VariableEditor is not None:
             self.Initialize(self.VariableEditor)
         elif self.Editor is not None:
-            self.Initialize(self.Editor)        
+            self.Initialize(self.Editor)
         
     def __init__(self, parent, tagname, window, controler, debug=False):
         self.ParentWindow = window
--- a/controls/PouInstanceVariablesPanel.py	Sat May 19 12:40:53 2012 +0200
+++ b/controls/PouInstanceVariablesPanel.py	Mon May 21 09:59:44 2012 +0200
@@ -48,6 +48,7 @@
               size=wx.Size(0, 28), style=wx.CB_READONLY)
         self.Bind(wx.EVT_COMBOBOX, self.OnInstanceChoiceChanged,
                 self.InstanceChoice)
+        self.InstanceChoice.Bind(wx.EVT_LEFT_DOWN, self.OnInstanceChoiceLeftDown)
         
         self.DebugButton = wx.lib.buttons.GenBitmapButton(
               name='DebugButton', parent=self, 
@@ -56,7 +57,7 @@
               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), 
@@ -66,12 +67,13 @@
                        CT.TR_HAS_VARIABLE_ROW_HEIGHT|
                        CT.TR_HIDE_ROOT|
                        CT.TR_NO_LINES|
-                       CT.TR_ALIGN_WINDOWS_RIGHT)
+                       getattr(CT, "TR_ALIGN_WINDOWS_RIGHT", CT.TR_ALIGN_WINDOWS))
         self.VariablesList.SetIndent(0)
         self.VariablesList.SetSpacing(5)
         self.VariablesList.DoSelectItem = lambda *x,**y:True
         self.VariablesList.Bind(CT.EVT_TREE_ITEM_ACTIVATED,
                 self.OnVariablesListItemActivated)
+        self.VariablesList.Bind(wx.EVT_LEFT_DOWN, self.OnVariablesListLeftDown)
         
         buttons_sizer = wx.FlexGridSizer(cols=3, hgap=0, rows=1, vgap=0)
         buttons_sizer.AddWindow(self.ParentButton, 0, border=0, flag=0)
@@ -106,7 +108,9 @@
     
     def SetController(self, controller):
         self.Controller = controller
-     
+    
+        self.RefreshView()
+    
     def SetPouType(self, tagname, pou_instance=None):
         self.PouTagName = tagname
         if pou_instance is not None:
@@ -115,6 +119,8 @@
         self.RefreshView()
     
     def ResetView(self):
+        self.Controller = None
+        
         self.PouTagName = None
         self.PouInfos = None
         self.PouInstance = None
@@ -124,6 +130,7 @@
     def RefreshView(self):
         self.VariablesList.DeleteAllItems()
         self.InstanceChoice.Clear()
+        self.InstanceChoice.SetValue("")
         
         if self.PouTagName is not None:
             self.PouInfos = self.Controller.GetPouVariables(self.PouTagName, self.Debug)
@@ -183,6 +190,8 @@
             instances = self.Controller.SearchPouInstances(self.PouTagName, self.Debug)
             for instance in instances:
                 self.InstanceChoice.Append(instance)
+            if len(instances) == 1:
+                self.PouInstance = instances[0]
             if self.PouInfos["class"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]:
                 self.PouInstance = None
                 self.InstanceChoice.SetSelection(0)
@@ -250,10 +259,21 @@
             event.Skip()
         return GraphButtonCallback
     
+    def ShowInstanceChoicePopup(self):
+        self.InstanceChoice.SetFocusFromKbd()
+        size = self.InstanceChoice.GetSize()
+        event = wx.MouseEvent(wx.EVT_LEFT_DOWN._getEvtType())
+        event.m_x = size.width / 2
+        event.m_y = size.height / 2
+        event.SetEventObject(self.InstanceChoice)
+        #event = wx.KeyEvent(wx.EVT_KEY_DOWN._getEvtType())
+        #event.m_keyCode = wx.WXK_SPACE
+        self.InstanceChoice.GetEventHandler().ProcessEvent(event)
+    
     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)
+            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)
@@ -277,7 +297,7 @@
             selected_item = event.GetItem()
             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 is not None and item_infos["class"] not in ITEMS_VARIABLE:
                     if item_infos["class"] == ITEM_RESOURCE:
                         tagname = self.Controller.ComputeConfigurationResourceName(
                                        instance_path, 
@@ -289,4 +309,10 @@
                     wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, tagname)
         event.Skip()
     
-    
+    def OnVariablesListLeftDown(self, event):
+        if self.InstanceChoice.GetSelection() == -1:
+            wx.CallAfter(self.ShowInstanceChoicePopup)
+        event.Skip()
+        
+    def OnInstanceChoiceLeftDown(self, event):
+        event.Skip()
--- a/graphics/FBD_Objects.py	Sat May 19 12:40:53 2012 +0200
+++ b/graphics/FBD_Objects.py	Mon May 21 09:59:44 2012 +0200
@@ -263,6 +263,7 @@
             self.Pen = MiterPen(self.Colour)
             
             # Extract the inputs properties and create or modify the corresponding connector
+            idx = 0
             for idx, (input_name, input_type, input_modifier) in enumerate(inputs):
                 if idx < len(self.Inputs):
                     connector = self.Inputs[idx]
@@ -280,6 +281,7 @@
             self.Inputs = self.Inputs[:idx + 1]
             
             # Extract the outputs properties and create or modify the corresponding connector
+            idx = 0
             for idx, (output_name, output_type, output_modifier) in enumerate(outputs):
                 if idx < len(self.Outputs):
                     connector = self.Outputs[idx]
--- a/plcopen/plcopen.py	Sat May 19 12:40:53 2012 +0200
+++ b/plcopen/plcopen.py	Mon May 21 09:59:44 2012 +0200
@@ -234,8 +234,10 @@
             self.contentHeader.setauthor(contentheader["authorName"])
         if contentheader.has_key("language"):
             self.contentHeader.setlanguage(contentheader["language"])
-        self.contentHeader.setpageSize(*contentheader["pageSize"])
-        self.contentHeader.setscaling(contentheader["scaling"])
+        if contentheader.has_key("pageSize"):
+            self.contentHeader.setpageSize(*contentheader["pageSize"])
+        if contentheader.has_key("scaling"):
+            self.contentHeader.setscaling(contentheader["scaling"])
     setattr(cls, "setcontentHeader", setcontentHeader)
     
     def getdataTypes(self):