IDEFrame.py
changeset 814 5743cbdff669
child 819 4424918efe8b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IDEFrame.py	Fri Sep 07 16:45:55 2012 +0200
@@ -0,0 +1,2553 @@
+
+import os, sys
+import cPickle
+from types import TupleType
+
+import wx, wx.grid
+import wx.aui
+
+from editors.EditorPanel import EditorPanel
+from editors.SFCViewer import SFC_Viewer
+from editors.LDViewer import LD_Viewer
+from editors.TextViewer import TextViewer
+from editors.Viewer import Viewer, ZOOM_FACTORS
+from editors.GraphicViewer import GraphicViewer
+from editors.ResourceEditor import ConfigurationEditor, ResourceEditor
+from editors.DataTypeEditor import DataTypeEditor
+from PLCControler import *
+from controls import CustomTree, LibraryPanel, PouInstanceVariablesPanel, DebugVariablePanel, SearchResultPanel
+from dialogs import ProjectDialog, PouTransitionDialog, PouActionDialog, FindInPouDialog
+from util.BitmapLibrary import GetBitmap
+
+# Define PLCOpenEditor controls id
+[ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, 
+ ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, 
+ 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 EditMenu extra items id
+[ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, ID_PLCOPENEDITOREDITMENUADDDATATYPE, 
+ ID_PLCOPENEDITOREDITMENUADDFUNCTION, ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, 
+ ID_PLCOPENEDITOREDITMENUADDPROGRAM, ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
+ ID_PLCOPENEDITOREDITMENUFINDNEXT, ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
+ ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, 
+] = [wx.NewId() for _init_coll_EditMenu_Items in range(9)]
+
+# Define PLCOpenEditor DisplayMenu extra items id
+[ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE, 
+] = [wx.NewId() for _init_coll_DisplayMenu_Items in range(1)]
+
+#-------------------------------------------------------------------------------
+#                            EditorToolBar definitions
+#-------------------------------------------------------------------------------
+
+# Define PLCOpenEditor Toolbar items id
+[ID_PLCOPENEDITOREDITORTOOLBARSELECTION, ID_PLCOPENEDITOREDITORTOOLBARCOMMENT,
+ ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, ID_PLCOPENEDITOREDITORTOOLBARBLOCK,
+ ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, ID_PLCOPENEDITOREDITORTOOLBARWIRE,
+ ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, ID_PLCOPENEDITOREDITORTOOLBARRUNG,
+ ID_PLCOPENEDITOREDITORTOOLBARCOIL, ID_PLCOPENEDITOREDITORTOOLBARCONTACT,
+ ID_PLCOPENEDITOREDITORTOOLBARBRANCH, ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP,
+ ID_PLCOPENEDITOREDITORTOOLBARSTEP, ID_PLCOPENEDITOREDITORTOOLBARTRANSITION,
+ ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK, ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE,
+ ID_PLCOPENEDITOREDITORTOOLBARJUMP, ID_PLCOPENEDITOREDITORTOOLBARMOTION, 
+] = [wx.NewId() for _init_coll_DefaultEditorToolBar_Items in range(18)]
+
+
+
+# Define behaviour of each Toolbar item according to current POU body type 
+# Informations meaning are in this order:
+#  - Item is toggled
+#  - PLCOpenEditor mode where item is displayed (could be more then one)
+#  - Item id
+#  - Item callback function name
+#  - Item icon filename
+#  - Item tooltip text
+EditorToolBarItems = {
+    "FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
+              "move", _("Move the view")),
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool",
+              "add_comment", _("Create a new comment")),
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool",
+              "add_variable", _("Create a new variable")),
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool",
+              "add_block", _("Create a new block")),
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool", 
+              "add_connection", _("Create a new connection"))],
+    "LD"  : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
+              "move", _("Move the view")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool", 
+              "add_comment", _("Create a new comment")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, "OnPowerRailTool", 
+              "add_powerrail", _("Create a new power rail")),
+             (False, DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARRUNG, "OnRungTool", 
+              "add_rung", _("Create a new rung")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCOIL, "OnCoilTool", 
+              "add_coil", _("Create a new coil")),
+             (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCONTACT, "OnContactTool", 
+              "add_contact", _("Create a new contact")),
+             (False, DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARBRANCH, "OnBranchTool", 
+              "add_branch", _("Create a new branch")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool", 
+              "add_variable", _("Create a new variable")),
+             (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool", 
+              "add_block", _("Create a new block")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool", 
+              "add_connection", _("Create a new connection"))],
+    "SFC" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
+              "move", _("Move the view")),
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool", 
+              "add_comment", _("Create a new comment")),
+             (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP, "OnInitialStepTool", 
+              "add_initial_step", _("Create a new initial step")),
+             (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARSTEP, "OnStepTool", 
+              "add_step", _("Create a new step")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARTRANSITION, "OnTransitionTool", 
+              "add_transition", _("Create a new transition")),
+             (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK, "OnActionBlockTool", 
+              "add_action", _("Create a new action block")),
+             (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE, "OnDivergenceTool", 
+              "add_divergence", _("Create a new divergence")),
+             (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARJUMP, "OnJumpTool", 
+              "add_jump", _("Create a new jump")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool", 
+              "add_variable", _("Create a new variable")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool", 
+              "add_block", _("Create a new block")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool", 
+              "add_connection", _("Create a new connection")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, "OnPowerRailTool", 
+              "add_powerrail", _("Create a new power rail")),
+             (True, FREEDRAWING_MODE, 
+              ID_PLCOPENEDITOREDITORTOOLBARCONTACT, "OnContactTool", 
+              "add_contact", _("Create a new contact"))],
+    "ST"  : [],
+    "IL"  : [],
+    "debug": [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
+              ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
+              "move", _("Move the view"))],
+}
+
+#-------------------------------------------------------------------------------
+#                               Helper Functions
+#-------------------------------------------------------------------------------
+
+import base64
+
+def EncodeFileSystemPath(path, use_base64=True):
+    path = path.encode(sys.getfilesystemencoding())
+    if use_base64:
+        return base64.encodestring(path)
+    return path
+
+def DecodeFileSystemPath(path, is_base64=True):
+    if is_base64:
+        path = base64.decodestring(path)
+    return unicode(path, sys.getfilesystemencoding())
+
+# Compatibility function for wx versions < 2.6
+def AppendMenu(parent, help, id, kind, text):
+    if wx.VERSION >= (2, 6, 0):
+        parent.Append(help=help, id=id, kind=kind, text=text)
+    else:
+        parent.Append(helpString=help, id=id, kind=kind, item=text)
+
+[TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, 
+ POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
+] = range(10)
+
+def GetShortcutKeyCallbackFunction(viewer_function):
+    def ShortcutKeyFunction(self, event):
+        control = self.FindFocus()
+        if control is not None and control.GetName() in ["Viewer", "TextViewer"]:
+            getattr(control.ParentWindow, viewer_function)()
+        elif isinstance(control, wx.stc.StyledTextCtrl):
+            getattr(control, viewer_function)()
+        elif isinstance(control, wx.TextCtrl):
+            control.ProcessEvent(event)
+    return ShortcutKeyFunction
+
+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:
+                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)
+        else:
+            self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")%name)
+    return DeleteElementFunction
+
+if wx.Platform == '__WXMSW__':
+    TAB_BORDER = 6
+    NOTEBOOK_BORDER = 6
+else:
+    TAB_BORDER = 7
+    NOTEBOOK_BORDER = 2
+
+def SimplifyTabLayout(tabs, rect):
+    for tab in tabs:
+        if tab["pos"][0] == rect.x:
+            others = [t for t in tabs if t != tab]
+            others.sort(lambda x,y: cmp(x["pos"][0], y["pos"][0]))
+            for other in others:
+                if (other["pos"][1] == tab["pos"][1] and 
+                    other["size"][1] == tab["size"][1] and
+                    other["pos"][0] == tab["pos"][0] + tab["size"][0] + TAB_BORDER):
+                    
+                    tab["size"] = (tab["size"][0] + other["size"][0] + TAB_BORDER, tab["size"][1])
+                    tab["pages"].extend(other["pages"])
+                    tabs.remove(other)
+                    
+                    if tab["size"][0] == rect.width:
+                        return True
+                    
+        elif tab["pos"][1] == rect.y:
+            others = [t for t in tabs if t != tab]
+            others.sort(lambda x,y: cmp(x["pos"][1], y["pos"][1]))
+            for other in others:
+                if (other["pos"][0] == tab["pos"][0] and 
+                    other["size"][0] == tab["size"][0] and
+                    other["pos"][1] == tab["pos"][1] + tab["size"][1] + TAB_BORDER):
+                    
+                    tab["size"] = (tab["size"][0], tab["size"][1] + other["size"][1] + TAB_BORDER)
+                    tab["pages"].extend(other["pages"])
+                    tabs.remove(other)
+                    
+                    if tab["size"][1] == rect.height:
+                        return True
+    return False
+    
+def ComputeTabsLayout(tabs, rect):
+    if len(tabs) == 0:
+        return tabs
+    if len(tabs) == 1:
+        return tabs[0]
+    split = None
+    for idx, tab in enumerate(tabs):
+        if len(tab["pages"]) == 0:
+            raise ValueError, "Not possible"
+        if tab["size"][0] == rect.width:
+            if tab["pos"][1] == rect.y:
+                split = (wx.TOP, float(tab["size"][1]) / float(rect.height))
+                split_rect = wx.Rect(rect.x, rect.y + tab["size"][1] + TAB_BORDER, 
+                                     rect.width, rect.height - tab["size"][1] - TAB_BORDER)
+            elif tab["pos"][1] == rect.height + 1 - tab["size"][1]:
+                split = (wx.BOTTOM, 1.0 - float(tab["size"][1]) / float(rect.height))
+                split_rect = wx.Rect(rect.x, rect.y, 
+                                     rect.width, rect.height - tab["size"][1] - TAB_BORDER)
+            break
+        elif tab["size"][1] == rect.height:
+            if tab["pos"][0] == rect.x:
+                split = (wx.LEFT, float(tab["size"][0]) / float(rect.width))
+                split_rect = wx.Rect(rect.x + tab["size"][0] + TAB_BORDER, rect.y, 
+                                     rect.width - tab["size"][0] - TAB_BORDER, rect.height)
+            elif tab["pos"][0] == rect.width + 1 - tab["size"][0]:
+                split = (wx.RIGHT, 1.0 - float(tab["size"][0]) / float(rect.width))
+                split_rect = wx.Rect(rect.x, rect.y, 
+                                     rect.width - tab["size"][0] - TAB_BORDER, rect.height)
+            break
+    if split != None:
+        split_tab = tabs.pop(idx)
+        return {"split": split,
+                "tab": split_tab, 
+                "others": ComputeTabsLayout(tabs, split_rect)}
+    else:
+        if SimplifyTabLayout(tabs, rect):
+            return ComputeTabsLayout(tabs, rect)
+    return tabs
+
+#-------------------------------------------------------------------------------
+#                              IDEFrame Base Class
+#-------------------------------------------------------------------------------
+
+UNEDITABLE_NAMES_DICT = dict([(_(name), name) for name in UNEDITABLE_NAMES])
+
+class IDEFrame(wx.Frame):
+    
+    Starting = False
+    
+    # Compatibility function for wx versions < 2.6
+    if wx.VERSION < (2, 6, 0):
+        def Bind(self, event, function, id = None):
+            if id is not None:
+                event(self, id, function)
+            else:
+                event(self, function)
+    
+    def _init_coll_MenuBar_Menus(self, parent):
+        parent.Append(menu=self.FileMenu, title=_(u'&File'))
+        parent.Append(menu=self.EditMenu, title=_(u'&Edit'))
+        parent.Append(menu=self.DisplayMenu, title=_(u'&Display'))
+        parent.Append(menu=self.HelpMenu, title=_(u'&Help'))
+
+    def _init_coll_FileMenu_Items(self, parent):
+        pass
+    
+    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,
+              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'))
+        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,
+              kind=wx.ITEM_NORMAL, text=_(u'Undo') + '\tCTRL+Z')
+        AppendMenu(parent, help='', id=wx.ID_REDO,
+              kind=wx.ITEM_NORMAL, text=_(u'Redo') + '\tCTRL+Y')
+        #AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO,
+        #      kind=wx.ITEM_CHECK, text=_(u'Enable Undo/Redo'))
+        enable_undo_redo = _(u'Enable Undo/Redo') # Keeping text in translations for possible menu reactivation
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=wx.ID_CUT,
+              kind=wx.ITEM_NORMAL, text=_(u'Cut') + '\tCTRL+X')
+        AppendMenu(parent, help='', id=wx.ID_COPY,
+              kind=wx.ITEM_NORMAL, text=_(u'Copy') + '\tCTRL+C')
+        AppendMenu(parent, help='', id=wx.ID_PASTE,
+              kind=wx.ITEM_NORMAL, text=_(u'Paste') + '\tCTRL+V')
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=wx.ID_FIND,
+              kind=wx.ITEM_NORMAL, text=_(u'Find') + '\tCTRL+F')
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDNEXT,
+              kind=wx.ITEM_NORMAL, text=_(u'Find Next') + '\tCTRL+K')
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
+              kind=wx.ITEM_NORMAL, text=_(u'Find Previous') + '\tCTRL+SHIFT+K')
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT,
+              kind=wx.ITEM_NORMAL, text=_(u'Search in Project') + '\tCTRL+SHIFT+F')
+        parent.AppendSeparator()
+        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,
+              kind=wx.ITEM_NORMAL, text=_(u'&Delete'))
+        self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
+        self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
+        #self.Bind(wx.EVT_MENU, self.OnEnableUndoRedoMenu, id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO)
+        self.Bind(wx.EVT_MENU, self.OnCutMenu, id=wx.ID_CUT)
+        self.Bind(wx.EVT_MENU, self.OnCopyMenu, id=wx.ID_COPY)
+        self.Bind(wx.EVT_MENU, self.OnPasteMenu, id=wx.ID_PASTE)
+        self.Bind(wx.EVT_MENU, self.OnFindMenu, id=wx.ID_FIND)
+        self.Bind(wx.EVT_MENU, self.OnFindNextMenu, 
+              id=ID_PLCOPENEDITOREDITMENUFINDNEXT)
+        self.Bind(wx.EVT_MENU, self.OnFindPreviousMenu, 
+              id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS)
+        self.Bind(wx.EVT_MENU, self.OnSearchInProjectMenu, 
+              id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT)
+        self.Bind(wx.EVT_MENU, self.OnSearchInProjectMenu, 
+              id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT)
+        self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu,
+              id=ID_PLCOPENEDITOREDITMENUADDDATATYPE)
+        self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("function"),
+              id=ID_PLCOPENEDITOREDITMENUADDFUNCTION)
+        self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("functionBlock"),
+              id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK)
+        self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("program"),
+              id=ID_PLCOPENEDITOREDITMENUADDPROGRAM)
+        self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu,
+              id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION)
+        self.Bind(wx.EVT_MENU, self.OnSelectAllMenu, id=wx.ID_SELECTALL)
+        self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE)
+        
+        self.AddToMenuToolBar([(wx.ID_UNDO, "undo", _(u'Undo'), None),
+                               (wx.ID_REDO, "redo", _(u'Redo'), None),
+                               None,
+                               (wx.ID_CUT, "cut", _(u'Cut'), None),
+                               (wx.ID_COPY, "copy", _(u'Copy'), None),
+                               (wx.ID_PASTE, "paste", _(u'Paste'), None),
+                               None,
+                               (ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, "find", _(u'Search in Project'), None)])
+
+    def _init_coll_DisplayMenu_Items(self, parent):
+        AppendMenu(parent, help='', id=wx.ID_REFRESH,
+              kind=wx.ITEM_NORMAL, text=_(u'Refresh') + '\tCTRL+R')
+        if self.EnableDebug:
+            AppendMenu(parent, help='', id=wx.ID_CLEAR,
+                  kind=wx.ITEM_NORMAL, text=_(u'Clear Errors') + '\tCTRL+K')
+        parent.AppendSeparator()
+        zoommenu = wx.Menu(title='')
+        parent.AppendMenu(wx.ID_ZOOM_FIT, _("Zoom"), zoommenu)
+        for idx, value in enumerate(ZOOM_FACTORS):
+            new_id = wx.NewId()
+            AppendMenu(zoommenu, help='', id=new_id,
+                  kind=wx.ITEM_RADIO, text=str(int(round(value * 100))) + "%")
+            self.Bind(wx.EVT_MENU, self.GenerateZoomFunction(idx), id=new_id)
+        
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE,
+              kind=wx.ITEM_NORMAL, text=_(u'Reset Perspective'))
+        self.Bind(wx.EVT_MENU, self.OnResetPerspective, id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE)
+        
+        self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
+        if self.EnableDebug:
+            self.Bind(wx.EVT_MENU, self.OnClearErrorsMenu, id=wx.ID_CLEAR)
+            
+    def _init_coll_HelpMenu_Items(self, parent):
+        pass
+
+    def _init_utils(self):
+        self.MenuBar = wx.MenuBar()
+
+        self.FileMenu = wx.Menu(title='')
+        self.EditMenu = wx.Menu(title='')
+        self.DisplayMenu = wx.Menu(title='')
+        self.HelpMenu = wx.Menu(title='')
+        
+        self._init_coll_MenuBar_Menus(self.MenuBar)
+        self._init_coll_FileMenu_Items(self.FileMenu)
+        self._init_coll_EditMenu_Items(self.EditMenu)
+        self._init_coll_DisplayMenu_Items(self.DisplayMenu)
+        self._init_coll_HelpMenu_Items(self.HelpMenu)
+
+    def _init_ctrls(self, prnt):
+        wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name='IDEFrame',
+              parent=prnt, pos=wx.DefaultPosition, size=wx.Size(1000, 600),
+              style=wx.DEFAULT_FRAME_STYLE)
+        self.SetClientSize(wx.Size(1000, 600))
+        self.Bind(wx.EVT_ACTIVATE, self.OnActivated)
+        self.Bind(wx.EVT_SIZE, self.OnResize)
+        
+        self.TabsImageList = wx.ImageList(31, 16)
+        self.TabsImageListIndexes = {}
+        
+        #-----------------------------------------------------------------------
+        #                          Creating main structure
+        #-----------------------------------------------------------------------
+        
+        self.AUIManager = wx.aui.AuiManager(self)
+        self.AUIManager.SetDockSizeConstraint(0.5, 0.5)
+        self.Panes = {}
+        
+        self.LeftNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORLEFTNOTEBOOK,
+              style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE|
+                    wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
+        self.LeftNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND, 
+                self.OnAllowNotebookDnD)
+        self.AUIManager.AddPane(self.LeftNoteBook, 
+              wx.aui.AuiPaneInfo().Name("ProjectPane").
+              Left().Layer(1).
+              BestSize(wx.Size(300, 500)).CloseButton(False))
+        
+        self.BottomNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORBOTTOMNOTEBOOK,
+              style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE|
+                    wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
+        self.BottomNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND, 
+                self.OnAllowNotebookDnD)
+        self.AUIManager.AddPane(self.BottomNoteBook, 
+              wx.aui.AuiPaneInfo().Name("ResultPane").
+              Bottom().Layer(0).
+              BestSize(wx.Size(800, 300)).CloseButton(False))
+        
+        self.RightNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORRIGHTNOTEBOOK,
+              style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE|
+                    wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE)
+        self.RightNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND, 
+                self.OnAllowNotebookDnD)
+        self.AUIManager.AddPane(self.RightNoteBook, 
+              wx.aui.AuiPaneInfo().Name("LibraryPane").
+              Right().Layer(0).
+              BestSize(wx.Size(250, 400)).CloseButton(False))
+        
+        self.TabsOpened = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORTABSOPENED, 
+              style=wx.aui.AUI_NB_DEFAULT_STYLE|wx.aui.AUI_NB_WINDOWLIST_BUTTON)
+        self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGING,
+              self.OnPouSelectedChanging)
+        self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED,
+              self.OnPouSelectedChanged)
+        self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE,
+              self.OnPageClose)
+        self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_END_DRAG,
+              self.OnPageDragged)
+        self.AUIManager.AddPane(self.TabsOpened, 
+              wx.aui.AuiPaneInfo().CentrePane().Name("TabsPane"))
+        
+        #-----------------------------------------------------------------------
+        #                    Creating PLCopen Project Types Tree
+        #-----------------------------------------------------------------------
+        
+        self.MainTabs = {}
+        
+        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(GetBitmap("custom_tree_background"),
+                                             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.OnProjectTreeRightUp,
+                  id=ID_PLCOPENEDITORPROJECTTREE)
+            self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnProjectTreeItemSelected,
+                  id=ID_PLCOPENEDITORPROJECTTREE)
+        else:
+            self.ProjectTree.Bind(wx.EVT_RIGHT_UP, self.OnProjectTreeRightUp)
+            self.ProjectTree.Bind(wx.EVT_LEFT_UP, 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 POU Instance Variables Panel
+        #-----------------------------------------------------------------------
+        
+        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
+        #-----------------------------------------------------------------------
+        
+        MenuToolBar = wx.ToolBar(self, ID_PLCOPENEDITOREDITORMENUTOOLBAR, wx.DefaultPosition, wx.DefaultSize,
+                wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER)
+        MenuToolBar.SetToolBitmapSize(wx.Size(25, 25))
+        MenuToolBar.Realize()
+        self.Panes["MenuToolBar"] = MenuToolBar
+        self.AUIManager.AddPane(MenuToolBar, wx.aui.AuiPaneInfo().
+                  Name("MenuToolBar").Caption(_("Menu ToolBar")).
+                  ToolbarPane().Top().
+                  LeftDockable(False).RightDockable(False))
+        
+        EditorToolBar = wx.ToolBar(self, ID_PLCOPENEDITOREDITORTOOLBAR, wx.DefaultPosition, wx.DefaultSize,
+                wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER)
+        EditorToolBar.SetToolBitmapSize(wx.Size(25, 25))
+        EditorToolBar.AddRadioTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, 
+              GetBitmap("select"), wx.NullBitmap, _("Select an object"))
+        EditorToolBar.Realize()
+        self.Panes["EditorToolBar"] = EditorToolBar
+        self.AUIManager.AddPane(EditorToolBar, wx.aui.AuiPaneInfo().
+                  Name("EditorToolBar").Caption(_("Editor ToolBar")).
+                  ToolbarPane().Top().Position(1).
+                  LeftDockable(False).RightDockable(False))
+            
+        self.Bind(wx.EVT_MENU, self.OnSelectionTool, 
+              id=ID_PLCOPENEDITOREDITORTOOLBARSELECTION)
+        
+        #-----------------------------------------------------------------------
+        #                            Creating Search Panel
+        #-----------------------------------------------------------------------
+        
+        self.SearchResultPanel = SearchResultPanel(self.BottomNoteBook, self)
+        self.MainTabs["SearchResultPanel"] = (self.SearchResultPanel, _("Search"))
+        self.BottomNoteBook.AddPage(*self.MainTabs["SearchResultPanel"])
+        
+        #-----------------------------------------------------------------------
+        #                            Creating Library Panel
+        #-----------------------------------------------------------------------
+        
+        self.LibraryPanel = LibraryPanel(self, True)
+        self.MainTabs["LibraryPanel"] = (self.LibraryPanel, _("Library"))
+        self.RightNoteBook.AddPage(*self.MainTabs["LibraryPanel"])
+                
+        self._init_utils()
+        self.SetMenuBar(self.MenuBar)
+                
+        if self.EnableDebug:
+            self.DebugVariablePanel = DebugVariablePanel(self.RightNoteBook, self.Controler)
+            self.MainTabs["DebugVariablePanel"] = (self.DebugVariablePanel, _("Debugger"))
+            self.RightNoteBook.AddPage(*self.MainTabs["DebugVariablePanel"])
+        
+        self.AUIManager.Update()
+    
+        self.FindDialog = FindInPouDialog(self)
+        self.FindDialog.Hide()
+    
+    ## Constructor of the PLCOpenEditor class.
+    #  @param parent The parent window.
+    #  @param controler The controler been used by PLCOpenEditor (default: None).
+    #  @param fileOpen The filepath to open if no controler defined (default: None).
+    #  @param debug The filepath to open if no controler defined (default: False).
+    def __init__(self, parent, enable_debug = False):
+        self.Controler = None
+        self.Config = wx.ConfigBase.Get()
+        self.EnableDebug = enable_debug
+        
+        self._init_ctrls(parent)
+        
+        # Define Tree item icon list
+        self.TreeImageList = wx.ImageList(16, 16)
+        self.TreeImageDict = {}
+        
+        # Icons for languages
+        for language in LANGUAGES:
+            self.TreeImageDict[language] = self.TreeImageList.Add(GetBitmap(language))
+            
+        # Icons for other items
+        for imgname, itemtype in [
+            #editables
+            ("PROJECT",        ITEM_PROJECT),
+            #("POU",            ITEM_POU),
+            #("VARIABLE",       ITEM_VARIABLE),
+            ("TRANSITION",     ITEM_TRANSITION),
+            ("ACTION",         ITEM_ACTION),
+            ("CONFIGURATION",  ITEM_CONFIGURATION),
+            ("RESOURCE",       ITEM_RESOURCE),
+            ("DATATYPE",       ITEM_DATATYPE),
+            # uneditables
+            ("DATATYPES",      ITEM_DATATYPES),
+            ("FUNCTION",       ITEM_FUNCTION),
+            ("FUNCTIONBLOCK",  ITEM_FUNCTIONBLOCK),
+            ("PROGRAM",        ITEM_PROGRAM),
+            ("VAR_LOCAL",      ITEM_VAR_LOCAL),
+            ("VAR_LOCAL",      ITEM_VAR_GLOBAL),
+            ("VAR_LOCAL",      ITEM_VAR_EXTERNAL),
+            ("VAR_LOCAL",      ITEM_VAR_TEMP),
+            ("VAR_INPUT",      ITEM_VAR_INPUT),
+            ("VAR_OUTPUT",     ITEM_VAR_OUTPUT),
+            ("VAR_INOUT",      ITEM_VAR_INOUT),
+            ("TRANSITIONS",    ITEM_TRANSITIONS),
+            ("ACTIONS",        ITEM_ACTIONS),
+            ("CONFIGURATIONS", ITEM_CONFIGURATIONS),
+            ("RESOURCES",      ITEM_RESOURCES),
+            ("PROPERTIES",     ITEM_PROPERTIES)]:
+            self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
+        
+        # Assign icon list to TreeCtrls
+        self.ProjectTree.SetImageList(self.TreeImageList)
+        self.PouInstanceVariablesPanel.SetTreeImageList(self.TreeImageList)
+        
+        self.CurrentEditorToolBar = []
+        self.CurrentMenu = None
+        self.SelectedItem = None
+        self.SearchParams = None
+        self.Highlights = {}
+        self.DrawingMode = FREEDRAWING_MODE
+        #self.DrawingMode = DRIVENDRAWING_MODE
+        self.AuiTabCtrl = []
+        self.DefaultPerspective = None
+        
+        # Initialize Printing configuring elements
+        self.PrintData = wx.PrintData()
+        self.PrintData.SetPaperId(wx.PAPER_A4)
+        self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER)
+        self.PageSetupData = wx.PageSetupDialogData(self.PrintData)
+        self.PageSetupData.SetMarginTopLeft(wx.Point(10, 15))
+        self.PageSetupData.SetMarginBottomRight(wx.Point(10, 20))
+        
+        self.SetRefreshFunctions()
+    
+    def __del__(self):
+        self.FindDialog.Destroy()
+    
+    def ResetStarting(self):
+        self.Starting = False
+    
+    def Show(self):
+        wx.Frame.Show(self)
+        wx.CallAfter(self.RestoreLastState)
+    
+    def OnActivated(self, event):
+        if event.GetActive():
+            wx.CallAfter(self._Refresh, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
+        event.Skip()
+
+#-------------------------------------------------------------------------------
+#                Saving and restoring frame organization functions
+#-------------------------------------------------------------------------------
+
+    def OnResize(self, event):
+        if self.Starting:
+            self.RestoreLastLayout()
+            if wx.Platform == '__WXMSW__':
+                wx.CallAfter(self.ResetStarting)
+            else:
+                self.ResetStarting()
+            wx.CallAfter(self.RefreshEditor)
+        event.Skip()
+    
+    def GetProjectConfiguration(self):
+        projects = {}
+        try:
+            if self.Config.HasEntry("projects"):
+                projects = cPickle.loads(str(self.Config.Read("projects")))
+        except:
+            pass
+        
+        return projects.get(
+            EncodeFileSystemPath(os.path.realpath(self.Controler.GetFilePath())), {})
+    
+    def SavePageState(self, page):
+        state = page.GetState()
+        if state is not None:
+            if self.Config.HasEntry("projects"):
+                projects = cPickle.loads(str(self.Config.Read("projects")))
+            else:
+                projects = {}
+            
+            project_infos = projects.setdefault(
+                 EncodeFileSystemPath(os.path.realpath(self.Controler.GetFilePath())), {})
+            editors_state = project_infos.setdefault("editors_state", {})
+            
+            if page.IsDebugging():
+                editors_state[page.GetInstancePath()] = state
+            else:
+                editors_state[page.GetTagName()] = state
+            
+            self.Config.Write("projects", cPickle.dumps(projects))
+            self.Config.Flush()
+    
+    def GetTabInfos(self, tab):
+        if isinstance(tab, EditorPanel):
+            if tab.IsDebugging():
+                return ("debug", tab.GetInstancePath())
+            else:
+                return ("editor", tab.GetTagName())
+        else:
+            for page_name, (page_ref, page_title) in self.MainTabs.iteritems():
+                if page_ref == tab:
+                    return ("main", page_name)
+        return None
+    
+    def SaveTabLayout(self, notebook):
+        tabs = []
+        for child in notebook.GetChildren():
+            if isinstance(child, wx.aui.AuiTabCtrl):
+                if child.GetPageCount() > 0:
+                    pos = child.GetPosition()
+                    tab = {"pos": (pos.x, pos.y), "pages": []}
+                    tab_size = child.GetSize()
+                    for page_idx in xrange(child.GetPageCount()):
+                        page = child.GetWindowFromIdx(page_idx)
+                        if not tab.has_key("size"):
+                            tab["size"] = (tab_size[0], tab_size[1] + page.GetSize()[1])
+                        tab_infos = self.GetTabInfos(page)
+                        if tab_infos is not None:
+                            tab["pages"].append((tab_infos, page_idx == child.GetActivePage()))
+                    tabs.append(tab)
+        tabs.sort(lambda x, y: cmp(x["pos"], y["pos"]))
+        size = notebook.GetSize()
+        return ComputeTabsLayout(tabs, wx.Rect(1, 1, size[0] - NOTEBOOK_BORDER, size[1] - NOTEBOOK_BORDER))
+    
+    def LoadTab(self, notebook, page_infos):
+        if page_infos[0] == "main":
+            infos = self.MainTabs.get(page_infos[1])
+            if infos is not None:
+                page_ref, page_title = infos
+                notebook.AddPage(page_ref, page_title)
+                return notebook.GetPageIndex(page_ref)
+        elif page_infos[0] == "editor":
+            tagname = page_infos[1]
+            page_ref = self.EditProjectElement(self.Controler.GetElementType(tagname), tagname)
+            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, self.EnableDebug)
+            if instance_infos is not None:
+                return notebook.GetPageIndex(self.OpenDebugViewer(instance_infos["class"], instance_path, instance_infos["type"]))
+        return None
+            
+    def LoadTabLayout(self, notebook, tabs, mode="all", first_index=None):
+        if isinstance(tabs, ListType):
+            if len(tabs) == 0:
+                return
+            raise ValueError, "Not supported"
+        
+        if tabs.has_key("split"):
+            self.LoadTabLayout(notebook, tabs["others"])
+            
+            split_dir, split_ratio = tabs["split"]
+            first_index = self.LoadTabLayout(notebook, tabs["tab"], mode="first")
+            notebook.Split(first_index, split_dir)
+            self.LoadTabLayout(notebook, tabs["tab"], mode="others", first_index=first_index)
+            
+        elif mode == "first":
+            return self.LoadTab(notebook, tabs["pages"][0][0])
+        else:
+            selected = first_index
+            if mode == "others":
+                add_tabs = tabs["pages"][1:]
+            else:
+                add_tabs = tabs["pages"]
+            for page_infos, page_selected in add_tabs:
+                page_idx = self.LoadTab(notebook, page_infos)
+                if page_selected:
+                    selected = page_idx
+            if selected is not None:
+                wx.CallAfter(notebook.SetSelection, selected)
+    
+    def ResetPerspective(self):
+        if self.DefaultPerspective is not None:
+            self.AUIManager.LoadPerspective(self.DefaultPerspective["perspective"])
+        
+            for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
+                for idx in xrange(notebook.GetPageCount()):
+                    notebook.RemovePage(0)
+                        
+            notebooks = self.DefaultPerspective["notebooks"]
+            for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
+                                         (self.BottomNoteBook, "bottomnotebook"),
+                                         (self.RightNoteBook, "rightnotebook")]:
+                self.LoadTabLayout(notebook, notebooks.get(entry_name))
+    
+            self._Refresh(EDITORTOOLBAR)
+    
+    def RestoreLastState(self):
+        frame_size = None
+        if self.Config.HasEntry("framesize"):
+            frame_size = cPickle.loads(str(self.Config.Read("framesize")))
+        
+        self.Starting = True
+        if frame_size is None:
+            self.Maximize()
+        else:
+            self.SetClientSize(frame_size)
+        
+    def RestoreLastLayout(self):
+        notebooks = {}
+        for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
+                                     (self.BottomNoteBook, "bottomnotebook"),
+                                     (self.RightNoteBook, "rightnotebook")]:
+            notebooks[entry_name] = self.SaveTabLayout(notebook)
+        self.DefaultPerspective = {
+            "perspective": self.AUIManager.SavePerspective(),
+            "notebooks": notebooks,
+        }
+        
+        try:
+            if self.Config.HasEntry("perspective"):
+                self.AUIManager.LoadPerspective(unicode(self.Config.Read("perspective")))
+        
+            if self.Config.HasEntry("notebooks"):
+                notebooks = cPickle.loads(str(self.Config.Read("notebooks")))
+                
+                for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
+                    for idx in xrange(notebook.GetPageCount()):
+                        notebook.RemovePage(0)
+                        
+                for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
+                                             (self.BottomNoteBook, "bottomnotebook"),
+                                             (self.RightNoteBook, "rightnotebook")]:
+                    self.LoadTabLayout(notebook, notebooks.get(entry_name))
+        except:
+            self.ResetPerspective()
+        
+        self.LoadProjectLayout()
+        
+        self._Refresh(EDITORTOOLBAR)
+    
+    def SaveLastState(self):
+        if not self.IsMaximized():
+            self.Config.Write("framesize", cPickle.dumps(self.GetClientSize()))
+        elif self.Config.HasEntry("framesize"):
+            self.Config.DeleteEntry("framesize")
+        
+        notebooks = {}
+        for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
+                                     (self.BottomNoteBook, "bottomnotebook"),
+                                     (self.RightNoteBook, "rightnotebook")]:
+            notebooks[entry_name] = self.SaveTabLayout(notebook)
+        self.Config.Write("notebooks", cPickle.dumps(notebooks))
+        
+        pane = self.AUIManager.GetPane(self.TabsOpened)
+        if pane.IsMaximized():
+            self.AUIManager.RestorePane(pane)
+        self.Config.Write("perspective", self.AUIManager.SavePerspective())
+    
+        self.SaveProjectLayout()
+        
+        for i in xrange(self.TabsOpened.GetPageCount()):
+            self.SavePageState(self.TabsOpened.GetPage(i))
+        
+        self.Config.Flush()
+
+    def SaveProjectLayout(self):
+        if self.Controler is not None:
+            tabs = []
+            
+            projects = {}
+            try:
+                 if self.Config.HasEntry("projects"):
+                    projects = cPickle.loads(str(self.Config.Read("projects")))
+            except:
+                pass
+            
+            project_infos = projects.setdefault(
+                 EncodeFileSystemPath(os.path.realpath(self.Controler.GetFilePath())), {})
+            project_infos["tabs"] = self.SaveTabLayout(self.TabsOpened)
+            if self.EnableDebug:
+                project_infos["debug_vars"] = self.DebugVariablePanel.GetDebugVariables()
+            
+            self.Config.Write("projects", cPickle.dumps(projects))
+            self.Config.Flush()
+    
+    def LoadProjectLayout(self):
+        if self.Controler is not None:
+            project = self.GetProjectConfiguration()
+            
+            try:
+                if project.has_key("tabs"):
+                    self.LoadTabLayout(self.TabsOpened, project["tabs"])
+            except:
+                self.DeleteAllPages()
+                
+            if self.EnableDebug:
+                try:
+                    for variable in project.get("debug_vars", []):
+                        self.DebugVariablePanel.InsertValue(variable, force=True)
+                except:
+                    self.DebugVariablePanel.ResetGrid()
+            
+#-------------------------------------------------------------------------------
+#                               General Functions
+#-------------------------------------------------------------------------------
+
+    def SetRefreshFunctions(self):
+        self.RefreshFunctions = {
+            TITLE : self.RefreshTitle,
+            EDITORTOOLBAR : self.RefreshEditorToolBar,
+            FILEMENU : self.RefreshFileMenu,
+            EDITMENU : self.RefreshEditMenu,
+            DISPLAYMENU : self.RefreshDisplayMenu,
+            PROJECTTREE : self.RefreshProjectTree,
+            POUINSTANCEVARIABLESPANEL : self.RefreshPouInstanceVariablesPanel, 
+            LIBRARYTREE : self.RefreshLibraryPanel,
+            SCALING : self.RefreshScaling,
+            PAGETITLES: self.RefreshPageTitles}
+
+    ## Call PLCOpenEditor refresh functions.
+    #  @param elements List of elements to refresh.
+    def _Refresh(self, *elements):
+        try:
+            for element in elements:
+                self.RefreshFunctions[element]()
+        except wx.PyDeadObjectError:
+            # ignore exceptions caused by refresh while quitting
+            pass
+
+    ## Callback function when AUINotebook Page closed with CloseButton
+    #  @param event AUINotebook Event.
+    def OnPageClose(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected > -1:
+            window = self.TabsOpened.GetPage(selected)
+            
+            if window.CheckSaveBeforeClosing():
+                self.SavePageState(window)
+                
+                # Refresh all window elements that have changed
+                wx.CallAfter(self._Refresh, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
+                wx.CallAfter(self.RefreshTabCtrlEvent)
+                wx.CallAfter(self.CloseFindInPouDialog)
+                event.Skip()
+            else:
+                event.Veto()
+        
+
+    def GetCopyBuffer(self):
+        data = None
+        if wx.TheClipboard.Open():
+            dataobj = wx.TextDataObject()
+            if wx.TheClipboard.GetData(dataobj):
+                data = dataobj.GetText()
+            wx.TheClipboard.Close()
+        return data
+        
+    def SetCopyBuffer(self, text):
+        if wx.TheClipboard.Open():
+            data = wx.TextDataObject()
+            data.SetText(text)
+            wx.TheClipboard.SetData(data)
+            wx.TheClipboard.Flush()
+            wx.TheClipboard.Close()
+        self.RefreshEditMenu()
+
+    def GetDrawingMode(self):
+        return self.DrawingMode
+
+    def RefreshScaling(self):
+        for i in xrange(self.TabsOpened.GetPageCount()):
+            editor = self.TabsOpened.GetPage(i)
+            editor.RefreshScaling()
+
+    def EditProjectSettings(self):
+        old_values = self.Controler.GetProjectProperties()
+        dialog = ProjectDialog(self)
+        dialog.SetValues(old_values)
+        if dialog.ShowModal() == wx.ID_OK:
+            new_values = dialog.GetValues()
+            new_values["creationDateTime"] = old_values["creationDateTime"]
+            if new_values != old_values:
+                self.Controler.SetProjectProperties(None, new_values)
+                self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, 
+                              PROJECTTREE, POUINSTANCEVARIABLESPANEL, SCALING)
+        dialog.Destroy()
+
+#-------------------------------------------------------------------------------
+#                            Notebook Unified Functions
+#-------------------------------------------------------------------------------
+    
+    ## Function that add a tab in Notebook, calling refresh for tab DClick event
+    # for wx.aui.AUINotebook.
+    #  @param window Panel to display in tab.
+    #  @param text title for the tab ctrl.
+    def AddPage(self, window, text):
+        self.TabsOpened.AddPage(window, text)
+        self.RefreshTabCtrlEvent()
+    
+    ## Function that add a tab in Notebook, calling refresh for tab DClick event
+    # for wx.aui.AUINotebook.
+    #  @param window Panel to display in tab.
+    #  @param text title for the tab ctrl.
+    def DeletePage(self, window):
+        for idx in xrange(self.TabsOpened.GetPageCount()):
+            if self.TabsOpened.GetPage(idx) == window:
+                self.TabsOpened.DeletePage(idx)
+                self.RefreshTabCtrlEvent()
+                return 
+        
+    ## Function that fix difference in deleting all tabs between 
+    # wx.Notebook and wx.aui.AUINotebook.
+    def DeleteAllPages(self):
+        for idx in xrange(self.TabsOpened.GetPageCount()):
+            self.TabsOpened.DeletePage(0)
+        self.RefreshTabCtrlEvent()
+
+    ## Function that fix difference in setting picture on tab between 
+    # wx.Notebook and wx.aui.AUINotebook.
+    #  @param idx Tab index.
+    #  @param bitmap wx.Bitmap to define on tab.
+    #  @return True if operation succeeded
+    def SetPageBitmap(self, idx, bitmap):
+        return self.TabsOpened.SetPageBitmap(idx, bitmap)
+
+#-------------------------------------------------------------------------------
+#                         Dialog Message Functions
+#-------------------------------------------------------------------------------
+
+    ## Function displaying an Error dialog in PLCOpenEditor.
+    #  @param message The message to display.
+    def ShowErrorMessage(self, message):
+        dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
+        dialog.ShowModal()
+        dialog.Destroy()
+
+    ## Function displaying an Error dialog in PLCOpenEditor.
+    #  @return False if closing cancelled.
+    def CheckSaveBeforeClosing(self, title=_("Close Project")):
+        if not self.Controler.ProjectIsSaved():
+            dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), title, wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
+            answer = dialog.ShowModal()
+            dialog.Destroy()
+            if answer == wx.ID_YES:
+                self.SaveProject()
+            elif answer == wx.ID_CANCEL:
+                return False
+        
+        for idx in xrange(self.TabsOpened.GetPageCount()):
+            window = self.TabsOpened.GetPage(idx)
+            if not window.CheckSaveBeforeClosing():
+                return False
+        
+        return True
+
+#-------------------------------------------------------------------------------
+#                            File Menu Functions
+#-------------------------------------------------------------------------------
+
+    def RefreshFileMenu(self):
+        pass
+
+    def ResetView(self):
+        self.DeleteAllPages()
+        self.ProjectTree.DeleteAllItems()
+        self.ProjectTree.Enable(False)
+        self.PouInstanceVariablesPanel.ResetView()
+        self.LibraryPanel.ResetTree()
+        self.LibraryPanel.SetController(None)
+        if self.EnableDebug:
+            self.DebugVariablePanel.ResetGrid()
+        self.Controler = None
+
+    def OnCloseTabMenu(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected >= 0:
+            self.TabsOpened.DeletePage(selected)
+            if self.TabsOpened.GetPageCount() > 0:
+                new_index = min(selected, self.TabsOpened.GetPageCount() - 1)
+                self.TabsOpened.SetSelection(new_index)
+        # Refresh all window elements that have changed
+        self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
+        self.RefreshTabCtrlEvent()
+
+    def OnPageSetupMenu(self, event):
+        dialog = wx.PageSetupDialog(self, self.PageSetupData)
+        if dialog.ShowModal() == wx.ID_OK:
+            self.PageSetupData = wx.PageSetupDialogData(dialog.GetPageSetupData())
+            self.PrintData = wx.PrintData(self.PageSetupData.GetPrintData())
+        dialog.Destroy()
+
+    def OnPreviewMenu(self, event):
+        selected = self.TabsOpened.GetSelection()        
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            data = wx.PrintDialogData(self.PrintData)
+            properties = self.Controler.GetProjectProperties(window.IsDebugging())
+            page_size = map(int, properties["pageSize"])
+            margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
+            printout = GraphicPrintout(window, page_size, margins, True)
+            printout2 = GraphicPrintout(window, page_size, margins, True)
+            preview = wx.PrintPreview(printout, printout2, data)
+
+            if preview.Ok():
+                preview_frame = wx.PreviewFrame(preview, self, _("Print preview"), style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT)
+
+                preview_frame.Initialize()
+                
+                preview_canvas = preview.GetCanvas()
+                preview_canvas.SetMinSize(preview_canvas.GetVirtualSize())
+                preview_frame.Fit()
+                
+                preview_frame.Show(True)
+
+    def OnPrintMenu(self, event):
+        selected = self.TabsOpened.GetSelection()        
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            dialog_data = wx.PrintDialogData(self.PrintData)
+            dialog_data.SetToPage(1)
+            properties = self.Controler.GetProjectProperties(window.IsDebugging())
+            page_size = map(int, properties["pageSize"])
+            margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
+            printer = wx.Printer(dialog_data)
+            printout = GraphicPrintout(window, page_size, margins)
+            
+            if not printer.Print(self, printout, True) and printer.GetLastError() != wx.PRINTER_CANCELLED:
+                self.ShowErrorMessage(_("There was a problem printing.\nPerhaps your current printer is not set correctly?"))
+            printout.Destroy()
+
+    def OnPropertiesMenu(self, event):
+        self.EditProjectSettings()
+
+    def OnQuitMenu(self, event):
+        self.Close()
+
+#-------------------------------------------------------------------------------
+#                            Edit Menu Functions
+#-------------------------------------------------------------------------------
+
+    def RefreshEditMenu(self):
+        MenuToolBar = self.Panes["MenuToolBar"]
+        if self.Controler is not None:
+            selected = self.TabsOpened.GetSelection()
+            if selected > -1:
+                window = self.TabsOpened.GetPage(selected)
+                undo, redo = window.GetBufferState()
+            else:
+                undo, redo = self.Controler.GetBufferState()
+            self.EditMenu.Enable(wx.ID_UNDO, undo)
+            MenuToolBar.EnableTool(wx.ID_UNDO, undo)
+            self.EditMenu.Enable(wx.ID_REDO, redo)
+            MenuToolBar.EnableTool(wx.ID_REDO, redo)
+            #self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, True)
+            #self.EditMenu.Check(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, 
+            #                self.Controler.IsProjectBufferEnabled())
+            self.EditMenu.Enable(wx.ID_FIND, selected > -1)
+            self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDNEXT, 
+                  selected > -1 and self.SearchParams is not None)
+            self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS, 
+                  selected > -1 and self.SearchParams is not None)
+            self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
+            MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
+            self.EditMenu.Enable(wx.ID_ADD, True)
+            self.EditMenu.Enable(wx.ID_DELETE, True)
+            if self.TabsOpened.GetPageCount() > 0:
+                self.EditMenu.Enable(wx.ID_CUT, True)
+                MenuToolBar.EnableTool(wx.ID_CUT, True)
+                self.EditMenu.Enable(wx.ID_COPY, True)
+                MenuToolBar.EnableTool(wx.ID_COPY, True)
+                if self.GetCopyBuffer() is not None:
+                    self.EditMenu.Enable(wx.ID_PASTE, True)
+                    MenuToolBar.EnableTool(wx.ID_PASTE, True)
+                else:
+                    self.EditMenu.Enable(wx.ID_PASTE, False)
+                    MenuToolBar.EnableTool(wx.ID_PASTE, False)
+                self.EditMenu.Enable(wx.ID_SELECTALL, True)
+            else:
+                self.EditMenu.Enable(wx.ID_CUT, False)
+                MenuToolBar.EnableTool(wx.ID_CUT, False)
+                self.EditMenu.Enable(wx.ID_COPY, False)
+                MenuToolBar.EnableTool(wx.ID_COPY, False)
+                self.EditMenu.Enable(wx.ID_PASTE, False)
+                MenuToolBar.EnableTool(wx.ID_PASTE, False)
+                self.EditMenu.Enable(wx.ID_SELECTALL, False)
+        else:
+            self.EditMenu.Enable(wx.ID_UNDO, False)
+            MenuToolBar.EnableTool(wx.ID_UNDO, False)
+            self.EditMenu.Enable(wx.ID_REDO, False)
+            MenuToolBar.EnableTool(wx.ID_REDO, False)
+            #self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, False)
+            self.EditMenu.Enable(wx.ID_CUT, False)
+            MenuToolBar.EnableTool(wx.ID_CUT, False)
+            self.EditMenu.Enable(wx.ID_COPY, False)
+            MenuToolBar.EnableTool(wx.ID_COPY, False)
+            self.EditMenu.Enable(wx.ID_PASTE, False)
+            MenuToolBar.EnableTool(wx.ID_PASTE, False)
+            self.EditMenu.Enable(wx.ID_SELECTALL, False)
+            self.EditMenu.Enable(wx.ID_FIND, False)
+            self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDNEXT, False)
+            self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS, False)
+            self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
+            MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
+            self.EditMenu.Enable(wx.ID_ADD, False)
+            self.EditMenu.Enable(wx.ID_DELETE, False)
+    
+    def CloseTabsWithoutModel(self, refresh=True):
+        idxs = range(self.TabsOpened.GetPageCount())
+        idxs.reverse()
+        for idx in idxs:
+            window = self.TabsOpened.GetPage(idx)
+            if window.HasNoModel():
+                self.TabsOpened.DeletePage(idx)
+        if refresh:
+            self.RefreshEditor()
+
+    def OnUndoMenu(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            window.Undo()
+        else:
+            self.Controler.LoadPrevious()
+        self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, 
+                      SCALING, PAGETITLES)    
+    
+    def OnRedoMenu(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            window.Redo()
+        else:
+            self.Controler.LoadNext()
+        self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, 
+                      SCALING, PAGETITLES)
+    
+    def OnEnableUndoRedoMenu(self, event):
+        self.Controler.EnableProjectBuffer(event.IsChecked())
+        self.RefreshEditMenu()
+
+    OnCutMenu = GetShortcutKeyCallbackFunction("Cut")
+    OnCopyMenu = GetShortcutKeyCallbackFunction("Copy")
+    OnPasteMenu = GetShortcutKeyCallbackFunction("Paste")
+
+    def OnSelectAllMenu(self, event):
+        control = self.FindFocus()
+        if control is not None and control.GetName() == "Viewer":
+            control.Parent.SelectAll()
+        elif isinstance(control, wx.stc.StyledTextCtrl):
+            control.SelectAll()
+        elif isinstance(control, wx.TextCtrl):
+            control.SetSelection(0, control.GetLastPosition())
+        elif isinstance(control, wx.ComboBox):
+            control.SetMark(0, control.GetLastPosition() + 1)
+    
+    DeleteFunctions = {
+        ITEM_DATATYPE: GetDeleteElementFunction(PLCControler.ProjectRemoveDataType, check_function=PLCControler.DataTypeIsUsed),
+        ITEM_POU: GetDeleteElementFunction(PLCControler.ProjectRemovePou, check_function=PLCControler.PouIsUsed),
+        ITEM_TRANSITION: GetDeleteElementFunction(PLCControler.ProjectRemovePouTransition, ITEM_POU),
+        ITEM_ACTION: GetDeleteElementFunction(PLCControler.ProjectRemovePouAction, ITEM_POU),
+        ITEM_CONFIGURATION: GetDeleteElementFunction(PLCControler.ProjectRemoveConfiguration),
+        ITEM_RESOURCE: GetDeleteElementFunction(PLCControler.ProjectRemoveConfigurationResource, ITEM_CONFIGURATION)
+    }
+    
+    def OnDeleteMenu(self, event):
+        window = self.FindFocus()
+        if window == self.ProjectTree or window is None:
+            selected = self.ProjectTree.GetSelection()
+            if selected.IsOk():
+                function = self.DeleteFunctions.get(self.ProjectTree.GetPyData(selected)["type"], None)
+                if function is not None:
+                    function(self, selected)
+                    self.CloseTabsWithoutModel()
+                    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
+            window.ProcessEvent(event)
+
+    def OnFindMenu(self, event):
+        if not self.FindDialog.IsShown():
+            self.FindDialog.Show()
+    
+    def CloseFindInPouDialog(self):
+        selected = self.TabsOpened.GetSelection()
+        if selected == -1 and self.FindDialog.IsShown():
+            self.FindDialog.Hide()
+    
+    def OnFindNextMenu(self, event):
+        self.FindInPou(1)
+    
+    def OnFindPreviousMenu(self, event):
+        self.FindInPou(-1)
+    
+    def FindInPou(self, direction, search_params=None):
+        if search_params is not None:
+            self.SearchParams = search_params
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            window.Find(direction, self.SearchParams)
+    
+    def OnSearchInProjectMenu(self, event):
+        dialog = SearchInProjectDialog(self)
+        if dialog.ShowModal() == wx.ID_OK:
+            criteria = dialog.GetCriteria()
+            result = self.Controler.SearchInProject(criteria)
+            self.ClearSearchResults()
+            self.SearchResultPanel.SetSearchResults(criteria, result)
+            self.BottomNoteBook.SetSelection(self.BottomNoteBook.GetPageIndex(self.SearchResultPanel))
+            
+#-------------------------------------------------------------------------------
+#                             Display Menu Functions
+#-------------------------------------------------------------------------------
+
+    def RefreshDisplayMenu(self):
+        if self.Controler is not None:
+            if self.TabsOpened.GetPageCount() > 0:
+                self.DisplayMenu.Enable(wx.ID_REFRESH, True)
+                selected = self.TabsOpened.GetSelection()
+                if selected != -1:
+                    window = self.TabsOpened.GetPage(selected)
+                    if isinstance(window, Viewer):
+                        self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, True)
+                        zoommenu = self.DisplayMenu.FindItemById(wx.ID_ZOOM_FIT).GetSubMenu()
+                        zoomitem = zoommenu.FindItemByPosition(window.GetScale())
+                        zoomitem.Check(True)
+                    else:
+                        self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
+                else:
+                    self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
+            else:
+                self.DisplayMenu.Enable(wx.ID_REFRESH, False)
+                self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
+            if self.EnableDebug:
+                self.DisplayMenu.Enable(wx.ID_CLEAR, True)
+        else:
+            self.DisplayMenu.Enable(wx.ID_REFRESH, False)
+            if self.EnableDebug:
+                self.DisplayMenu.Enable(wx.ID_CLEAR, False)
+            self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
+        
+    def OnRefreshMenu(self, event):
+        self.RefreshEditor()
+
+    def OnClearErrorsMenu(self, event):
+        self.ClearErrors()
+
+    def GenerateZoomFunction(self, idx):
+        def ZoomFunction(event):
+            selected = self.TabsOpened.GetSelection()
+            if selected != -1:
+                window = self.TabsOpened.GetPage(selected)
+                window.SetScale(idx)
+                window.RefreshVisibleElements()
+                window.RefreshScrollBars()
+            event.Skip()
+        return ZoomFunction
+
+    def OnResetPerspective(self, event):
+        self.ResetPerspective()
+
+#-------------------------------------------------------------------------------
+#                      Project Editor Panels Management Functions
+#-------------------------------------------------------------------------------
+    
+    def OnPageDragged(self, event):
+        wx.CallAfter(self.RefreshTabCtrlEvent)
+        event.Skip()
+    
+    def OnAllowNotebookDnD(self, event):
+        event.Allow()
+    
+    def RefreshTabCtrlEvent(self):
+        auitabctrl = []
+        for child in self.TabsOpened.GetChildren():
+            if isinstance(child, wx.aui.AuiTabCtrl):
+                auitabctrl.append(child)
+                if child not in self.AuiTabCtrl:
+                    child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child))
+        self.AuiTabCtrl = auitabctrl
+        if self.TabsOpened.GetPageCount() == 0:
+            pane = self.AUIManager.GetPane(self.TabsOpened)
+            if pane.IsMaximized():
+                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()
+            if selected >= 0:
+                window = self.TabsOpened.GetPage(selected)
+                if not window.IsDebugging():
+                    window.ResetBuffer()
+        event.Skip()
+    
+    def OnPouSelectedChanged(self, event):
+        if not self.Starting:
+            selected = self.TabsOpened.GetSelection()
+            if selected >= 0:
+                window = self.TabsOpened.GetPage(selected)
+                tagname = window.GetTagName()
+                if not window.IsDebugging():
+                    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()
+        
+    def RefreshEditor(self):
+        selected = self.TabsOpened.GetSelection()
+        if selected >= 0:
+            window = self.TabsOpened.GetPage(selected)
+            tagname = window.GetTagName()
+            if not window.IsDebugging():
+                self.SelectProjectTreeItem(tagname)
+                self.PouInstanceVariablesPanel.SetPouType(tagname)
+            else:
+                instance_path = window.GetInstancePath()
+                if tagname == "":
+                    instance_path = instance_path.rsplit(".", 1)[0]
+                    tagname = self.Controler.GetPouInstanceTagName(instance_path, self.EnableDebug)
+                self.PouInstanceVariablesPanel.SetPouType(tagname, instance_path)
+            for child in self.TabsOpened.GetChildren():
+                if isinstance(child, wx.aui.AuiTabCtrl):
+                    active_page = child.GetActivePage()
+                    if active_page >= 0:
+                        window = child.GetWindowFromIdx(active_page)
+                        window.RefreshView()
+            self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
+    
+    def RefreshEditorNames(self, old_tagname, new_tagname):
+        for i in xrange(self.TabsOpened.GetPageCount()):
+            editor = self.TabsOpened.GetPage(i)
+            if editor.GetTagName() == old_tagname:
+                editor.SetTagName(new_tagname)
+    
+    def IsOpened(self, tagname):
+        for idx in xrange(self.TabsOpened.GetPageCount()):
+            if self.TabsOpened.GetPage(idx).IsViewing(tagname):
+                return idx
+        return None
+
+    def RefreshPageTitles(self):
+        for idx in xrange(self.TabsOpened.GetPageCount()):
+            window = self.TabsOpened.GetPage(idx)
+            icon = window.GetIcon()
+            if icon is not None:
+                self.SetPageBitmap(idx, icon)
+            self.TabsOpened.SetPageText(idx, window.GetTitle())
+
+    def GetTabsOpenedDClickFunction(self, tabctrl):
+        def OnTabsOpenedDClick(event):
+            pos = event.GetPosition()
+            if tabctrl.TabHitTest(pos.x, pos.y, None):
+                pane = self.AUIManager.GetPane(self.TabsOpened)
+                if pane.IsMaximized():
+                    self.AUIManager.RestorePane(pane)
+                else:
+                    self.AUIManager.MaximizePane(pane)
+                self.AUIManager.Update()
+            event.Skip()
+        return OnTabsOpenedDClick
+
+#-------------------------------------------------------------------------------
+#                         Types Tree Management Functions
+#-------------------------------------------------------------------------------
+
+    def RefreshProjectTree(self):
+        infos = self.Controler.GetProjectInfos()
+        root = self.ProjectTree.GetRootItem()
+        if not root.IsOk():
+            root = self.ProjectTree.AddRoot(infos["name"])
+        self.GenerateProjectTreeBranch(root, infos)
+        self.ProjectTree.Expand(root)
+
+    def ResetSelectedItem(self):
+        self.SelectedItem = None
+
+    def GenerateProjectTreeBranch(self, root, infos):
+        to_delete = []
+        item_name = infos["name"]
+        if infos["type"] in ITEMS_UNEDITABLE:
+            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)
+        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"])])
+        elif infos.has_key("icon") and infos["icon"] is not None:
+            icon_name = infos["icon"]
+            if not self.TreeImageDict.has_key(icon_name):
+                self.TreeImageDict[icon_name] = self.TreeImageList.Add(GetBitmap(icon_name))
+            self.ProjectTree.SetItemImage(root, self.TreeImageDict[icon_name])
+        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:
+            item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
+        for values in infos["values"]:
+            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.ProjectTree.GetNextChild(root, root_cookie)
+        for item in to_delete:
+            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.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_DATATYPE)])
+                elif words[0] == "P":
+                    return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU)])
+                elif words[0] == "T":
+                    return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)])
+                elif words[0] == "A":
+                    return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)])
+                elif words[0] == "C":
+                    return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)])
+                elif words[0] == "R":
+                    return self.RecursiveProjectTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)])
+        return False
+
+    def RecursiveProjectTreeItemSelection(self, root, items):
+        found = False
+        if wx.VERSION >= (2, 6, 0):
+            item, root_cookie = self.ProjectTree.GetFirstChild(root)
+        else:
+            item, root_cookie = self.ProjectTree.GetFirstChild(root, 0)
+        while item.IsOk() and not found:
+            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
+                    wx.CallAfter(self.ProjectTree.SelectItem, item)
+                    wx.CallAfter(self.ResetSelectedItem)
+                    return True
+                else:
+                    found = self.RecursiveProjectTreeItemSelection(item, items[1:])
+            else:
+                found = self.RecursiveProjectTreeItemSelection(item, items)
+            item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
+        return found
+
+    def OnProjectTreeBeginDrag(self, event):
+        if wx.Platform == '__WXMSW__':
+            self.SelectedItem = event.GetItem()
+        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":
+                data = wx.TextDataObject(str((block_name, block_type, "")))
+                dragSource = wx.DropSource(self.ProjectTree)
+                dragSource.SetData(data)
+                dragSource.DoDragDrop()
+            self.ResetSelectedItem()
+
+    def OnProjectTreeItemBeginEdit(self, event):
+        selected = event.GetItem()
+        if self.ProjectTree.GetPyData(selected)["type"] in ITEMS_UNEDITABLE:
+            event.Veto()
+        else:
+            event.Skip()
+
+    def OnProjectTreeItemEndEdit(self, event):
+        message = None
+        abort = False
+        new_name = event.GetLabel()
+        if new_name != "":
+            if not TestIdentifier(new_name):
+                message = _("\"%s\" is not a valid identifier!")%new_name
+            elif new_name.upper() in IEC_KEYWORDS:
+                message = _("\"%s\" is a keyword. It can't be used!")%new_name
+            else:
+                item = event.GetItem()
+                old_name = self.ProjectTree.GetItemText(item)
+                item_infos = self.ProjectTree.GetPyData(item)
+                if item_infos["type"] == ITEM_PROJECT:
+                    self.Controler.SetProjectProperties(name = new_name)
+                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
+                    if not abort:
+                        self.Controler.ChangeDataTypeName(old_name, new_name)
+                        self.RefreshEditorNames(self.Controler.ComputeDataTypeName(old_name), 
+                                                self.Controler.ComputeDataTypeName(new_name))
+                        self.RefreshPageTitles()
+                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
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
+                        messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
+                        if messageDialog.ShowModal() == wx.ID_NO:
+                            abort = True
+                        messageDialog.Destroy()
+                    if not abort:
+                        self.Controler.ChangePouName(old_name, new_name)
+                        self.RefreshEditorNames(self.Controler.ComputePouName(old_name), 
+                                                self.Controler.ComputePouName(new_name))
+                        self.RefreshLibraryPanel()
+                        self.RefreshPageTitles()
+                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:
+                        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 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:
+                        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 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
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
+                        messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
+                        if messageDialog.ShowModal() == wx.ID_NO:
+                            abort = True
+                        messageDialog.Destroy()
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
+                        messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
+                        if messageDialog.ShowModal() == wx.ID_NO:
+                            abort = True
+                        messageDialog.Destroy()
+                    if not abort:
+                        self.Controler.ChangeConfigurationName(old_name, new_name)
+                        self.RefreshEditorNames(self.Controler.ComputeConfigurationName(old_name), 
+                                                self.Controler.ComputeConfigurationName(new_name))
+                        self.RefreshPageTitles()
+                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
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
+                        messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
+                        if messageDialog.ShowModal() == wx.ID_NO:
+                            abort = True
+                        messageDialog.Destroy()
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
+                        messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
+                        if messageDialog.ShowModal() == wx.ID_NO:
+                            abort = True
+                        messageDialog.Destroy()
+                    if not abort:
+                        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:
+                    self.ShowErrorMessage(message)
+                item = event.GetItem()
+                wx.CallAfter(self.ProjectTree.EditLabel, item)
+                event.Veto()
+            else:
+                wx.CallAfter(self.RefreshProjectTree)
+                self.RefreshEditor()
+                self._Refresh(TITLE, FILEMENU, EDITMENU)
+                event.Skip()
+    
+    def OnProjectTreeItemActivated(self, event):
+        selected = event.GetItem()
+        name = self.ProjectTree.GetItemText(selected)
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == ITEM_PROJECT:
+            self.EditProjectSettings()
+        else:
+            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"])
+            event.Skip()
+    
+    def ProjectTreeItemSelect(self, select_item):
+        name = self.ProjectTree.GetItemText(select_item)
+        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:
+            self.ProjectTree.SelectItem(self.SelectedItem)
+            self.ProjectTreeItemSelect(self.SelectedItem)
+            wx.CallAfter(self.ResetSelectedItem)
+        event.Skip()
+    
+    def OnProjectTreeItemSelected(self, event):
+        self.ProjectTreeItemSelect(event.GetItem())
+        event.Skip()
+    
+    def OnProjectTreeItemChanging(self, event):
+        if self.ProjectTree.GetPyData(event.GetItem())["type"] not in ITEMS_UNEDITABLE and self.SelectedItem is None:
+            self.SelectedItem = event.GetItem()
+            event.Veto()
+        else:
+            event.Skip()
+    
+    def EditProjectElement(self, element, tagname, onlyopened = False):
+        openedidx = self.IsOpened(tagname)
+        if openedidx is not None:
+            old_selected = self.TabsOpened.GetSelection()
+            if old_selected != openedidx:
+                if old_selected >= 0:
+                    self.TabsOpened.GetPage(old_selected).ResetBuffer()
+                self.TabsOpened.SetSelection(openedidx)
+            self._Refresh(FILEMENU, EDITMENU, EDITORTOOLBAR, PAGETITLES)
+        elif not onlyopened:
+            new_window = None
+            if element == ITEM_CONFIGURATION:
+                new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
+                new_window.SetIcon(GetBitmap("CONFIGURATION"))
+                self.AddPage(new_window, "")
+            elif element == ITEM_RESOURCE:
+                new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler)
+                new_window.SetIcon(GetBitmap("RESOURCE"))
+                self.AddPage(new_window, "")
+            elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
+                bodytype = self.Controler.GetEditedElementBodyType(tagname)
+                if bodytype == "FBD":
+                    new_window = Viewer(self.TabsOpened, tagname, self, self.Controler)
+                    new_window.RefreshScaling(False)
+                elif bodytype == "LD":
+                    new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler)
+                    new_window.RefreshScaling(False)
+                elif bodytype == "SFC":
+                    new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler)
+                    new_window.RefreshScaling(False)
+                else:
+                    new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler)
+                    new_window.SetTextSyntax(bodytype)
+                    if bodytype == "IL":
+                        new_window.SetKeywords(IL_KEYWORDS)
+                    else:
+                        new_window.SetKeywords(ST_KEYWORDS)
+                if element == ITEM_POU:
+                    pou_type = self.Controler.GetEditedElementType(tagname)[1].upper()
+                    icon = GetBitmap(pou_type, bodytype)
+                elif element == ITEM_TRANSITION:
+                    icon = GetBitmap("TRANSITION", bodytype)
+                elif element == ITEM_ACTION:
+                    icon = GetBitmap("ACTION", bodytype)
+                new_window.SetIcon(icon)
+                self.AddPage(new_window, "")
+            elif element == ITEM_DATATYPE:
+                new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler)
+                new_window.SetIcon(GetBitmap("DATATYPE"))
+                self.AddPage(new_window, "")
+            elif isinstance(element, EditorPanel):
+                new_window = element
+                self.AddPage(element, "")
+            if new_window is not None:
+                project_infos = self.GetProjectConfiguration()
+                if project_infos.has_key("editors_state"):
+                    state = project_infos["editors_state"].get(tagname)
+                    if state is not None:
+                        wx.CallAfter(new_window.SetState, state)
+                
+                openedidx = self.IsOpened(tagname)
+                old_selected = self.TabsOpened.GetSelection()
+                if old_selected != openedidx:
+                    if old_selected >= 0:
+                        self.TabsOpened.GetPage(old_selected).ResetBuffer()
+                for i in xrange(self.TabsOpened.GetPageCount()):
+                    window = self.TabsOpened.GetPage(i)
+                    if window == new_window:
+                        self.TabsOpened.SetSelection(i)
+                        window.SetFocus()
+                self.RefreshPageTitles()
+            return new_window
+    
+    def OnProjectTreeRightUp(self, event):
+        if wx.Platform == '__WXMSW__':
+            item = event.GetItem()
+        else:
+            item, flags = self.ProjectTree.HitTest(wx.Point(event.GetX(), event.GetY()))
+        self.ProjectTree.SelectItem(item)
+        self.ProjectTreeItemSelect(item)
+        name = self.ProjectTree.GetItemText(item)
+        item_infos = self.ProjectTree.GetPyData(item)
+        
+        menu = None
+        if item_infos["type"] in ITEMS_UNEDITABLE + [ITEM_PROJECT]:
+            if item_infos["type"] == ITEM_PROJECT:
+                name = "Project"
+            else:
+                name = UNEDITABLE_NAMES_DICT[name]
+            
+            if name == "Data Types":
+                menu = wx.Menu(title='')
+                new_id = wx.NewId()
+                AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add DataType"))
+                self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, id=new_id)
+            
+            elif name in ["Functions", "Function Blocks", "Programs", "Project"]:
+                menu = wx.Menu(title='')
+                
+                if name != "Project":
+                    new_id = wx.NewId()
+                    AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add POU"))
+                    self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id)
+
+                new_id = wx.NewId()
+                AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Paste POU"))
+                self.Bind(wx.EVT_MENU, self.OnPastePou, id=new_id)
+                if self.GetCopyBuffer() is None:
+                    menu.Enable(new_id, False)
+
+            elif name == "Configurations":
+                menu = wx.Menu(title='')
+                new_id = wx.NewId()
+                AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Configuration"))
+                self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, id=new_id)
+            
+            elif name == "Transitions":
+                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)["type"]
+                parent_type = self.ProjectTree.GetPyData(parent)
+                while parent_type != ITEM_POU:
+                    parent = self.ProjectTree.GetItemParent(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":
+                menu = wx.Menu(title='')
+                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)["type"]
+                while parent_type != ITEM_POU:
+                    parent = self.ProjectTree.GetItemParent(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":
+                menu = wx.Menu(title='')
+                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)["type"]
+                while parent_type not in [ITEM_CONFIGURATION, ITEM_PROJECT]:
+                    parent = self.ProjectTree.GetItemParent(parent)
+                    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 item_infos["type"] == ITEM_POU:
+                menu = wx.Menu(title='')
+                if self.Controler.GetPouBodyType(name) == "SFC":
+                    new_id = wx.NewId()
+                    AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition"))
+                    self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), id=new_id)
+                    new_id = wx.NewId()
+                    AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action"))
+                    self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id)
+                    menu.AppendSeparator()
+    
+                new_id = wx.NewId()
+                AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Copy POU"))
+                self.Bind(wx.EVT_MENU, self.OnCopyPou, id=new_id)
+    
+                pou_type = self.Controler.GetPouType(name)
+                if pou_type in ["function", "functionBlock"]:
+                    change_menu = wx.Menu(title='')
+                    if pou_type == "function":
+                        new_id = wx.NewId()
+                        AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Function Block"))
+                        self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "functionBlock"), id=new_id)
+                    new_id = wx.NewId()
+                    AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Program"))
+                    self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "program"), id=new_id)
+                    menu.AppendMenu(wx.NewId(), _("Change POU Type To"), change_menu)
+                new_id = wx.NewId()
+                AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Rename"))
+                self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, id=new_id)
+            
+            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 item_infos["type"] in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]:
+                menu = wx.Menu(title='')
+                
+            if menu is not None:
+                new_id = wx.NewId()
+                AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete"))
+                self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id)
+        
+        if menu is not None:
+            self.PopupMenu(menu)
+            menu.Destroy()
+        
+        event.Skip()
+
+
+#-------------------------------------------------------------------------------
+#                         Instances Tree Management Functions
+#-------------------------------------------------------------------------------
+
+    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)
+        if openedidx is not None:
+            old_selected = self.TabsOpened.GetSelection()
+            if old_selected != openedidx:
+                if old_selected >= 0:
+                    self.TabsOpened.GetPage(old_selected).ResetBuffer()
+                self.TabsOpened.SetSelection(openedidx)
+        
+        elif instance_category in ITEMS_VARIABLE:
+            if self.Controler.IsOfType(instance_type, "ANY_NUM", True) or\
+               self.Controler.IsOfType(instance_type, "ANY_BIT", True):
+                
+                return self.OpenGraphicViewer(instance_path)
+        
+        else:
+            bodytype = self.Controler.GetEditedElementBodyType(instance_type, True)
+            new_window = None
+            if bodytype == "FBD":
+                new_window = Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
+                new_window.RefreshScaling(False)
+            elif bodytype == "LD":
+                new_window = LD_Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
+                new_window.RefreshScaling(False)
+            elif bodytype == "SFC":
+                new_window = SFC_Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
+                new_window.RefreshScaling(False)
+            else:
+                new_window = TextViewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
+                new_window.SetTextSyntax(bodytype)
+                if bodytype == "IL":
+                    new_window.SetKeywords(IL_KEYWORDS)
+                else:
+                    new_window.SetKeywords(ST_KEYWORDS)
+            if new_window is not None:
+                project_infos = self.GetProjectConfiguration()
+                if project_infos.has_key("editors_state"):
+                    state = project_infos["editors_state"].get(instance_path)
+                    if state is not None:
+                        wx.CallAfter(new_window.SetState, state)
+                
+                if instance_category in [ITEM_FUNCTIONBLOCK, ITEM_PROGRAM]:
+                    pou_type = self.Controler.GetEditedElementType(instance_type, True)[1].upper()
+                    icon = GetBitmap(pou_type, bodytype)
+                elif instance_category == ITEM_TRANSITION:
+                    icon = GetBitmap("TRANSITION", bodytype)
+                elif instance_category == ITEM_ACTION:
+                    icon = GetBitmap("ACTION", bodytype)
+                new_window.SetIcon(icon)
+                self.AddPage(new_window, "")
+                new_window.RefreshView()
+                new_window.SetFocus()
+                self.RefreshPageTitles()
+            return new_window
+        
+        return None
+
+    def OpenGraphicViewer(self, var_path):
+        new_window = GraphicViewer(self.TabsOpened, self, self.Controler, var_path)
+        new_window.SetIcon(GetBitmap("GRAPH"))
+        self.AddPage(new_window, "")
+        new_window.RefreshView()
+        new_window.SetFocus()
+        self.RefreshPageTitles()
+        return new_window
+
+    def ResetGraphicViewers(self):
+        for i in xrange(self.TabsOpened.GetPageCount()):
+            editor = self.TabsOpened.GetPage(i)
+            if isinstance(editor, GraphicViewer):
+                editor.ResetView()
+
+    def CloseObsoleteDebugTabs(self):
+        if self.EnableDebug:
+            idxs = range(self.TabsOpened.GetPageCount())
+            idxs.reverse()
+            for idx in idxs:
+                editor = self.TabsOpened.GetPage(idx)
+                if editor.IsDebugging():
+                    instance_infos = self.Controler.GetInstanceInfos(editor.GetInstancePath(), self.EnableDebug)
+                    if instance_infos is None:
+                        self.TabsOpened.DeletePage(idx)
+                    elif isinstance(editor, GraphicViewer):
+                        editor.ResetView(True)
+                    else:
+                        editor.RefreshView()
+            self.DebugVariablePanel.UnregisterObsoleteData()
+    
+    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
+#-------------------------------------------------------------------------------
+
+    def RefreshLibraryPanel(self):
+        self.LibraryPanel.RefreshTree()
+        
+#-------------------------------------------------------------------------------
+#                          ToolBars Management Functions
+#-------------------------------------------------------------------------------
+
+    def AddToMenuToolBar(self, items):
+        MenuToolBar = self.Panes["MenuToolBar"]
+        if MenuToolBar.GetToolsCount() > 0:
+            MenuToolBar.AddSeparator()
+        for toolbar_item in items:
+            if toolbar_item is None:
+                MenuToolBar.AddSeparator()
+            else:
+                id, bitmap, help, callback = toolbar_item
+                MenuToolBar.AddSimpleTool(id=id, shortHelpString=help, bitmap=GetBitmap(bitmap))
+                if callback is not None:
+                    self.Bind(wx.EVT_TOOL, callback, id=id)
+        MenuToolBar.Realize()
+        self.AUIManager.GetPane("MenuToolBar").BestSize(MenuToolBar.GetBestSize())
+
+    def ResetEditorToolBar(self):
+        EditorToolBar = self.Panes["EditorToolBar"]
+        
+        for item in self.CurrentEditorToolBar:
+            if wx.VERSION >= (2, 6, 0):
+                self.Unbind(wx.EVT_MENU, id=item)
+            else:
+                self.Disconnect(id=item, eventType=wx.wxEVT_COMMAND_MENU_SELECTED) 
+        
+            if EditorToolBar:
+                EditorToolBar.DeleteTool(item)
+        
+        if EditorToolBar:
+            EditorToolBar.Realize()
+            self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
+            self.AUIManager.GetPane("EditorToolBar").Hide()
+            self.AUIManager.Update()
+
+    def RefreshEditorToolBar(self):
+        selected = self.TabsOpened.GetSelection()
+        menu = None
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            if isinstance(window, (Viewer, TextViewer, GraphicViewer)):
+                if not window.IsDebugging():
+                    menu = self.Controler.GetEditedElementBodyType(window.GetTagName())
+                else:
+                    menu = "debug"
+        if menu is not None and menu != self.CurrentMenu:
+            self.ResetEditorToolBar()
+            self.CurrentMenu = menu
+            self.CurrentEditorToolBar = []
+            EditorToolBar = self.Panes["EditorToolBar"]
+            if EditorToolBar:
+                for radio, modes, id, method, picture, help in EditorToolBarItems[menu]:
+                    if modes & self.DrawingMode:
+                        if radio or self.DrawingMode == FREEDRAWING_MODE:
+                            EditorToolBar.AddRadioTool(id, GetBitmap(picture), wx.NullBitmap, help)
+                        else:
+                            EditorToolBar.AddSimpleTool(id, GetBitmap(picture), help)
+                        self.Bind(wx.EVT_MENU, getattr(self, method), id=id)
+                        self.CurrentEditorToolBar.append(id)
+                EditorToolBar.Realize()
+                self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
+                self.AUIManager.GetPane("EditorToolBar").Show()
+                self.AUIManager.Update()
+        elif menu is None:
+            self.ResetEditorToolBar()
+            self.CurrentMenu = menu
+        self.ResetCurrentMode()
+
+
+#-------------------------------------------------------------------------------
+#                           EditorToolBar Items Functions
+#-------------------------------------------------------------------------------
+
+    def ResetCurrentMode(self):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            window = self.TabsOpened.GetPage(selected)
+            window.SetMode(MODE_SELECTION)
+        EditorToolBar = self.Panes["EditorToolBar"]
+        if EditorToolBar:
+            EditorToolBar.ToggleTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, False)
+            EditorToolBar.ToggleTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, True)
+        
+    def ResetToolToggle(self, id):
+        tool = self.Panes["EditorToolBar"].FindById(id)
+        tool.SetToggle(False)
+
+    def OnSelectionTool(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION)
+    
+    def OnMotionTool(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_MOTION)
+    
+    def OnCommentTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCOMMENT)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT)
+    
+    def OnVariableTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARVARIABLE)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE)
+    
+    def OnBlockTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARBLOCK)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK)
+        
+    def OnConnectionTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCONNECTION)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION)
+    
+    def OnPowerRailTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_POWERRAIL)
+    
+    def OnRungTool(self, event):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).AddLadderRung()
+        event.Skip()
+    
+    def OnCoilTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCOIL)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_COIL)
+        event.Skip()
+    
+    def OnContactTool(self, event):
+        if self.DrawingMode == FREEDRAWING_MODE:
+            self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCONTACT)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            if self.DrawingMode == FREEDRAWING_MODE:
+                self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT)
+            else:
+                self.TabsOpened.GetPage(selected).AddLadderContact()
+    
+    def OnBranchTool(self, event): 
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).AddLadderBranch()
+    
+    def OnInitialStepTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_INITIALSTEP)
+    
+    def OnStepTool(self, event):
+        if self.GetDrawingMode() == FREEDRAWING_MODE:
+            self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARSTEP)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            if self.GetDrawingMode() == FREEDRAWING_MODE:
+                self.TabsOpened.GetPage(selected).SetMode(MODE_STEP)
+            else:
+                self.TabsOpened.GetPage(selected).AddStep()
+    
+    def OnActionBlockTool(self, event):
+        if self.GetDrawingMode() == FREEDRAWING_MODE:
+            self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            if self.GetDrawingMode() == FREEDRAWING_MODE:
+                self.TabsOpened.GetPage(selected).SetMode(MODE_ACTION)
+            else:
+                self.TabsOpened.GetPage(selected).AddStepAction()
+    
+    def OnTransitionTool(self, event):
+        self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARTRANSITION)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).SetMode(MODE_TRANSITION)
+    
+    def OnDivergenceTool(self, event):
+        if self.GetDrawingMode() == FREEDRAWING_MODE:
+            self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            if self.GetDrawingMode() == FREEDRAWING_MODE:
+                self.TabsOpened.GetPage(selected).SetMode(MODE_DIVERGENCE)
+            else:
+                self.TabsOpened.GetPage(selected).AddDivergence()
+    
+    def OnJumpTool(self, event):
+        if self.GetDrawingMode() == FREEDRAWING_MODE:
+            self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARJUMP)
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            if self.GetDrawingMode() == FREEDRAWING_MODE:
+                self.TabsOpened.GetPage(selected).SetMode(MODE_JUMP)
+            else:
+                self.TabsOpened.GetPage(selected).AddJump()
+    
+
+#-------------------------------------------------------------------------------
+#                         Add Project Elements Functions
+#-------------------------------------------------------------------------------
+
+    def OnAddDataTypeMenu(self, event):
+        tagname = self.Controler.ProjectAddDataType()
+        if tagname is not None:
+            self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
+            self.EditProjectElement(ITEM_DATATYPE, tagname)
+        
+    def GenerateAddPouFunction(self, pou_type):
+        def OnAddPouMenu(event):
+            dialog = PouDialog(self, pou_type)
+            dialog.SetPouNames(self.Controler.GetProjectPouNames())
+            dialog.SetPouElementNames(self.Controler.GetProjectPouVariables())
+            dialog.SetValues({"pouName": self.Controler.GenerateNewName(None, None, "%s%%d" % pou_type)})
+            if dialog.ShowModal() == wx.ID_OK:
+                values = dialog.GetValues()
+                tagname = self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"])
+                if tagname is not None:
+                    self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
+                    self.EditProjectElement(ITEM_POU, tagname)
+            dialog.Destroy()
+        return OnAddPouMenu
+
+    def GenerateAddTransitionFunction(self, pou_name):
+        def OnAddTransitionMenu(event):
+            dialog = PouTransitionDialog(self)
+            dialog.SetPouNames(self.Controler.GetProjectPouNames())
+            dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name))
+            dialog.SetValues({"transitionName": self.Controler.GenerateNewName(None, None, "transition%d")})
+            if dialog.ShowModal() == wx.ID_OK: 
+                values = dialog.GetValues()
+                tagname = self.Controler.ProjectAddPouTransition(pou_name, values["transitionName"], values["language"])
+                if tagname is not None:
+                    self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
+                    self.EditProjectElement(ITEM_TRANSITION, tagname)
+            dialog.Destroy()
+        return OnAddTransitionMenu
+
+    def GenerateAddActionFunction(self, pou_name):
+        def OnAddActionMenu(event):
+            dialog = PouActionDialog(self)
+            dialog.SetPouNames(self.Controler.GetProjectPouNames())
+            dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name))
+            dialog.SetValues({"actionName": self.Controler.GenerateNewName(None, None, "action%d")})
+            if dialog.ShowModal() == wx.ID_OK:
+                values = dialog.GetValues()
+                tagname = self.Controler.ProjectAddPouAction(pou_name, values["actionName"], values["language"])
+                if tagname is not None:
+                    self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
+                    self.EditProjectElement(ITEM_ACTION, tagname)
+            dialog.Destroy()
+        return OnAddActionMenu
+
+    def OnAddConfigurationMenu(self, event):
+        tagname = self.Controler.ProjectAddConfiguration()
+        if tagname is not None:
+            self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
+            self.EditProjectElement(ITEM_CONFIGURATION, tagname)
+        dialog.Destroy()
+
+    def GenerateAddResourceFunction(self, config_name):
+        def OnAddResourceMenu(event):
+            tagname = self.Controler.ProjectAddConfigurationResource(config_name)
+            if tagname is not None:
+                self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
+                self.EditProjectElement(ITEM_RESOURCE, tagname)
+        return OnAddResourceMenu
+
+    def GenerateChangePouTypeFunction(self, name, new_type):
+        def OnChangePouTypeMenu(event):
+            selected = self.ProjectTree.GetSelection()
+            if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU: 
+                self.Controler.ProjectChangePouType(name, new_type)
+                self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
+        return OnChangePouTypeMenu
+
+    def OnCopyPou(self, event):
+        selected = self.ProjectTree.GetSelection()
+        pou_name = self.ProjectTree.GetItemText(selected)
+        
+        pou_xml = self.Controler.GetPouXml(pou_name)
+        if pou_xml is not None:
+            self.SetCopyBuffer(pou_xml)
+            self._Refresh(EDITMENU)
+
+    def OnPastePou(self, event):
+        selected = self.ProjectTree.GetSelection()
+        
+        if self.ProjectTree.GetPyData(selected)["type"] != ITEM_PROJECT: 
+            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]
+        else:
+            pou_type = None
+        
+        pou_xml = self.GetCopyBuffer()
+
+        result = self.Controler.PastePou(pou_type, pou_xml)
+
+        if not isinstance(result, TupleType):
+            message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        else:
+            self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
+            self.EditProjectElement(ITEM_POU, result[0])
+
+#-------------------------------------------------------------------------------
+#                        Remove Project Elements Functions
+#-------------------------------------------------------------------------------
+
+    def OnRemoveDataTypeMenu(self, event):
+        selected = self.ProjectTree.GetSelection()
+        if self.ProjectTree.GetPyData(selected)["type"] == 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, PROJECTTREE)
+            else:
+                self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!"))
+
+    def OnRenamePouMenu(self, event):
+        selected = self.ProjectTree.GetSelection()
+        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)["type"] == 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, 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.ProjectTree.GetSelection()
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == ITEM_TRANSITION: 
+            transition = self.ProjectTree.GetItemText(selected)
+            pou_name = item_infos["tagname"].split("::")[1]
+            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, PROJECTTREE)
+
+    def OnRemoveActionMenu(self, event):
+        selected = self.ProjectTree.GetSelection()
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == ITEM_ACTION: 
+            action = self.ProjectTree.GetItemText(selected)
+            pou_name = item_infos["tagname"].split("::")[1]
+            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, PROJECTTREE)
+
+    def OnRemoveConfigurationMenu(self, event):
+        selected = self.ProjectTree.GetSelection()
+        if self.ProjectTree.GetPyData(selected)["type"] == 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, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
+
+    def OnRemoveResourceMenu(self, event):
+        selected = self.ProjectTree.GetSelection()
+        item_infos = self.ProjectTree.GetPyData(selected)
+        if item_infos["type"] == ITEM_RESOURCE:
+            resource = self.ProjectTree.GetItemText(selected)
+            config_name = item_infos["tagname"].split("::")[1]
+            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, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
+
+#-------------------------------------------------------------------------------
+#                        Highlights showing functions
+#-------------------------------------------------------------------------------
+
+    def ShowHighlight(self, infos, start, end, highlight_type):
+        self.SelectProjectTreeItem(infos[0])
+        if infos[1] == "name":
+            self.Highlights[infos[0]] = highlight_type
+            self.RefreshProjectTree()
+            self.ProjectTree.Unselect()
+        else:
+            self.EditProjectElement(self.Controler.GetElementType(infos[0]), infos[0])
+            selected = self.TabsOpened.GetSelection()
+            if selected != -1:
+                viewer = self.TabsOpened.GetPage(selected)
+                viewer.AddHighlight(infos[1:], start, end, highlight_type)
+
+    def ShowError(self, infos, start, end):
+        self.ShowHighlight(infos, start, end, ERROR_HIGHLIGHT)
+
+    def ShowSearchResult(self, infos, start, end):
+        self.ShowHighlight(infos, start, end, SEARCH_RESULT_HIGHLIGHT)
+
+    def ClearHighlights(self, highlight_type=None):
+        if highlight_type is None:
+            self.Highlights = {}
+        else:
+            self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.iteritems() if highlight != highlight_type])
+        self.RefreshProjectTree()
+        for i in xrange(self.TabsOpened.GetPageCount()):
+            viewer = self.TabsOpened.GetPage(i)
+            viewer.ClearHighlights(highlight_type)
+
+    def ClearErrors(self):
+        self.ClearHighlights(ERROR_HIGHLIGHT)
+
+    def ClearSearchResults(self):
+        self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)