andrej@1511: #!/usr/bin/env python
andrej@1511: # -*- coding: utf-8 -*-
andrej@1511: 
andrej@1511: # This file is part of Beremiz, a Integrated Development Environment for
andrej@1511: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
andrej@1511: #
andrej@1511: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
andrej@1511: #
andrej@1511: # See COPYING file for copyrights details.
andrej@1511: #
andrej@1511: # This program is free software; you can redistribute it and/or
andrej@1511: # modify it under the terms of the GNU General Public License
andrej@1511: # as published by the Free Software Foundation; either version 2
andrej@1511: # of the License, or (at your option) any later version.
andrej@1511: #
andrej@1511: # This program is distributed in the hope that it will be useful,
andrej@1511: # but WITHOUT ANY WARRANTY; without even the implied warranty of
andrej@1511: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
andrej@1511: # GNU General Public License for more details.
andrej@1511: #
andrej@1511: # You should have received a copy of the GNU General Public License
andrej@1511: # along with this program; if not, write to the Free Software
andrej@1511: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Laurent@814: 
kinsamanka@3750: 
kinsamanka@3759: from functools import cmp_to_key
kinsamanka@3770: import pickle
kinsamanka@3759: from operator import eq
andrej@1783: import base64
Laurent@814: 
andrej@1732: import wx
andrej@1732: import wx.grid
Laurent@814: import wx.aui
Laurent@814: 
Laurent@814: from editors.EditorPanel import EditorPanel
Laurent@814: from editors.SFCViewer import SFC_Viewer
Laurent@814: from editors.LDViewer import LD_Viewer
Laurent@814: from editors.TextViewer import TextViewer
Laurent@814: from editors.Viewer import Viewer, ZOOM_FACTORS
Laurent@814: from editors.ResourceEditor import ConfigurationEditor, ResourceEditor
Laurent@814: from editors.DataTypeEditor import DataTypeEditor
Laurent@814: from PLCControler import *
Laurent@1193: from controls import CustomTree, LibraryPanel, PouInstanceVariablesPanel, SearchResultPanel
Laurent@1198: from controls.DebugVariablePanel import DebugVariablePanel
laurent@819: from dialogs import ProjectDialog, PouDialog, PouTransitionDialog, PouActionDialog, FindInPouDialog, SearchInProjectDialog
Laurent@814: from util.BitmapLibrary import GetBitmap
Edouard@1948: from plcopen.types_enums import *
Laurent@814: 
Laurent@814: # Define PLCOpenEditor controls id
andrej@1773: [
andrej@1773:     ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK,
andrej@1773:     ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK,
andrej@1773:     ID_PLCOPENEDITORPROJECTTREE, ID_PLCOPENEDITORMAINSPLITTER,
andrej@1773:     ID_PLCOPENEDITORSECONDSPLITTER, ID_PLCOPENEDITORTHIRDSPLITTER,
andrej@1773:     ID_PLCOPENEDITORLIBRARYPANEL, ID_PLCOPENEDITORLIBRARYSEARCHCTRL,
andrej@1773:     ID_PLCOPENEDITORLIBRARYTREE, ID_PLCOPENEDITORLIBRARYCOMMENT,
andrej@1773:     ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTABSOPENED,
andrej@1773:     ID_PLCOPENEDITOREDITORMENUTOOLBAR, ID_PLCOPENEDITOREDITORTOOLBAR,
andrej@1773:     ID_PLCOPENEDITORPROJECTPANEL,
kinsamanka@3766: ] = [wx.NewIdRef() for _init_ctrls in range(17)]
Laurent@814: 
Laurent@814: # Define PLCOpenEditor EditMenu extra items id
andrej@1773: [
andrej@1773:     ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, ID_PLCOPENEDITOREDITMENUADDDATATYPE,
andrej@1773:     ID_PLCOPENEDITOREDITMENUADDFUNCTION, ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK,
andrej@1773:     ID_PLCOPENEDITOREDITMENUADDPROGRAM, ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
andrej@1773:     ID_PLCOPENEDITOREDITMENUFINDNEXT, ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
andrej@1773:     ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, ID_PLCOPENEDITOREDITMENUADDRESOURCE
kinsamanka@3766: ] = [wx.NewIdRef() for _init_coll_EditMenu_Items in range(10)]
Laurent@814: 
Laurent@814: # Define PLCOpenEditor DisplayMenu extra items id
andrej@1773: [
andrej@1773:     ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE,
andrej@1773:     ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE,
andrej@2242:     ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN,
kinsamanka@3766: ] = [wx.NewIdRef() for _init_coll_DisplayMenu_Items in range(3)]
Laurent@814: 
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: #                            EditorToolBar definitions
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814: # Define PLCOpenEditor Toolbar items id
andrej@1773: [
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARSELECTION, ID_PLCOPENEDITOREDITORTOOLBARCOMMENT,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, ID_PLCOPENEDITOREDITORTOOLBARBLOCK,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, ID_PLCOPENEDITOREDITORTOOLBARWIRE,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, ID_PLCOPENEDITOREDITORTOOLBARRUNG,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARCOIL, ID_PLCOPENEDITOREDITORTOOLBARCONTACT,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARBRANCH, ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARSTEP, ID_PLCOPENEDITOREDITORTOOLBARTRANSITION,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK, ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE,
andrej@1773:     ID_PLCOPENEDITOREDITORTOOLBARJUMP, ID_PLCOPENEDITOREDITORTOOLBARMOTION,
kinsamanka@3766: ] = [wx.NewIdRef() for _init_coll_DefaultEditorToolBar_Items in range(18)]
Laurent@814: 
Laurent@814: 
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: #                               Helper Functions
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
andrej@1736: 
Laurent@814: def EncodeFileSystemPath(path, use_base64=True):
Laurent@814:     if use_base64:
kinsamanka@3755:         path = base64.b64encode(path.encode()).decode()
Laurent@814:     return path
Laurent@814: 
andrej@1736: 
Laurent@814: def DecodeFileSystemPath(path, is_base64=True):
Laurent@814:     if is_base64:
kinsamanka@3755:         path = base64.b64decode(path.encode()).decode()
kinsamanka@3755:     return path
Laurent@814: 
andrej@1736: 
Edouard@2737: def AppendMenu(parent, help, kind, text, id=wx.ID_ANY):
edouard@3303:     return parent.Append(wx.MenuItem(helpString=help, kind=kind, text=text, id=id))
Laurent@814: 
andrej@1749: 
andrej@1773: [
andrej@1773:     TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
andrej@1773:     POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
kinsamanka@3750: ] = list(range(10))
Laurent@814: 
andrej@1736: 
Laurent@814: def GetShortcutKeyCallbackFunction(viewer_function):
Laurent@814:     def ShortcutKeyFunction(self, event):
Laurent@814:         control = self.FindFocus()
Laurent@814:         if control is not None and control.GetName() in ["Viewer", "TextViewer"]:
Laurent@814:             getattr(control.ParentWindow, viewer_function)()
Laurent@814:         elif isinstance(control, wx.stc.StyledTextCtrl):
Laurent@814:             getattr(control, viewer_function)()
Laurent@814:         elif isinstance(control, wx.TextCtrl):
Laurent@814:             control.ProcessEvent(event)
Laurent@814:     return ShortcutKeyFunction
Laurent@814: 
andrej@1736: 
Laurent@814: def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None):
Laurent@814:     def DeleteElementFunction(self, selected):
Laurent@814:         name = self.ProjectTree.GetItemText(selected)
Laurent@1129:         if check_function is None or check_function(name):
Laurent@814:             if parent_type is not None:
kinsamanka@3789:                 item_infos = self.ProjectTree.GetItemData(selected)
Laurent@814:                 parent_name = item_infos["tagname"].split("::")[1]
Laurent@814:                 remove_function(self.Controler, parent_name, name)
Laurent@814:             else:
Laurent@814:                 remove_function(self.Controler, name)
Laurent@814:     return DeleteElementFunction
Laurent@814: 
andrej@1749: 
Laurent@814: if wx.Platform == '__WXMSW__':
Laurent@814:     TAB_BORDER = 6
Laurent@814:     NOTEBOOK_BORDER = 6
Laurent@814: else:
Laurent@814:     TAB_BORDER = 7
Laurent@814:     NOTEBOOK_BORDER = 2
Laurent@814: 
andrej@1736: 
Laurent@814: def SimplifyTabLayout(tabs, rect):
Laurent@814:     for tab in tabs:
Laurent@814:         if tab["pos"][0] == rect.x:
Laurent@814:             others = [t for t in tabs if t != tab]
kinsamanka@3759:             others.sort(key=cmp_to_key(lambda x, y: eq(x["pos"][0],
kinsamanka@3759:                                                        y["pos"][0])))
Laurent@814:             for other in others:
andrej@1766:                 if other["pos"][1] == tab["pos"][1] and \
andrej@1766:                    other["size"][1] == tab["size"][1] and \
andrej@1766:                    other["pos"][0] == tab["pos"][0] + tab["size"][0] + TAB_BORDER:
Edouard@1408: 
Laurent@814:                     tab["size"] = (tab["size"][0] + other["size"][0] + TAB_BORDER, tab["size"][1])
Laurent@814:                     tab["pages"].extend(other["pages"])
Laurent@814:                     tabs.remove(other)
Edouard@1408: 
Laurent@814:                     if tab["size"][0] == rect.width:
Laurent@814:                         return True
Edouard@1408: 
Laurent@814:         elif tab["pos"][1] == rect.y:
Laurent@814:             others = [t for t in tabs if t != tab]
kinsamanka@3759:             others.sort(key=cmp_to_key(lambda x, y: eq(x["pos"][1],
kinsamanka@3759:                                                        y["pos"][1])))
Laurent@814:             for other in others:
andrej@1766:                 if other["pos"][0] == tab["pos"][0] and \
andrej@1766:                    other["size"][0] == tab["size"][0] and \
andrej@1766:                    other["pos"][1] == tab["pos"][1] + tab["size"][1] + TAB_BORDER:
Edouard@1408: 
Laurent@814:                     tab["size"] = (tab["size"][0], tab["size"][1] + other["size"][1] + TAB_BORDER)
Laurent@814:                     tab["pages"].extend(other["pages"])
Laurent@814:                     tabs.remove(other)
Edouard@1408: 
Laurent@814:                     if tab["size"][1] == rect.height:
Laurent@814:                         return True
Laurent@814:     return False
Edouard@1408: 
andrej@1736: 
Laurent@814: def ComputeTabsLayout(tabs, rect):
Laurent@814:     if len(tabs) == 0:
Laurent@814:         return tabs
Laurent@814:     if len(tabs) == 1:
Laurent@814:         return tabs[0]
Laurent@814:     split = None
andrej@1855:     split_id = None
Laurent@814:     for idx, tab in enumerate(tabs):
Laurent@814:         if len(tab["pages"]) == 0:
andrej@1765:             raise ValueError("Not possible")
Laurent@814:         if tab["size"][0] == rect.width:
Laurent@814:             if tab["pos"][1] == rect.y:
andrej@2437:                 split = (wx.TOP, tab["size"][1] / rect.height)
Edouard@1408:                 split_rect = wx.Rect(rect.x, rect.y + tab["size"][1] + TAB_BORDER,
Laurent@814:                                      rect.width, rect.height - tab["size"][1] - TAB_BORDER)
Laurent@814:             elif tab["pos"][1] == rect.height + 1 - tab["size"][1]:
andrej@2437:                 split = (wx.BOTTOM, 1.0 - tab["size"][1] / rect.height)
Edouard@1408:                 split_rect = wx.Rect(rect.x, rect.y,
Laurent@814:                                      rect.width, rect.height - tab["size"][1] - TAB_BORDER)
andrej@1855:             split_id = idx
Laurent@814:             break
Laurent@814:         elif tab["size"][1] == rect.height:
Laurent@814:             if tab["pos"][0] == rect.x:
andrej@2437:                 split = (wx.LEFT, tab["size"][0] / rect.width)
Edouard@1408:                 split_rect = wx.Rect(rect.x + tab["size"][0] + TAB_BORDER, rect.y,
Laurent@814:                                      rect.width - tab["size"][0] - TAB_BORDER, rect.height)
Laurent@814:             elif tab["pos"][0] == rect.width + 1 - tab["size"][0]:
andrej@2437:                 split = (wx.RIGHT, 1.0 - tab["size"][0] / rect.width)
Edouard@1408:                 split_rect = wx.Rect(rect.x, rect.y,
Laurent@814:                                      rect.width - tab["size"][0] - TAB_BORDER, rect.height)
andrej@2169:             split_id = idx
Laurent@814:             break
andrej@1743:     if split is not None:
andrej@1855:         split_tab = tabs.pop(split_id)
Laurent@814:         return {"split": split,
Edouard@1408:                 "tab": split_tab,
Laurent@814:                 "others": ComputeTabsLayout(tabs, split_rect)}
Laurent@814:     else:
Laurent@814:         if SimplifyTabLayout(tabs, rect):
Laurent@814:             return ComputeTabsLayout(tabs, rect)
Laurent@814:     return tabs
Laurent@814: 
andrej@1749: 
Laurent@814: class IDEFrame(wx.Frame):
andrej@1782:     """IDEFrame Base Class"""
Edouard@1408: 
andrej@2301:     def InitEditorToolbarItems(self):
andrej@2301:         """
andrej@2301:         Initialize dictionary with lists of elements that need to be shown
andrej@2301:         if POU in particular programming language is edited.
andrej@2301:         """
andrej@2301:         # Define behaviour of each Toolbar item according to current POU body type
andrej@2301:         # Informations meaning are in this order:
andrej@2301:         #  - Item is toggled
andrej@2301:         #  - PLCOpenEditor mode where item is displayed (could be more then one)
andrej@2301:         #  - Item id
andrej@2301:         #  - Item callback function name
andrej@2301:         #  - Item icon filename
andrej@2301:         #  - Item tooltip text
andrej@2301:         self.EditorToolBarItems = {
andrej@2301:             "FBD":   [(True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
andrej@2301:                        "move", _("Move the view")),
andrej@2301:                       (True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool",
andrej@2301:                        "add_comment", _("Create a new comment")),
andrej@2301:                       (True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool",
andrej@2301:                        "add_variable", _("Create a new variable")),
andrej@2301:                       (True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool",
andrej@2301:                        "add_block", _("Create a new block")),
andrej@2301:                       (True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool",
andrej@2301:                        "add_connection", _("Create a new connection"))],
andrej@2301:             "LD":    [(True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
andrej@2301:                        "move", _("Move the view")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool",
andrej@2301:                        "add_comment", _("Create a new comment")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, "OnPowerRailTool",
andrej@2301:                        "add_powerrail", _("Create a new power rail")),
andrej@2301:                       (False, DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARRUNG, "OnRungTool",
andrej@2301:                        "add_rung", _("Create a new rung")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCOIL, "OnCoilTool",
andrej@2301:                        "add_coil", _("Create a new coil")),
andrej@2301:                       (False, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCONTACT, "OnContactTool",
andrej@2301:                        "add_contact", _("Create a new contact")),
andrej@2301:                       (False, DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARBRANCH, "OnBranchTool",
andrej@2301:                        "add_branch", _("Create a new branch")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool",
andrej@2301:                        "add_variable", _("Create a new variable")),
andrej@2301:                       (False, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool",
andrej@2301:                        "add_block", _("Create a new block")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool",
andrej@2301:                        "add_connection", _("Create a new connection"))],
andrej@2301:             "SFC":   [(True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
andrej@2301:                        "move", _("Move the view")),
andrej@2301:                       (True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCOMMENT, "OnCommentTool",
andrej@2301:                        "add_comment", _("Create a new comment")),
andrej@2301:                       (True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP, "OnInitialStepTool",
andrej@2301:                        "add_initial_step", _("Create a new initial step")),
andrej@2301:                       (False, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARSTEP, "OnStepTool",
andrej@2301:                        "add_step", _("Create a new step")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARTRANSITION, "OnTransitionTool",
andrej@2301:                        "add_transition", _("Create a new transition")),
andrej@2301:                       (False, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK, "OnActionBlockTool",
andrej@2301:                        "add_action", _("Create a new action block")),
andrej@2301:                       (False, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE, "OnDivergenceTool",
andrej@2301:                        "add_divergence", _("Create a new divergence")),
andrej@2301:                       (False, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARJUMP, "OnJumpTool",
andrej@2301:                        "add_jump", _("Create a new jump")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARVARIABLE, "OnVariableTool",
andrej@2301:                        "add_variable", _("Create a new variable")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARBLOCK, "OnBlockTool",
andrej@2301:                        "add_block", _("Create a new block")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCONNECTION, "OnConnectionTool",
andrej@2301:                        "add_connection", _("Create a new connection")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL, "OnPowerRailTool",
andrej@2301:                        "add_powerrail", _("Create a new power rail")),
andrej@2301:                       (True, FREEDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARCONTACT, "OnContactTool",
andrej@2301:                        "add_contact", _("Create a new contact"))],
andrej@2301:             "ST":    [],
andrej@2301:             "IL":    [],
andrej@2301:             "debug": [(True, FREEDRAWING_MODE | DRIVENDRAWING_MODE,
andrej@2301:                        ID_PLCOPENEDITOREDITORTOOLBARMOTION, "OnMotionTool",
andrej@2301:                        "move", _("Move the view"))],
andrej@2301:         }
andrej@2301: 
Laurent@814:     def _init_coll_MenuBar_Menus(self, parent):
kinsamanka@3750:         parent.Append(menu=self.FileMenu, title=_('&File'))
kinsamanka@3750:         parent.Append(menu=self.EditMenu, title=_('&Edit'))
kinsamanka@3750:         parent.Append(menu=self.DisplayMenu, title=_('&Display'))
kinsamanka@3750:         parent.Append(menu=self.HelpMenu, title=_('&Help'))
Laurent@814: 
Laurent@814:     def _init_coll_FileMenu_Items(self, parent):
Laurent@814:         pass
Edouard@1408: 
Laurent@814:     def _init_coll_AddMenu_Items(self, parent, add_config=True):
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('&Data Type'))
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('&Function'))
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Function &Block'))
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('&Program'))
Edouard@1401:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDRESOURCE,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('&Resource'))
Laurent@814:         if add_config:
Laurent@814:             AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
kinsamanka@3750:                        kind=wx.ITEM_NORMAL, text=_('&Configuration'))
Edouard@1408: 
Laurent@814:     def _init_coll_EditMenu_Items(self, parent):
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_UNDO,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Undo') + '\tCTRL+Z')
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_REDO,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Redo') + '\tCTRL+Y')
Laurent@814:         parent.AppendSeparator()
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_CUT,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Cut') + '\tCTRL+X')
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_COPY,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Copy') + '\tCTRL+C')
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_PASTE,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Paste') + '\tCTRL+V')
Laurent@814:         parent.AppendSeparator()
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_FIND,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Find') + '\tCTRL+F')
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDNEXT,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Find Next') + '\tCTRL+K')
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Find Previous') + '\tCTRL+SHIFT+K')
Laurent@814:         parent.AppendSeparator()
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Search in Project') + '\tCTRL+SHIFT+F')
Laurent@814:         parent.AppendSeparator()
Laurent@814:         add_menu = wx.Menu(title='')
Laurent@814:         self._init_coll_AddMenu_Items(add_menu)
edouard@3833:         self.AddMenuItem = parent.AppendSubMenu(add_menu, _("&Add Element"))
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_SELECTALL,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Select All') + '\tCTRL+A')
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_DELETE,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('&Delete'))
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
andrej@1782:         # self.Bind(wx.EVT_MENU, self.OnEnableUndoRedoMenu, id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnCutMenu, id=wx.ID_CUT)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnCopyMenu, id=wx.ID_COPY)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnPasteMenu, id=wx.ID_PASTE)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnFindMenu, id=wx.ID_FIND)
Edouard@1408:         self.Bind(wx.EVT_MENU, self.OnFindNextMenu,
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUFINDNEXT)
Edouard@1408:         self.Bind(wx.EVT_MENU, self.OnFindPreviousMenu,
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUFINDPREVIOUS)
Edouard@1408:         self.Bind(wx.EVT_MENU, self.OnSearchInProjectMenu,
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu,
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUADDDATATYPE)
Laurent@814:         self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("function"),
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUADDFUNCTION)
Laurent@814:         self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("functionBlock"),
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK)
Laurent@814:         self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("program"),
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUADDPROGRAM)
Edouard@1408:         self.Bind(wx.EVT_MENU, self.AddResourceMenu,
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUADDRESOURCE)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu,
andrej@1768:                   id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnSelectAllMenu, id=wx.ID_SELECTALL)
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE)
Edouard@1408: 
kinsamanka@3750:         self.AddToMenuToolBar([(wx.ID_UNDO, "undo", _('Undo'), None),
kinsamanka@3750:                                (wx.ID_REDO, "redo", _('Redo'), None),
Laurent@814:                                None,
kinsamanka@3750:                                (wx.ID_CUT, "cut", _('Cut'), None),
kinsamanka@3750:                                (wx.ID_COPY, "copy", _('Copy'), None),
kinsamanka@3750:                                (wx.ID_PASTE, "paste", _('Paste'), None),
Laurent@814:                                None,
kinsamanka@3750:                                (ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, "find", _('Search in Project'), None),
kinsamanka@3750:                                (ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN, "fullscreen", _('Toggle fullscreen mode'), None)])
Laurent@814: 
Laurent@814:     def _init_coll_DisplayMenu_Items(self, parent):
Laurent@814:         AppendMenu(parent, help='', id=wx.ID_REFRESH,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Refresh') + '\tCTRL+R')
Laurent@814:         if self.EnableDebug:
Laurent@814:             AppendMenu(parent, help='', id=wx.ID_CLEAR,
kinsamanka@3750:                        kind=wx.ITEM_NORMAL, text=_('Clear Errors') + '\tCTRL+K')
Laurent@814:         parent.AppendSeparator()
Laurent@814:         zoommenu = wx.Menu(title='')
edouard@3833:         self.ZoomMenuItem = parent.AppendSubMenu(zoommenu, _("Zoom"))
Laurent@814:         for idx, value in enumerate(ZOOM_FACTORS):
Edouard@2737:             new_item = AppendMenu(zoommenu, help='',
andrej@1768:                        kind=wx.ITEM_RADIO, text=str(int(round(value * 100))) + "%")
Edouard@2737:             self.Bind(wx.EVT_MENU, self.GenerateZoomFunction(idx), new_item)
Edouard@1408: 
Laurent@814:         parent.AppendSeparator()
edouard@3791:         if wx.VERSION >= (4, 1, 0):
edouard@3791:             AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE,
edouard@3791:                        kind=wx.ITEM_NORMAL, text=_('Switch perspective') + '\tF12')
edouard@3791:             self.Bind(wx.EVT_MENU, self.SwitchPerspective, id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE)
andrej@2242: 
andrej@2242:         AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Full screen') + '\tShift-F12')
andrej@2242:         self.Bind(wx.EVT_MENU, self.SwitchFullScrMode, id=ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN)
surkovsv93@1530: 
Laurent@814:         AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE,
kinsamanka@3750:                    kind=wx.ITEM_NORMAL, text=_('Reset Perspective'))
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnResetPerspective, id=ID_PLCOPENEDITORDISPLAYMENURESETPERSPECTIVE)
Edouard@1408: 
Laurent@814:         self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
Laurent@814:         if self.EnableDebug:
Laurent@814:             self.Bind(wx.EVT_MENU, self.OnClearErrorsMenu, id=wx.ID_CLEAR)
Edouard@1408: 
Laurent@814:     def _init_coll_HelpMenu_Items(self, parent):
Laurent@814:         pass
Laurent@814: 
Laurent@814:     def _init_utils(self):
Laurent@814:         self.MenuBar = wx.MenuBar()
Laurent@814: 
Laurent@814:         self.FileMenu = wx.Menu(title='')
Laurent@814:         self.EditMenu = wx.Menu(title='')
Laurent@814:         self.DisplayMenu = wx.Menu(title='')
Laurent@814:         self.HelpMenu = wx.Menu(title='')
Edouard@1408: 
Laurent@814:         self._init_coll_MenuBar_Menus(self.MenuBar)
Laurent@814:         self._init_coll_FileMenu_Items(self.FileMenu)
Laurent@814:         self._init_coll_EditMenu_Items(self.EditMenu)
Laurent@814:         self._init_coll_DisplayMenu_Items(self.DisplayMenu)
Laurent@814:         self._init_coll_HelpMenu_Items(self.HelpMenu)
Laurent@814: 
andrej@1490:     def _init_icon(self, parent):
andrej@1490:         if self.icon:
andrej@1730:             self.SetIcon(self.icon)
andrej@1490:         elif parent and parent.icon:
andrej@1730:             self.SetIcon(parent.icon)
andrej@1730: 
Laurent@814:     def _init_ctrls(self, prnt):
andrej@1490:         self._init_icon(prnt)
Laurent@814:         self.SetClientSize(wx.Size(1000, 600))
Laurent@814:         self.Bind(wx.EVT_ACTIVATE, self.OnActivated)
Edouard@1408: 
Laurent@814:         self.TabsImageList = wx.ImageList(31, 16)
Laurent@814:         self.TabsImageListIndexes = {}
Edouard@1408: 
andrej@1782:         # -----------------------------------------------------------------------
Laurent@814:         #                          Creating main structure
andrej@1782:         # -----------------------------------------------------------------------
Edouard@1408: 
Laurent@814:         self.AUIManager = wx.aui.AuiManager(self)
Laurent@814:         self.AUIManager.SetDockSizeConstraint(0.5, 0.5)
Laurent@814:         self.Panes = {}
Edouard@1408: 
andrej@1768:         self.LeftNoteBook = wx.aui.AuiNotebook(
andrej@1768:             self, ID_PLCOPENEDITORLEFTNOTEBOOK,
andrej@1768:             style=(wx.aui.AUI_NB_TOP |
andrej@1768:                    wx.aui.AUI_NB_TAB_SPLIT |
andrej@1768:                    wx.aui.AUI_NB_TAB_MOVE |
andrej@1768:                    wx.aui.AUI_NB_SCROLL_BUTTONS |
andrej@1768:                    wx.aui.AUI_NB_TAB_EXTERNAL_MOVE))
Edouard@1408:         self.LeftNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND,
andrej@1768:                                self.OnAllowNotebookDnD)
andrej@1768:         self.AUIManager.AddPane(
andrej@1768:             self.LeftNoteBook,
andrej@1768:             wx.aui.AuiPaneInfo().Name("ProjectPane").Left().Layer(1).
andrej@1768:             BestSize(wx.Size(300, 500)).CloseButton(False))
andrej@1768: 
andrej@1768:         self.BottomNoteBook = wx.aui.AuiNotebook(
andrej@1768:             self, ID_PLCOPENEDITORBOTTOMNOTEBOOK,
andrej@1768:             style=(wx.aui.AUI_NB_TOP |
andrej@1768:                    wx.aui.AUI_NB_TAB_SPLIT |
andrej@1768:                    wx.aui.AUI_NB_TAB_MOVE |
andrej@1768:                    wx.aui.AUI_NB_SCROLL_BUTTONS |
andrej@1768:                    wx.aui.AUI_NB_TAB_EXTERNAL_MOVE))
Edouard@1408:         self.BottomNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND,
andrej@1768:                                  self.OnAllowNotebookDnD)
andrej@1768:         self.AUIManager.AddPane(
andrej@1768:             self.BottomNoteBook,
andrej@1768:             wx.aui.AuiPaneInfo().Name("ResultPane").Bottom().Layer(0).
andrej@1768:             BestSize(wx.Size(800, 300)).CloseButton(False))
andrej@1768: 
andrej@1768:         self.RightNoteBook = wx.aui.AuiNotebook(
andrej@1768:             self, ID_PLCOPENEDITORRIGHTNOTEBOOK,
andrej@1768:             style=(wx.aui.AUI_NB_TOP |
andrej@1768:                    wx.aui.AUI_NB_TAB_SPLIT |
andrej@1768:                    wx.aui.AUI_NB_TAB_MOVE |
andrej@1768:                    wx.aui.AUI_NB_SCROLL_BUTTONS |
andrej@1768:                    wx.aui.AUI_NB_TAB_EXTERNAL_MOVE))
Edouard@1408:         self.RightNoteBook.Bind(wx.aui.EVT_AUINOTEBOOK_ALLOW_DND,
andrej@1768:                                 self.OnAllowNotebookDnD)
andrej@1768:         self.AUIManager.AddPane(
andrej@1768:             self.RightNoteBook,
andrej@1768:             wx.aui.AuiPaneInfo().Name("LibraryPane").Right().Layer(0).
andrej@1768:             BestSize(wx.Size(250, 400)).CloseButton(False))
andrej@1768: 
andrej@1768:         self.TabsOpened = wx.aui.AuiNotebook(
andrej@1768:             self, ID_PLCOPENEDITORTABSOPENED,
andrej@1768:             style=(wx.aui.AUI_NB_DEFAULT_STYLE |
andrej@1768:                    wx.aui.AUI_NB_WINDOWLIST_BUTTON))
Laurent@814:         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGING,
andrej@1768:                              self.OnPouSelectedChanging)
Laurent@814:         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED,
andrej@1768:                              self.OnPouSelectedChanged)
Laurent@814:         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE,
andrej@1768:                              self.OnPageClose)
Laurent@814:         self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_END_DRAG,
andrej@1768:                              self.OnPageDragged)
Edouard@1408:         self.AUIManager.AddPane(self.TabsOpened,
andrej@1768:                                 wx.aui.AuiPaneInfo().CentrePane().Name("TabsPane"))
Edouard@1408: 
andrej@1782:         # -----------------------------------------------------------------------
Laurent@814:         #                    Creating PLCopen Project Types Tree
andrej@1782:         # -----------------------------------------------------------------------
Edouard@1408: 
Laurent@814:         self.MainTabs = {}
Edouard@1408: 
andrej@1768:         self.ProjectPanel = wx.SplitterWindow(
andrej@1768:             id=ID_PLCOPENEDITORPROJECTPANEL,
edouard@3303:             name='ProjectPanel', parent=self.LeftNoteBook,
edouard@3303:             size=wx.Size(0, 0))
Edouard@1408: 
Laurent@814:         self.ProjectTree = CustomTree(id=ID_PLCOPENEDITORPROJECTTREE,
andrej@1768:                                       name='ProjectTree',
andrej@1768:                                       parent=self.ProjectPanel,
andrej@1768:                                       pos=wx.Point(0, 0), size=wx.Size(0, 0),
andrej@1768:                                       style=wx.SUNKEN_BORDER,
andrej@1768:                                       agwStyle=(wx.TR_HAS_BUTTONS |
andrej@1768:                                                 wx.TR_SINGLE |
andrej@1768:                                                 wx.TR_EDIT_LABELS))
Laurent@814:         self.ProjectTree.SetBackgroundBitmap(GetBitmap("custom_tree_background"),
andrej@1745:                                              wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM)
Laurent@814:         add_menu = wx.Menu()
Laurent@814:         self._init_coll_AddMenu_Items(add_menu)
Laurent@814:         self.ProjectTree.SetAddMenu(add_menu)
Laurent@1240:         self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnProjectTreeRightUp,
andrej@1768:                   id=ID_PLCOPENEDITORPROJECTTREE)
Laurent@1240:         self.ProjectTree.Bind(wx.EVT_LEFT_UP, self.OnProjectTreeLeftUp)
Laurent@1240:         self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnProjectTreeItemChanging,
andrej@1768:                   id=ID_PLCOPENEDITORPROJECTTREE)
Laurent@814:         self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnProjectTreeBeginDrag,
andrej@1768:                   id=ID_PLCOPENEDITORPROJECTTREE)
Laurent@814:         self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnProjectTreeItemBeginEdit,
andrej@1768:                   id=ID_PLCOPENEDITORPROJECTTREE)
Laurent@814:         self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnProjectTreeItemEndEdit,
andrej@1768:                   id=ID_PLCOPENEDITORPROJECTTREE)
Laurent@814:         self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnProjectTreeItemActivated,
andrej@1768:                   id=ID_PLCOPENEDITORPROJECTTREE)
Laurent@1106:         self.ProjectTree.Bind(wx.EVT_MOTION, self.OnProjectTreeMotion)
Edouard@1408: 
andrej@1782:         # -----------------------------------------------------------------------
Laurent@814:         #        Creating PLCopen Project POU Instance Variables Panel
andrej@1782:         # -----------------------------------------------------------------------
Edouard@1408: 
Laurent@814:         self.PouInstanceVariablesPanel = PouInstanceVariablesPanel(self.ProjectPanel, self, self.Controler, self.EnableDebug)
Edouard@1408: 
Laurent@814:         self.MainTabs["ProjectPanel"] = (self.ProjectPanel, _("Project"))
Laurent@814:         self.LeftNoteBook.AddPage(*self.MainTabs["ProjectPanel"])
Edouard@1408: 
Laurent@814:         self.ProjectPanel.SplitHorizontally(self.ProjectTree, self.PouInstanceVariablesPanel, 300)
Edouard@1408: 
andrej@1782:         # -----------------------------------------------------------------------
Laurent@814:         #                            Creating Tool Bar
andrej@1782:         # -----------------------------------------------------------------------
Edouard@1408: 
andrej@1768:         MenuToolBar = wx.ToolBar(self, ID_PLCOPENEDITOREDITORMENUTOOLBAR,
andrej@1768:                                  wx.DefaultPosition, wx.DefaultSize,
edouard@3588:                                  wx.TB_FLAT | wx.TB_HORIZONTAL | wx.NO_BORDER)
Laurent@814:         MenuToolBar.SetToolBitmapSize(wx.Size(25, 25))
Laurent@814:         MenuToolBar.Realize()
Laurent@814:         self.Panes["MenuToolBar"] = MenuToolBar
Laurent@814:         self.AUIManager.AddPane(MenuToolBar, wx.aui.AuiPaneInfo().
andrej@1768:                                 Name("MenuToolBar").Caption(_("Menu ToolBar")).
andrej@1768:                                 ToolbarPane().Top().
andrej@1768:                                 LeftDockable(False).RightDockable(False))
andrej@1768: 
andrej@1768:         EditorToolBar = wx.ToolBar(self, ID_PLCOPENEDITOREDITORTOOLBAR,
andrej@1768:                                    wx.DefaultPosition, wx.DefaultSize,
edouard@3588:                                    wx.TB_FLAT | wx.TB_HORIZONTAL | wx.NO_BORDER)
Laurent@814:         EditorToolBar.SetToolBitmapSize(wx.Size(25, 25))
Edouard@1408:         EditorToolBar.AddRadioTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION,
edouard@3588:                                    _("Select"),
andrej@1768:                                    GetBitmap("select"),
edouard@3588:                                    wx.NullBitmap,
edouard@3588:                                    _("Select an object"))
Laurent@814:         EditorToolBar.Realize()
Laurent@814:         self.Panes["EditorToolBar"] = EditorToolBar
Laurent@814:         self.AUIManager.AddPane(EditorToolBar, wx.aui.AuiPaneInfo().
andrej@1768:                                 Name("EditorToolBar").Caption(_("Editor ToolBar")).
andrej@1768:                                 ToolbarPane().Top().Position(1).
andrej@1768:                                 LeftDockable(False).RightDockable(False))
Edouard@1408: 
Edouard@1408:         self.Bind(wx.EVT_MENU, self.OnSelectionTool,
andrej@1768:                   id=ID_PLCOPENEDITOREDITORTOOLBARSELECTION)
Edouard@1408: 
andrej@1782:         # -----------------------------------------------------------------------
Laurent@814:         #                            Creating Search Panel
andrej@1782:         # -----------------------------------------------------------------------
Edouard@1408: 
Laurent@814:         self.SearchResultPanel = SearchResultPanel(self.BottomNoteBook, self)
Laurent@814:         self.MainTabs["SearchResultPanel"] = (self.SearchResultPanel, _("Search"))
Laurent@814:         self.BottomNoteBook.AddPage(*self.MainTabs["SearchResultPanel"])
Edouard@1408: 
andrej@1782:         # -----------------------------------------------------------------------
Laurent@814:         #                            Creating Library Panel
andrej@1782:         # -----------------------------------------------------------------------
Edouard@1408: 
Laurent@814:         self.LibraryPanel = LibraryPanel(self, True)
Laurent@814:         self.MainTabs["LibraryPanel"] = (self.LibraryPanel, _("Library"))
Laurent@814:         self.RightNoteBook.AddPage(*self.MainTabs["LibraryPanel"])
Edouard@1408: 
Laurent@814:         self._init_utils()
Laurent@814:         self.SetMenuBar(self.MenuBar)
Edouard@1408: 
Laurent@814:         if self.EnableDebug:
Laurent@902:             self.DebugVariablePanel = DebugVariablePanel(self.RightNoteBook, self.Controler, self)
Laurent@814:             self.MainTabs["DebugVariablePanel"] = (self.DebugVariablePanel, _("Debugger"))
Laurent@814:             self.RightNoteBook.AddPage(*self.MainTabs["DebugVariablePanel"])
Edouard@1408: 
Laurent@814:         self.AUIManager.Update()
Edouard@1408: 
andrej@1744:     def __init__(self, parent, enable_debug=False):
andrej@1836:         wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name='IDEFrame',
andrej@1836:                           parent=parent, pos=wx.DefaultPosition,
andrej@1836:                           size=wx.Size(1000, 600),
andrej@1836:                           style=wx.DEFAULT_FRAME_STYLE)
andrej@1836: 
andrej@2301:         self.UNEDITABLE_NAMES_DICT = dict([(_(n), n) for n in UNEDITABLE_NAMES])
andrej@2301: 
Laurent@814:         self.Controler = None
Laurent@814:         self.Config = wx.ConfigBase.Get()
Laurent@814:         self.EnableDebug = enable_debug
Edouard@1408: 
andrej@2301:         self.InitEditorToolbarItems()
Laurent@814:         self._init_ctrls(parent)
Edouard@1408: 
Laurent@814:         # Define Tree item icon list
Laurent@814:         self.TreeImageList = wx.ImageList(16, 16)
Laurent@814:         self.TreeImageDict = {}
Edouard@1408: 
Laurent@814:         # Icons for languages
Laurent@814:         for language in LANGUAGES:
Laurent@814:             self.TreeImageDict[language] = self.TreeImageList.Add(GetBitmap(language))
Edouard@1408: 
Laurent@814:         # Icons for other items
Laurent@814:         for imgname, itemtype in [
andrej@1766:                 # editables
andrej@1766:                 ("PROJECT",        ITEM_PROJECT),
andrej@1782:                 # ("POU",          ITEM_POU),
andrej@1782:                 # ("VARIABLE",     ITEM_VARIABLE),
andrej@1766:                 ("TRANSITION",     ITEM_TRANSITION),
andrej@1766:                 ("ACTION",         ITEM_ACTION),
andrej@1766:                 ("CONFIGURATION",  ITEM_CONFIGURATION),
andrej@1766:                 ("RESOURCE",       ITEM_RESOURCE),
andrej@1766:                 ("DATATYPE",       ITEM_DATATYPE),
andrej@1766:                 # uneditables
andrej@1766:                 ("DATATYPES",      ITEM_DATATYPES),
andrej@1766:                 ("FUNCTION",       ITEM_FUNCTION),
andrej@1766:                 ("FUNCTIONBLOCK",  ITEM_FUNCTIONBLOCK),
andrej@1766:                 ("PROGRAM",        ITEM_PROGRAM),
andrej@1766:                 ("VAR_LOCAL",      ITEM_VAR_LOCAL),
andrej@1766:                 ("VAR_LOCAL",      ITEM_VAR_GLOBAL),
andrej@1766:                 ("VAR_LOCAL",      ITEM_VAR_EXTERNAL),
andrej@1766:                 ("VAR_LOCAL",      ITEM_VAR_TEMP),
andrej@1766:                 ("VAR_INPUT",      ITEM_VAR_INPUT),
andrej@1766:                 ("VAR_OUTPUT",     ITEM_VAR_OUTPUT),
andrej@1766:                 ("VAR_INOUT",      ITEM_VAR_INOUT),
andrej@1766:                 ("TRANSITIONS",    ITEM_TRANSITIONS),
andrej@1766:                 ("ACTIONS",        ITEM_ACTIONS),
andrej@1766:                 ("CONFIGURATIONS", ITEM_CONFIGURATIONS),
andrej@1766:                 ("RESOURCES",      ITEM_RESOURCES),
andrej@1766:                 ("PROPERTIES",     ITEM_PROPERTIES)]:
Laurent@814:             self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname))
Edouard@1408: 
Laurent@814:         # Assign icon list to TreeCtrls
Laurent@814:         self.ProjectTree.SetImageList(self.TreeImageList)
Laurent@814:         self.PouInstanceVariablesPanel.SetTreeImageList(self.TreeImageList)
Edouard@1408: 
Laurent@814:         self.CurrentEditorToolBar = []
Laurent@814:         self.CurrentMenu = None
Laurent@814:         self.SelectedItem = None
Laurent@1106:         self.LastToolTipItem = None
Laurent@814:         self.SearchParams = None
Laurent@814:         self.Highlights = {}
Laurent@814:         self.DrawingMode = FREEDRAWING_MODE
andrej@1782:         # self.DrawingMode = DRIVENDRAWING_MODE
Laurent@814:         self.AuiTabCtrl = []
Edouard@1408: 
Laurent@980:         # Save default perspective
Laurent@980:         notebooks = {}
Laurent@980:         for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
Laurent@980:                                      (self.BottomNoteBook, "bottomnotebook"),
Laurent@980:                                      (self.RightNoteBook, "rightnotebook")]:
Laurent@980:             notebooks[entry_name] = self.SaveTabLayout(notebook)
Laurent@980:         self.DefaultPerspective = {
Laurent@980:             "perspective": self.AUIManager.SavePerspective(),
Laurent@980:             "notebooks": notebooks,
Laurent@980:         }
Edouard@1408: 
Laurent@814:         # Initialize Printing configuring elements
Laurent@814:         self.PrintData = wx.PrintData()
Laurent@814:         self.PrintData.SetPaperId(wx.PAPER_A4)
Laurent@814:         self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER)
Laurent@814:         self.PageSetupData = wx.PageSetupDialogData(self.PrintData)
Laurent@814:         self.PageSetupData.SetMarginTopLeft(wx.Point(10, 15))
Laurent@814:         self.PageSetupData.SetMarginBottomRight(wx.Point(10, 20))
Edouard@1408: 
Laurent@814:         self.SetRefreshFunctions()
Laurent@1129:         self.SetDeleteFunctions()
Edouard@1408: 
edouard@3350:         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
edouard@3350: 
andrej@1700:         wx.CallAfter(self.InitFindDialog)
andrej@1700: 
andrej@1700:     def InitFindDialog(self):
andrej@1700:         self.FindDialog = FindInPouDialog(self)
andrej@1700:         self.FindDialog.Hide()
andrej@1700: 
Laurent@814:     def Show(self):
Laurent@814:         wx.Frame.Show(self)
Laurent@814:         wx.CallAfter(self.RestoreLastState)
Edouard@1408: 
Laurent@814:     def OnActivated(self, event):
Laurent@814:         if event.GetActive():
Laurent@814:             wx.CallAfter(self._Refresh, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@999:     def SelectTab(self, tab):
Laurent@999:         for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
Laurent@999:             idx = notebook.GetPageIndex(tab)
Laurent@1015:             if idx != wx.NOT_FOUND and idx != notebook.GetSelection():
Laurent@999:                 notebook.SetSelection(idx)
Laurent@999:                 return
Laurent@999: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                Saving and restoring frame organization functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def GetTabInfos(self, tab):
kinsamanka@3750:         for page_name, (page_ref, _page_title) in self.MainTabs.items():
Laurent@981:             if page_ref == tab:
Laurent@981:                 return ("main", page_name)
Laurent@814:         return None
Edouard@1408: 
Laurent@814:     def SaveTabLayout(self, notebook):
Laurent@814:         tabs = []
Laurent@814:         for child in notebook.GetChildren():
Laurent@814:             if isinstance(child, wx.aui.AuiTabCtrl):
Laurent@814:                 if child.GetPageCount() > 0:
Laurent@814:                     pos = child.GetPosition()
Laurent@814:                     tab = {"pos": (pos.x, pos.y), "pages": []}
Laurent@814:                     tab_size = child.GetSize()
kinsamanka@3750:                     for page_idx in range(child.GetPageCount()):
Laurent@814:                         page = child.GetWindowFromIdx(page_idx)
andrej@1775:                         if "size" not in tab:
Laurent@814:                             tab["size"] = (tab_size[0], tab_size[1] + page.GetSize()[1])
Laurent@814:                         tab_infos = self.GetTabInfos(page)
Laurent@814:                         if tab_infos is not None:
Laurent@814:                             tab["pages"].append((tab_infos, page_idx == child.GetActivePage()))
Laurent@814:                     tabs.append(tab)
kinsamanka@3759:         tabs.sort(key=cmp_to_key(lambda x, y: eq(x["pos"], y["pos"])))
Laurent@814:         size = notebook.GetSize()
Laurent@814:         return ComputeTabsLayout(tabs, wx.Rect(1, 1, size[0] - NOTEBOOK_BORDER, size[1] - NOTEBOOK_BORDER))
Edouard@1408: 
Laurent@814:     def LoadTab(self, notebook, page_infos):
Laurent@814:         if page_infos[0] == "main":
Laurent@814:             infos = self.MainTabs.get(page_infos[1])
Laurent@814:             if infos is not None:
Laurent@814:                 page_ref, page_title = infos
Laurent@814:                 notebook.AddPage(page_ref, page_title)
Laurent@814:                 return notebook.GetPageIndex(page_ref)
Laurent@814:         elif page_infos[0] == "editor":
Laurent@814:             tagname = page_infos[1]
Edouard@1948:             page_ref = self.EditProjectElement(GetElementType(tagname), tagname)
Laurent@814:             if page_ref is not None:
Laurent@814:                 page_ref.RefreshView()
Laurent@814:                 return notebook.GetPageIndex(page_ref)
Laurent@814:         elif page_infos[0] == "debug":
Laurent@814:             instance_path = page_infos[1]
Laurent@814:             instance_infos = self.Controler.GetInstanceInfos(instance_path, self.EnableDebug)
Laurent@814:             if instance_infos is not None:
Laurent@814:                 return notebook.GetPageIndex(self.OpenDebugViewer(instance_infos["class"], instance_path, instance_infos["type"]))
Laurent@814:         return None
Edouard@1408: 
Laurent@814:     def LoadTabLayout(self, notebook, tabs, mode="all", first_index=None):
andrej@2450:         if isinstance(tabs, list):
Laurent@814:             if len(tabs) == 0:
Laurent@814:                 return
andrej@1765:             raise ValueError("Not supported")
Edouard@1408: 
andrej@1763:         if "split" in tabs:
Laurent@814:             self.LoadTabLayout(notebook, tabs["others"])
Edouard@1408: 
andrej@1847:             split_dir, _split_ratio = tabs["split"]
Laurent@814:             first_index = self.LoadTabLayout(notebook, tabs["tab"], mode="first")
Laurent@814:             notebook.Split(first_index, split_dir)
Laurent@814:             self.LoadTabLayout(notebook, tabs["tab"], mode="others", first_index=first_index)
Edouard@1408: 
Laurent@814:         elif mode == "first":
Laurent@814:             return self.LoadTab(notebook, tabs["pages"][0][0])
Laurent@814:         else:
Laurent@814:             selected = first_index
Laurent@814:             if mode == "others":
Laurent@814:                 add_tabs = tabs["pages"][1:]
Laurent@814:             else:
Laurent@814:                 add_tabs = tabs["pages"]
Laurent@814:             for page_infos, page_selected in add_tabs:
Laurent@814:                 page_idx = self.LoadTab(notebook, page_infos)
Laurent@814:                 if page_selected:
Laurent@814:                     selected = page_idx
Laurent@814:             if selected is not None:
Laurent@814:                 wx.CallAfter(notebook.SetSelection, selected)
Edouard@1408: 
Laurent@814:     def ResetPerspective(self):
Laurent@814:         if self.DefaultPerspective is not None:
Laurent@814:             self.AUIManager.LoadPerspective(self.DefaultPerspective["perspective"])
Edouard@1408: 
Laurent@814:             for notebook in [self.LeftNoteBook, self.BottomNoteBook, self.RightNoteBook]:
kinsamanka@3750:                 for dummy in range(notebook.GetPageCount()):
Laurent@814:                     notebook.RemovePage(0)
Edouard@1408: 
Laurent@814:             notebooks = self.DefaultPerspective["notebooks"]
Laurent@814:             for notebook, entry_name in [(self.LeftNoteBook, "leftnotebook"),
Laurent@814:                                          (self.BottomNoteBook, "bottomnotebook"),
Laurent@814:                                          (self.RightNoteBook, "rightnotebook")]:
Laurent@814:                 self.LoadTabLayout(notebook, notebooks.get(entry_name))
Edouard@1408: 
Laurent@814:             self._Refresh(EDITORTOOLBAR)
Edouard@1408: 
Laurent@814:     def RestoreLastState(self):
Laurent@814:         frame_size = None
Laurent@814:         if self.Config.HasEntry("framesize"):
kinsamanka@3758:             frame_size = pickle.loads(self.Config.Read("framesize").encode())
Edouard@1408: 
Laurent@814:         if frame_size is None:
Laurent@814:             self.Maximize()
Laurent@814:         else:
Laurent@814:             self.SetClientSize(frame_size)
Edouard@1408: 
Laurent@814:     def SaveLastState(self):
Laurent@814:         if not self.IsMaximized():
kinsamanka@3758:             self.Config.Write("framesize", pickle.dumps(self.GetClientSize(), 0))
Laurent@814:         elif self.Config.HasEntry("framesize"):
Laurent@814:             self.Config.DeleteEntry("framesize")
Edouard@1408: 
Laurent@814:         self.Config.Flush()
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                               General Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def SetRefreshFunctions(self):
Laurent@814:         self.RefreshFunctions = {
andrej@1739:             TITLE: self.RefreshTitle,
andrej@1739:             EDITORTOOLBAR: self.RefreshEditorToolBar,
andrej@1739:             FILEMENU: self.RefreshFileMenu,
andrej@1739:             EDITMENU: self.RefreshEditMenu,
andrej@1739:             DISPLAYMENU: self.RefreshDisplayMenu,
andrej@1739:             PROJECTTREE: self.RefreshProjectTree,
andrej@1739:             POUINSTANCEVARIABLESPANEL: self.RefreshPouInstanceVariablesPanel,
andrej@1739:             LIBRARYTREE: self.RefreshLibraryPanel,
andrej@1739:             SCALING: self.RefreshScaling,
Laurent@814:             PAGETITLES: self.RefreshPageTitles}
Laurent@814: 
Laurent@814:     def _Refresh(self, *elements):
andrej@1781:         """Call Editor refresh functions.
andrej@1781: 
andrej@1781:         :param elements: List of elements to refresh.
andrej@1781:         """
edouard@3303:         for element in elements:
edouard@3303:             self.RefreshFunctions[element]()
Laurent@814: 
Laurent@814:     def OnPageClose(self, event):
andrej@1781:         """Callback function when AUINotebook Page closed with CloseButton
andrej@1781: 
andrej@1781:         :param event: AUINotebook Event.
andrej@1781:         """
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected > -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Edouard@1408: 
Laurent@814:             if window.CheckSaveBeforeClosing():
Edouard@1408: 
Laurent@814:                 # Refresh all window elements that have changed
Laurent@814:                 wx.CallAfter(self._Refresh, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
Laurent@814:                 wx.CallAfter(self.RefreshTabCtrlEvent)
Laurent@814:                 wx.CallAfter(self.CloseFindInPouDialog)
Laurent@814:                 event.Skip()
Laurent@814:             else:
Laurent@814:                 event.Veto()
Edouard@1408: 
Laurent@1015:     def GetCopyBuffer(self, primary_selection=False):
Laurent@814:         data = None
Laurent@1028:         if primary_selection and wx.Platform == '__WXMSW__':
Laurent@1028:             return data
Laurent@1028:         else:
Laurent@1028:             wx.TheClipboard.UsePrimarySelection(primary_selection)
andrej@2166: 
andrej@2166:         if not wx.TheClipboard.IsOpened():
Laurent@814:             dataobj = wx.TextDataObject()
andrej@2166:             if wx.TheClipboard.Open():
andrej@2233:                 success = False
andrej@2233:                 try:
andrej@2233:                     success = wx.TheClipboard.GetData(dataobj)
andrej@2233:                 except wx._core.PyAssertionError:
andrej@2233:                     pass
andrej@2166:                 wx.TheClipboard.Close()
andrej@2166:                 if success:
andrej@2166:                     data = dataobj.GetText()
Laurent@814:         return data
Edouard@1408: 
Laurent@1015:     def SetCopyBuffer(self, text, primary_selection=False):
Laurent@1028:         if primary_selection and wx.Platform == '__WXMSW__':
Laurent@1028:             return
Laurent@1028:         else:
Laurent@1028:             wx.TheClipboard.UsePrimarySelection(primary_selection)
andrej@2166:         if not wx.TheClipboard.IsOpened():
Laurent@814:             data = wx.TextDataObject()
Laurent@814:             data.SetText(text)
andrej@2166:             if wx.TheClipboard.Open():
andrej@2166:                 wx.TheClipboard.SetData(data)
andrej@2166:                 wx.TheClipboard.Flush()
andrej@2166:                 wx.TheClipboard.Close()
andrej@2167:         wx.CallAfter(self.RefreshEditMenu)
Laurent@814: 
Laurent@814:     def GetDrawingMode(self):
Laurent@814:         return self.DrawingMode
Laurent@814: 
Laurent@814:     def RefreshScaling(self):
kinsamanka@3750:         for i in range(self.TabsOpened.GetPageCount()):
Laurent@814:             editor = self.TabsOpened.GetPage(i)
Laurent@814:             editor.RefreshScaling()
Laurent@814: 
Laurent@814:     def EditProjectSettings(self):
Laurent@814:         old_values = self.Controler.GetProjectProperties()
Laurent@814:         dialog = ProjectDialog(self)
Laurent@814:         dialog.SetValues(old_values)
Laurent@814:         if dialog.ShowModal() == wx.ID_OK:
Laurent@814:             new_values = dialog.GetValues()
Laurent@814:             new_values["creationDateTime"] = old_values["creationDateTime"]
Laurent@814:             if new_values != old_values:
Laurent@814:                 self.Controler.SetProjectProperties(None, new_values)
Edouard@1408:                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU,
Laurent@814:                               PROJECTTREE, POUINSTANCEVARIABLESPANEL, SCALING)
Laurent@814:         dialog.Destroy()
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                            Notebook Unified Functions
andrej@1782:     # -------------------------------------------------------------------------------
Edouard@1408: 
Laurent@814:     def AddPage(self, window, text):
andrej@1781:         """Function that add a tab in Notebook, calling refresh for tab DClick event
andrej@1781:         for wx.aui.AUINotebook.
andrej@1781: 
andrej@1781:         :param window: Panel to display in tab.
andrej@1781:         :param text: title for the tab ctrl.
andrej@1781:         """
Laurent@814:         self.TabsOpened.AddPage(window, text)
Laurent@814:         self.RefreshTabCtrlEvent()
Edouard@1408: 
Laurent@814:     def DeletePage(self, window):
kinsamanka@3750:         for idx in range(self.TabsOpened.GetPageCount()):
Laurent@814:             if self.TabsOpened.GetPage(idx) == window:
Laurent@814:                 self.TabsOpened.DeletePage(idx)
Laurent@814:                 self.RefreshTabCtrlEvent()
Edouard@1408:                 return
Edouard@1408: 
Laurent@814:     def DeleteAllPages(self):
andrej@1781:         """Function that fix difference in deleting all tabs between
andrej@1781:         wx.Notebook and wx.aui.AUINotebook.
andrej@1781:         """
kinsamanka@3750:         for dummy in range(self.TabsOpened.GetPageCount()):
Laurent@814:             self.TabsOpened.DeletePage(0)
Laurent@814:         self.RefreshTabCtrlEvent()
Laurent@814: 
Laurent@814:     def SetPageBitmap(self, idx, bitmap):
andrej@1781:         """Function that fix difference in setting picture on tab between
andrej@1781:         wx.Notebook and wx.aui.AUINotebook.
andrej@1781: 
andrej@1781:         :param idx: Tab index.
andrej@1781:         :param bitmap: wx.Bitmap to define on tab.
andrej@1781:         :returns: True if operation succeeded
andrej@1781:         """
Laurent@814:         return self.TabsOpened.SetPageBitmap(idx, bitmap)
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                         Dialog Message Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def ShowErrorMessage(self, message):
andrej@1781:         """Function displaying an Error dialog in editor.
andrej@1781: 
andrej@1781:         :param message: The message to display.
andrej@1781:         """
andrej@1745:         dialog = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR)
Laurent@814:         dialog.ShowModal()
Laurent@814:         dialog.Destroy()
Laurent@814: 
Laurent@814:     def CheckSaveBeforeClosing(self, title=_("Close Project")):
andrej@1781:         """Function displaying an question dialog if project is not saved"
andrej@1781: 
andrej@1781:         :returns: False if closing cancelled.
andrej@1781:         """
Laurent@814:         if not self.Controler.ProjectIsSaved():
andrej@1745:             dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), title, wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION)
Laurent@814:             answer = dialog.ShowModal()
Laurent@814:             dialog.Destroy()
Laurent@814:             if answer == wx.ID_YES:
Laurent@814:                 self.SaveProject()
Laurent@814:             elif answer == wx.ID_CANCEL:
Laurent@814:                 return False
Edouard@1408: 
kinsamanka@3750:         for idx in range(self.TabsOpened.GetPageCount()):
Laurent@814:             window = self.TabsOpened.GetPage(idx)
Laurent@814:             if not window.CheckSaveBeforeClosing():
Laurent@814:                 return False
Edouard@1408: 
Laurent@814:         return True
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                            File Menu Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def RefreshFileMenu(self):
Laurent@814:         pass
Laurent@814: 
Laurent@814:     def ResetView(self):
Laurent@814:         self.DeleteAllPages()
Laurent@814:         self.ProjectTree.DeleteAllItems()
Laurent@814:         self.ProjectTree.Enable(False)
Laurent@814:         self.PouInstanceVariablesPanel.ResetView()
Laurent@814:         self.LibraryPanel.ResetTree()
Laurent@814:         self.LibraryPanel.SetController(None)
Laurent@814:         if self.EnableDebug:
Laurent@916:             self.DebugVariablePanel.ResetView()
Laurent@814:         self.Controler = None
Laurent@814: 
Laurent@814:     def OnCloseTabMenu(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected >= 0:
Laurent@814:             self.TabsOpened.DeletePage(selected)
Laurent@814:             if self.TabsOpened.GetPageCount() > 0:
Laurent@814:                 new_index = min(selected, self.TabsOpened.GetPageCount() - 1)
Laurent@814:                 self.TabsOpened.SetSelection(new_index)
Laurent@814:         # Refresh all window elements that have changed
Laurent@814:         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
Laurent@814:         self.RefreshTabCtrlEvent()
Laurent@814: 
Laurent@814:     def OnPageSetupMenu(self, event):
Laurent@814:         dialog = wx.PageSetupDialog(self, self.PageSetupData)
Laurent@814:         if dialog.ShowModal() == wx.ID_OK:
Laurent@814:             self.PageSetupData = wx.PageSetupDialogData(dialog.GetPageSetupData())
Laurent@814:             self.PrintData = wx.PrintData(self.PageSetupData.GetPrintData())
Laurent@814:         dialog.Destroy()
Laurent@814: 
Laurent@814:     def OnPreviewMenu(self, event):
Edouard@1408:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             data = wx.PrintDialogData(self.PrintData)
Laurent@814:             properties = self.Controler.GetProjectProperties(window.IsDebugging())
kinsamanka@3750:             page_size = list(map(int, properties["pageSize"]))
Laurent@814:             margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
Laurent@814:             printout = GraphicPrintout(window, page_size, margins, True)
Laurent@814:             printout2 = GraphicPrintout(window, page_size, margins, True)
Laurent@814:             preview = wx.PrintPreview(printout, printout2, data)
Laurent@814: 
edouard@3966:             if preview.IsOk():
andrej@1745:                 preview_frame = wx.PreviewFrame(preview, self, _("Print preview"), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT)
Laurent@814: 
Laurent@814:                 preview_frame.Initialize()
Edouard@1408: 
Laurent@814:                 preview_canvas = preview.GetCanvas()
Laurent@814:                 preview_canvas.SetMinSize(preview_canvas.GetVirtualSize())
Laurent@814:                 preview_frame.Fit()
Edouard@1408: 
Laurent@814:                 preview_frame.Show(True)
Laurent@814: 
Laurent@814:     def OnPrintMenu(self, event):
Edouard@1408:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             dialog_data = wx.PrintDialogData(self.PrintData)
Laurent@814:             dialog_data.SetToPage(1)
Laurent@814:             properties = self.Controler.GetProjectProperties(window.IsDebugging())
kinsamanka@3750:             page_size = list(map(int, properties["pageSize"]))
Laurent@814:             margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight())
Laurent@814:             printer = wx.Printer(dialog_data)
Laurent@814:             printout = GraphicPrintout(window, page_size, margins)
Edouard@1408: 
Laurent@814:             if not printer.Print(self, printout, True) and printer.GetLastError() != wx.PRINTER_CANCELLED:
Laurent@814:                 self.ShowErrorMessage(_("There was a problem printing.\nPerhaps your current printer is not set correctly?"))
Laurent@814:             printout.Destroy()
Laurent@814: 
Laurent@814:     def OnPropertiesMenu(self, event):
Laurent@814:         self.EditProjectSettings()
Laurent@814: 
Laurent@814:     def OnQuitMenu(self, event):
Laurent@814:         self.Close()
Laurent@814: 
edouard@3350:     def OnCloseFrame(self, event):
edouard@3350:         self.AUIManager.UnInit()
edouard@3350: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                            Edit Menu Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def RefreshEditMenu(self):
Laurent@814:         MenuToolBar = self.Panes["MenuToolBar"]
Laurent@814:         if self.Controler is not None:
Laurent@814:             selected = self.TabsOpened.GetSelection()
Laurent@814:             if selected > -1:
Laurent@814:                 window = self.TabsOpened.GetPage(selected)
Laurent@814:                 undo, redo = window.GetBufferState()
Laurent@814:             else:
Laurent@814:                 undo, redo = self.Controler.GetBufferState()
Laurent@814:             self.EditMenu.Enable(wx.ID_UNDO, undo)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_UNDO, undo)
Laurent@814:             self.EditMenu.Enable(wx.ID_REDO, redo)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_REDO, redo)
andrej@1782:             # self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, True)
andrej@1782:             # self.EditMenu.Check(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO,
Laurent@814:             #                self.Controler.IsProjectBufferEnabled())
Laurent@814:             self.EditMenu.Enable(wx.ID_FIND, selected > -1)
Edouard@1408:             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDNEXT,
andrej@1768:                                  selected > -1 and self.SearchParams is not None)
Edouard@1408:             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS,
andrej@1768:                                  selected > -1 and self.SearchParams is not None)
Laurent@814:             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
Laurent@814:             MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
edouard@3833:             self.AddMenuItem.Enable(True)
Laurent@814:             self.EditMenu.Enable(wx.ID_DELETE, True)
Laurent@814:             if self.TabsOpened.GetPageCount() > 0:
Laurent@814:                 self.EditMenu.Enable(wx.ID_CUT, True)
Laurent@814:                 MenuToolBar.EnableTool(wx.ID_CUT, True)
Laurent@814:                 self.EditMenu.Enable(wx.ID_COPY, True)
Laurent@814:                 MenuToolBar.EnableTool(wx.ID_COPY, True)
Laurent@814:                 if self.GetCopyBuffer() is not None:
Laurent@814:                     self.EditMenu.Enable(wx.ID_PASTE, True)
Laurent@814:                     MenuToolBar.EnableTool(wx.ID_PASTE, True)
Laurent@814:                 else:
Laurent@814:                     self.EditMenu.Enable(wx.ID_PASTE, False)
Laurent@814:                     MenuToolBar.EnableTool(wx.ID_PASTE, False)
Laurent@814:                 self.EditMenu.Enable(wx.ID_SELECTALL, True)
Laurent@814:             else:
Laurent@814:                 self.EditMenu.Enable(wx.ID_CUT, False)
Laurent@814:                 MenuToolBar.EnableTool(wx.ID_CUT, False)
Laurent@814:                 self.EditMenu.Enable(wx.ID_COPY, False)
Laurent@814:                 MenuToolBar.EnableTool(wx.ID_COPY, False)
Laurent@814:                 self.EditMenu.Enable(wx.ID_PASTE, False)
Laurent@814:                 MenuToolBar.EnableTool(wx.ID_PASTE, False)
Laurent@814:                 self.EditMenu.Enable(wx.ID_SELECTALL, False)
Laurent@814:         else:
Laurent@814:             self.EditMenu.Enable(wx.ID_UNDO, False)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_UNDO, False)
Laurent@814:             self.EditMenu.Enable(wx.ID_REDO, False)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_REDO, False)
andrej@1782:             # self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, False)
Laurent@814:             self.EditMenu.Enable(wx.ID_CUT, False)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_CUT, False)
Laurent@814:             self.EditMenu.Enable(wx.ID_COPY, False)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_COPY, False)
Laurent@814:             self.EditMenu.Enable(wx.ID_PASTE, False)
Laurent@814:             MenuToolBar.EnableTool(wx.ID_PASTE, False)
Laurent@814:             self.EditMenu.Enable(wx.ID_SELECTALL, False)
Laurent@814:             self.EditMenu.Enable(wx.ID_FIND, False)
Laurent@814:             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDNEXT, False)
Laurent@814:             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS, False)
Laurent@814:             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
Laurent@814:             MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
edouard@3833:             self.AddMenuItem.Enable( False)
Laurent@814:             self.EditMenu.Enable(wx.ID_DELETE, False)
Edouard@1408: 
Laurent@814:     def CloseTabsWithoutModel(self, refresh=True):
kinsamanka@3750:         idxs = list(range(self.TabsOpened.GetPageCount()))
Laurent@814:         idxs.reverse()
Laurent@814:         for idx in idxs:
Laurent@814:             window = self.TabsOpened.GetPage(idx)
Laurent@814:             if window.HasNoModel():
Laurent@814:                 self.TabsOpened.DeletePage(idx)
Laurent@814:         if refresh:
Laurent@814:             self.RefreshEditor()
Laurent@814: 
Laurent@814:     def OnUndoMenu(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             window.Undo()
Laurent@814:         else:
Laurent@814:             self.Controler.LoadPrevious()
Edouard@1408:         self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE,
Edouard@1408:                       SCALING, PAGETITLES)
Edouard@1408: 
Laurent@814:     def OnRedoMenu(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             window.Redo()
Laurent@814:         else:
Laurent@814:             self.Controler.LoadNext()
Edouard@1408:         self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE,
Laurent@814:                       SCALING, PAGETITLES)
Edouard@1408: 
Laurent@814:     def OnEnableUndoRedoMenu(self, event):
Laurent@814:         self.Controler.EnableProjectBuffer(event.IsChecked())
Laurent@814:         self.RefreshEditMenu()
Laurent@814: 
Laurent@814:     OnCutMenu = GetShortcutKeyCallbackFunction("Cut")
Laurent@814:     OnCopyMenu = GetShortcutKeyCallbackFunction("Copy")
Laurent@814:     OnPasteMenu = GetShortcutKeyCallbackFunction("Paste")
Laurent@814: 
Laurent@814:     def OnSelectAllMenu(self, event):
Laurent@814:         control = self.FindFocus()
Laurent@814:         if control is not None and control.GetName() == "Viewer":
Laurent@814:             control.Parent.SelectAll()
Laurent@814:         elif isinstance(control, wx.stc.StyledTextCtrl):
Laurent@814:             control.SelectAll()
Laurent@814:         elif isinstance(control, wx.TextCtrl):
Laurent@814:             control.SetSelection(0, control.GetLastPosition())
Laurent@814:         elif isinstance(control, wx.ComboBox):
Laurent@814:             control.SetMark(0, control.GetLastPosition() + 1)
Edouard@1408: 
Laurent@1129:     def SetDeleteFunctions(self):
Laurent@1129:         self.DeleteFunctions = {
Laurent@1129:             ITEM_DATATYPE: GetDeleteElementFunction(
andrej@1878:                 PLCControler.ProjectRemoveDataType,
andrej@1878:                 check_function=self.CheckDataTypeIsUsedBeforeDeletion),
Laurent@1129:             ITEM_POU: GetDeleteElementFunction(
andrej@1878:                 PLCControler.ProjectRemovePou,
andrej@1878:                 check_function=self.CheckPouIsUsedBeforeDeletion),
Laurent@1129:             ITEM_TRANSITION: GetDeleteElementFunction(
andrej@1878:                 PLCControler.ProjectRemovePouTransition, ITEM_POU),
Laurent@1129:             ITEM_ACTION: GetDeleteElementFunction(
andrej@1878:                 PLCControler.ProjectRemovePouAction, ITEM_POU),
Laurent@1129:             ITEM_CONFIGURATION: GetDeleteElementFunction(
andrej@1878:                 PLCControler.ProjectRemoveConfiguration),
Laurent@1129:             ITEM_RESOURCE: GetDeleteElementFunction(
andrej@1878:                 PLCControler.ProjectRemoveConfigurationResource, ITEM_CONFIGURATION)
Laurent@1129:         }
Edouard@1408: 
Laurent@814:     def OnDeleteMenu(self, event):
Laurent@814:         window = self.FindFocus()
Laurent@814:         if window == self.ProjectTree or window is None:
Laurent@814:             selected = self.ProjectTree.GetSelection()
Laurent@1165:             if selected is not None and selected.IsOk():
kinsamanka@3789:                 function = self.DeleteFunctions.get(self.ProjectTree.GetItemData(selected)["type"], None)
Laurent@814:                 if function is not None:
Laurent@814:                     function(self, selected)
Laurent@814:                     self.CloseTabsWithoutModel()
Edouard@1408:                     self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE,
Laurent@814:                                   POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
Laurent@814:         elif isinstance(window, (Viewer, TextViewer)):
Laurent@814:             event = wx.KeyEvent(wx.EVT_CHAR._getEvtType())
Laurent@814:             event.m_keyCode = wx.WXK_DELETE
Laurent@814:             window.ProcessEvent(event)
Laurent@814: 
Laurent@814:     def OnFindMenu(self, event):
Laurent@814:         if not self.FindDialog.IsShown():
Laurent@814:             self.FindDialog.Show()
surkovsv93@1556:             self.FindDialog.FindPattern.SetFocus()
Edouard@1408: 
Laurent@814:     def CloseFindInPouDialog(self):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected == -1 and self.FindDialog.IsShown():
Laurent@814:             self.FindDialog.Hide()
Edouard@1408: 
Laurent@814:     def OnFindNextMenu(self, event):
Laurent@814:         self.FindInPou(1)
Edouard@1408: 
Laurent@814:     def OnFindPreviousMenu(self, event):
Laurent@814:         self.FindInPou(-1)
Edouard@1408: 
Laurent@814:     def FindInPou(self, direction, search_params=None):
Laurent@814:         if search_params is not None:
Laurent@814:             self.SearchParams = search_params
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             window.Find(direction, self.SearchParams)
Edouard@1408: 
Laurent@814:     def OnSearchInProjectMenu(self, event):
Laurent@814:         dialog = SearchInProjectDialog(self)
Laurent@814:         if dialog.ShowModal() == wx.ID_OK:
Laurent@814:             criteria = dialog.GetCriteria()
surkovsv93@1556:             if len(criteria) > 0:
surkovsv93@1556:                 result = self.Controler.SearchInProject(criteria)
surkovsv93@1556:                 self.ClearSearchResults()
surkovsv93@1556:                 self.SearchResultPanel.SetSearchResults(criteria, result)
surkovsv93@1556:                 self.SelectTab(self.SearchResultPanel)
Edouard@1408: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                             Display Menu Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def RefreshDisplayMenu(self):
Laurent@814:         if self.Controler is not None:
Laurent@814:             if self.TabsOpened.GetPageCount() > 0:
Laurent@814:                 self.DisplayMenu.Enable(wx.ID_REFRESH, True)
Laurent@814:                 selected = self.TabsOpened.GetSelection()
Laurent@814:                 if selected != -1:
Laurent@814:                     window = self.TabsOpened.GetPage(selected)
Laurent@814:                     if isinstance(window, Viewer):
edouard@3833:                         self.ZoomMenuItem.Enable(True)
edouard@3833:                         zoommenu = self.ZoomMenuItem.GetSubMenu()
Laurent@814:                         zoomitem = zoommenu.FindItemByPosition(window.GetScale())
Laurent@814:                         zoomitem.Check(True)
Laurent@814:                     else:
edouard@3833:                         self.ZoomMenuItem.Enable(False)
Laurent@814:                 else:
edouard@3833:                     self.ZoomMenuItem.Enable(False)
Laurent@814:             else:
Laurent@814:                 self.DisplayMenu.Enable(wx.ID_REFRESH, False)
edouard@3833:                 self.ZoomMenuItem.Enable(False)
Laurent@814:             if self.EnableDebug:
Laurent@814:                 self.DisplayMenu.Enable(wx.ID_CLEAR, True)
Laurent@814:         else:
Laurent@814:             self.DisplayMenu.Enable(wx.ID_REFRESH, False)
Laurent@814:             if self.EnableDebug:
Laurent@814:                 self.DisplayMenu.Enable(wx.ID_CLEAR, False)
edouard@3833:             self.ZoomMenuItem.Enable(False)
Edouard@1408: 
Laurent@814:     def OnRefreshMenu(self, event):
Laurent@814:         self.RefreshEditor()
Laurent@814: 
Laurent@814:     def OnClearErrorsMenu(self, event):
Laurent@814:         self.ClearErrors()
Laurent@814: 
Laurent@814:     def GenerateZoomFunction(self, idx):
Laurent@814:         def ZoomFunction(event):
Laurent@814:             selected = self.TabsOpened.GetSelection()
Laurent@814:             if selected != -1:
Laurent@814:                 window = self.TabsOpened.GetPage(selected)
Laurent@814:                 window.SetScale(idx)
Laurent@814:                 window.RefreshVisibleElements()
Laurent@814:                 window.RefreshScrollBars()
Laurent@814:             event.Skip()
Laurent@814:         return ZoomFunction
Laurent@814: 
Laurent@814:     def OnResetPerspective(self, event):
Laurent@814:         self.ResetPerspective()
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                      Project Editor Panels Management Functions
andrej@1782:     # -------------------------------------------------------------------------------
Edouard@1408: 
Laurent@814:     def OnPageDragged(self, event):
Laurent@814:         wx.CallAfter(self.RefreshTabCtrlEvent)
Laurent@814:         event.Skip()
Edouard@1408: 
Laurent@814:     def OnAllowNotebookDnD(self, event):
Laurent@814:         event.Allow()
Edouard@1408: 
Laurent@814:     def RefreshTabCtrlEvent(self):
Laurent@814:         auitabctrl = []
Laurent@814:         for child in self.TabsOpened.GetChildren():
Laurent@814:             if isinstance(child, wx.aui.AuiTabCtrl):
Laurent@814:                 auitabctrl.append(child)
edouard@3793:                 if wx.VERSION >= (4, 1, 0) and child not in self.AuiTabCtrl:
Laurent@814:                     child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child))
Laurent@814:         self.AuiTabCtrl = auitabctrl
edouard@3791:         # on wxPython 4.0.7, AuiManager has no "RestorePane" method...
edouard@3793:         if wx.VERSION >= (4, 1, 0) and self.TabsOpened.GetPageCount() == 0:
Laurent@814:             pane = self.AUIManager.GetPane(self.TabsOpened)
edouard@3309:             # on wxPython 4.1.0, AuiPaneInfo has no "IsMaximized" attribute...
edouard@3309:             if (not hasattr(pane, "IsMaximized")) or pane.IsMaximized():
Laurent@814:                 self.AUIManager.RestorePane(pane)
Laurent@814:             self.AUIManager.Update()
Edouard@1408: 
Laurent@814:     def EnsureTabVisible(self, tab):
Laurent@814:         notebook = tab.GetParent()
Laurent@814:         notebook.SetSelection(notebook.GetPageIndex(tab))
Edouard@1408: 
Laurent@814:     def OnPouSelectedChanging(self, event):
Laurent@989:         selected = self.TabsOpened.GetSelection()
Laurent@989:         if selected >= 0:
Laurent@989:             window = self.TabsOpened.GetPage(selected)
Laurent@989:             if not window.IsDebugging():
Laurent@989:                 window.ResetBuffer()
Laurent@814:         event.Skip()
Edouard@1408: 
Laurent@814:     def OnPouSelectedChanged(self, event):
Laurent@989:         selected = self.TabsOpened.GetSelection()
Laurent@989:         if selected >= 0:
Laurent@989:             window = self.TabsOpened.GetPage(selected)
Laurent@989:             tagname = window.GetTagName()
Laurent@989:             if not window.IsDebugging():
Laurent@1158:                 self.SelectProjectTreeItem(tagname)
Laurent@1233:                 self.PouInstanceVariablesPanel.SetPouType(tagname)
Laurent@989:                 window.RefreshView()
Laurent@989:                 self.EnsureTabVisible(self.LibraryPanel)
Laurent@989:             else:
Laurent@989:                 instance_path = window.GetInstancePath()
Laurent@989:                 if tagname == "":
Laurent@989:                     instance_path = instance_path.rsplit(".", 1)[0]
Laurent@989:                     tagname = self.Controler.GetPouInstanceTagName(instance_path, self.EnableDebug)
Laurent@989:                 self.EnsureTabVisible(self.DebugVariablePanel)
Laurent@989:                 wx.CallAfter(self.PouInstanceVariablesPanel.SetPouType, tagname, instance_path)
Laurent@989:         wx.CallAfter(self._Refresh, FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
Laurent@814:         event.Skip()
Edouard@1408: 
Laurent@814:     def RefreshEditor(self):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected >= 0:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             tagname = window.GetTagName()
Laurent@814:             if not window.IsDebugging():
Laurent@814:                 self.SelectProjectTreeItem(tagname)
Laurent@814:                 self.PouInstanceVariablesPanel.SetPouType(tagname)
Laurent@814:             else:
Laurent@814:                 instance_path = window.GetInstancePath()
Laurent@814:                 if tagname == "":
Laurent@814:                     instance_path = instance_path.rsplit(".", 1)[0]
Laurent@814:                     tagname = self.Controler.GetPouInstanceTagName(instance_path, self.EnableDebug)
Laurent@814:                 self.PouInstanceVariablesPanel.SetPouType(tagname, instance_path)
Laurent@814:             for child in self.TabsOpened.GetChildren():
Laurent@814:                 if isinstance(child, wx.aui.AuiTabCtrl):
Laurent@814:                     active_page = child.GetActivePage()
Laurent@814:                     if active_page >= 0:
Laurent@814:                         window = child.GetWindowFromIdx(active_page)
Laurent@814:                         window.RefreshView()
Laurent@814:             self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, EDITORTOOLBAR)
Edouard@1408: 
Laurent@814:     def RefreshEditorNames(self, old_tagname, new_tagname):
kinsamanka@3750:         for i in range(self.TabsOpened.GetPageCount()):
Laurent@814:             editor = self.TabsOpened.GetPage(i)
Laurent@814:             if editor.GetTagName() == old_tagname:
Laurent@814:                 editor.SetTagName(new_tagname)
Edouard@1408: 
Laurent@814:     def IsOpened(self, tagname):
kinsamanka@3750:         for idx in range(self.TabsOpened.GetPageCount()):
Laurent@814:             if self.TabsOpened.GetPage(idx).IsViewing(tagname):
Laurent@814:                 return idx
Laurent@814:         return None
Laurent@814: 
Laurent@814:     def RefreshPageTitles(self):
kinsamanka@3750:         for idx in range(self.TabsOpened.GetPageCount()):
Laurent@814:             window = self.TabsOpened.GetPage(idx)
Laurent@814:             icon = window.GetIcon()
Laurent@814:             if icon is not None:
Laurent@814:                 self.SetPageBitmap(idx, icon)
Laurent@814:             self.TabsOpened.SetPageText(idx, window.GetTitle())
Laurent@814: 
Laurent@814:     def GetTabsOpenedDClickFunction(self, tabctrl):
Laurent@814:         def OnTabsOpenedDClick(event):
Laurent@814:             pos = event.GetPosition()
edouard@3434:             if tabctrl.TabHitTest(pos.x, pos.y):
andrej@2242:                 self.SwitchPerspective(event)
Laurent@814:             event.Skip()
Laurent@814:         return OnTabsOpenedDClick
Laurent@814: 
andrej@2242:     def SwitchPerspective(self, evt):
edouard@3791:         if not hasattr(self.AUIManager, "MaximizePane"):
edouard@3791:             return
surkovsv93@1530:         pane = self.AUIManager.GetPane(self.TabsOpened)
edouard@3309:         # on wxPython 4.1.0, AuiPaneInfo has no "IsMaximized" attribute...
edouard@3434:         IsMaximized = pane.IsMaximized() if hasattr(pane, "IsMaximized") \
edouard@3434:             else (self.TabBookIsMaximized if hasattr(self, "TabBookIsMaximized") \
edouard@3434:                 else False)
edouard@3434:         if IsMaximized:
surkovsv93@1530:             self.AUIManager.RestorePane(pane)
edouard@3434:             self.TabBookIsMaximized = False
surkovsv93@1530:         else:
surkovsv93@1530:             self.AUIManager.MaximizePane(pane)
edouard@3434:             self.TabBookIsMaximized = True
surkovsv93@1530:         self.AUIManager.Update()
surkovsv93@1530: 
andrej@2242:     def SwitchFullScrMode(self, evt):
andrej@2242:         show = not self.IsFullScreen()
andrej@2242:         self.ShowFullScreen(show)
andrej@2242: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                         Types Tree Management Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def RefreshProjectTree(self):
Laurent@1105:         # Extract current selected item tagname
Laurent@1105:         selected = self.ProjectTree.GetSelection()
Laurent@1105:         if selected is not None and selected.IsOk():
kinsamanka@3789:             item_infos = self.ProjectTree.GetItemData(selected)
Laurent@1105:             tagname = item_infos.get("tagname", None)
Laurent@1105:         else:
Laurent@1105:             tagname = None
Edouard@1408: 
Laurent@1105:         # Refresh treectrl items according to project infos
surkovsv93@1884:         if self.Controler:
surkovsv93@1884:             infos = self.Controler.GetProjectInfos()
surkovsv93@1884:             root = self.ProjectTree.GetRootItem()
surkovsv93@1884:             if root is None or not root.IsOk():
surkovsv93@1884:                 root = self.ProjectTree.AddRoot(infos["name"])
surkovsv93@1884:             self.GenerateProjectTreeBranch(root, infos)
surkovsv93@1884:             self.ProjectTree.Expand(root)
Edouard@1408: 
Laurent@1105:         # Select new item corresponding to previous selected item
Laurent@1105:         if tagname is not None:
Laurent@1158:             self.SelectProjectTreeItem(tagname)
Laurent@814: 
Laurent@1164:     def GenerateProjectTreeBranch(self, root, infos, item_alone=False):
Laurent@814:         to_delete = []
Laurent@814:         item_name = infos["name"]
Laurent@814:         if infos["type"] in ITEMS_UNEDITABLE:
Laurent@814:             if len(infos["values"]) == 1:
Laurent@1164:                 return self.GenerateProjectTreeBranch(root, infos["values"][0], True)
Laurent@814:             item_name = _(item_name)
Laurent@814:         self.ProjectTree.SetItemText(root, item_name)
Laurent@814:         self.ProjectTree.SetPyData(root, infos)
andrej@1635:         highlight_colours = self.Highlights.get(infos.get("tagname", None), (wx.Colour(255, 255, 255, 0), wx.BLACK))
denis@1978:         self.ProjectTree.SetItemBackgroundColour(root, highlight_colours[0])
Laurent@814:         self.ProjectTree.SetItemTextColour(root, highlight_colours[1])
Laurent@1188:         self.ProjectTree.SetItemExtraImage(root, None)
Laurent@814:         if infos["type"] == ITEM_POU:
andrej@1768:             self.ProjectTree.SetItemImage(
andrej@1768:                 root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])])
Laurent@1164:             if item_alone:
Laurent@1164:                 self.ProjectTree.SetItemExtraImage(root, self.Controler.GetPouType(infos["name"]))
andrej@1763:         elif "icon" in infos and infos["icon"] is not None:
Laurent@814:             icon_name = infos["icon"]
andrej@1775:             if icon_name not in self.TreeImageDict:
Laurent@814:                 self.TreeImageDict[icon_name] = self.TreeImageList.Add(GetBitmap(icon_name))
Laurent@814:             self.ProjectTree.SetItemImage(root, self.TreeImageDict[icon_name])
andrej@1763:         elif infos["type"] in self.TreeImageDict:
Edouard@1408:             self.ProjectTree.SetItemImage(root, self.TreeImageDict[infos["type"]])
Edouard@1408: 
Laurent@1164:         item, root_cookie = self.ProjectTree.GetFirstChild(root)
Laurent@814:         for values in infos["values"]:
Laurent@814:             if values["type"] not in ITEMS_UNEDITABLE or len(values["values"]) > 0:
Laurent@1164:                 if item is None or not item.IsOk():
Laurent@814:                     item = self.ProjectTree.AppendItem(root, "")
Laurent@1165:                     item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
Laurent@814:                 self.GenerateProjectTreeBranch(item, values)
Laurent@814:                 item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
Laurent@1164:         while item is not None and item.IsOk():
Laurent@814:             to_delete.append(item)
Laurent@814:             item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
Laurent@814:         for item in to_delete:
Laurent@814:             self.ProjectTree.Delete(item)
Laurent@814: 
Laurent@1165:     TagNamePartsItemTypes = {
Laurent@1165:         "D": [ITEM_DATATYPE],
Laurent@1165:         "P": [ITEM_POU],
Laurent@1165:         "T": [ITEM_POU, ITEM_TRANSITION],
Laurent@1165:         "A": [ITEM_POU, ITEM_ACTION],
Laurent@1165:         "C": [ITEM_CONFIGURATION],
Laurent@1165:         "R": [ITEM_CONFIGURATION, ITEM_RESOURCE]}
Laurent@1165: 
Laurent@814:     def SelectProjectTreeItem(self, tagname):
Laurent@1158:         result = False
Laurent@814:         if self.ProjectTree is not None:
Laurent@814:             root = self.ProjectTree.GetRootItem()
Laurent@1165:             if root is not None and root.IsOk():
Laurent@814:                 words = tagname.split("::")
andrej@1768:                 result = self.RecursiveProjectTreeItemSelection(
kinsamanka@3750:                     root, list(zip(words[1:], self.TagNamePartsItemTypes.get(words[0], []))))
Laurent@1158:         return result
Laurent@814: 
Laurent@814:     def RecursiveProjectTreeItemSelection(self, root, items):
Laurent@814:         found = False
Laurent@1164:         item, root_cookie = self.ProjectTree.GetFirstChild(root)
Laurent@1164:         while item is not None and item.IsOk() and not found:
kinsamanka@3789:             item_infos = self.ProjectTree.GetItemData(item)
Laurent@814:             if (item_infos["name"].split(":")[-1].strip(), item_infos["type"]) == items[0]:
Laurent@814:                 if len(items) == 1:
Laurent@814:                     self.SelectedItem = item
Laurent@1158:                     self.ProjectTree.SelectItem(item)
Laurent@1158:                     self.ResetSelectedItem()
Laurent@814:                     return True
Laurent@814:                 else:
Laurent@814:                     found = self.RecursiveProjectTreeItemSelection(item, items[1:])
Laurent@814:             else:
Laurent@814:                 found = self.RecursiveProjectTreeItemSelection(item, items)
Laurent@814:             item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
Laurent@814:         return found
Laurent@814: 
Laurent@1243:     def ResetSelectedItem(self):
Laurent@1243:         self.SelectedItem = None
Laurent@1243: 
Laurent@814:     def OnProjectTreeBeginDrag(self, event):
Edouard@1408:         selected_item = (self.SelectedItem
Laurent@1243:                          if self.SelectedItem is not None
Laurent@1243:                          else event.GetItem())
kinsamanka@3789:         if selected_item.IsOk() and self.ProjectTree.GetItemData(selected_item)["type"] == ITEM_POU:
Laurent@1243:             block_name = self.ProjectTree.GetItemText(selected_item)
Laurent@814:             block_type = self.Controler.GetPouType(block_name)
Laurent@814:             if block_type != "program":
Laurent@814:                 data = wx.TextDataObject(str((block_name, block_type, "")))
Laurent@814:                 dragSource = wx.DropSource(self.ProjectTree)
Laurent@814:                 dragSource.SetData(data)
Laurent@814:                 dragSource.DoDragDrop()
Laurent@814:             self.ResetSelectedItem()
Laurent@814: 
Laurent@814:     def OnProjectTreeItemBeginEdit(self, event):
Laurent@814:         selected = event.GetItem()
kinsamanka@3789:         if self.ProjectTree.GetItemData(selected)["type"] in ITEMS_UNEDITABLE:
Laurent@814:             event.Veto()
Laurent@814:         else:
Laurent@814:             event.Skip()
Laurent@814: 
Laurent@814:     def OnProjectTreeItemEndEdit(self, event):
Laurent@814:         message = None
Laurent@814:         abort = False
Laurent@814:         new_name = event.GetLabel()
Laurent@814:         if new_name != "":
Laurent@814:             if not TestIdentifier(new_name):
andrej@1734:                 message = _("\"%s\" is not a valid identifier!") % new_name
Laurent@814:             elif new_name.upper() in IEC_KEYWORDS:
andrej@1734:                 message = _("\"%s\" is a keyword. It can't be used!") % new_name
Laurent@814:             else:
Laurent@814:                 item = event.GetItem()
Laurent@814:                 old_name = self.ProjectTree.GetItemText(item)
kinsamanka@3789:                 item_infos = self.ProjectTree.GetItemData(item)
Laurent@814:                 if item_infos["type"] == ITEM_PROJECT:
andrej@1744:                     self.Controler.SetProjectProperties(name=new_name)
Laurent@814:                 elif item_infos["type"] == ITEM_DATATYPE:
Laurent@814:                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectDataTypeNames() if name != old_name]:
andrej@1734:                         message = _("\"%s\" data type already exists!") % new_name
Laurent@814:                         abort = True
Laurent@814:                     if not abort:
Laurent@814:                         self.Controler.ChangeDataTypeName(old_name, new_name)
Edouard@1948:                         self.RefreshEditorNames(ComputeDataTypeName(old_name),
Edouard@1948:                                                 ComputeDataTypeName(new_name))
Laurent@814:                         self.RefreshPageTitles()
Laurent@814:                 elif item_infos["type"] == ITEM_POU:
Laurent@814:                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
andrej@1734:                         message = _("\"%s\" pou already exists!") % new_name
Laurent@814:                         abort = True
Laurent@1171:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames()]:
andrej@1745:                         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)
Laurent@814:                         if messageDialog.ShowModal() == wx.ID_NO:
Laurent@814:                             abort = True
Laurent@814:                         messageDialog.Destroy()
Laurent@814:                     if not abort:
Laurent@814:                         self.Controler.ChangePouName(old_name, new_name)
Edouard@1948:                         self.RefreshEditorNames(ComputePouName(old_name),
Edouard@1948:                                                 ComputePouName(new_name))
Laurent@814:                         self.RefreshLibraryPanel()
Laurent@814:                         self.RefreshPageTitles()
Laurent@814:                 elif item_infos["type"] == ITEM_TRANSITION:
andrej@1610:                     pou_item = self.ProjectTree.GetItemParent(event.GetItem())
andrej@1730:                     pou_name = self.ProjectTree.GetItemText(pou_item)
Laurent@814:                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
andrej@1734:                         message = _("A POU named \"%s\" already exists!") % new_name
Laurent@1171:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames(pou_name) if name != old_name]:
andrej@1734:                         message = _("A variable with \"%s\" as name already exists in this pou!") % new_name
Laurent@814:                     else:
Laurent@814:                         words = item_infos["tagname"].split("::")
Laurent@814:                         self.Controler.ChangePouTransitionName(words[1], old_name, new_name)
Edouard@1948:                         self.RefreshEditorNames(ComputePouTransitionName(words[1], old_name),
Edouard@1948:                                                 ComputePouTransitionName(words[1], new_name))
Laurent@814:                         self.RefreshPageTitles()
Laurent@814:                 elif item_infos["type"] == ITEM_ACTION:
andrej@1610:                     pou_item = self.ProjectTree.GetItemParent(event.GetItem())
andrej@1610:                     pou_name = self.ProjectTree.GetItemText(pou_item)
Laurent@814:                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
andrej@1734:                         message = _("A POU named \"%s\" already exists!") % new_name
Laurent@1171:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames(pou_name) if name != old_name]:
andrej@1734:                         message = _("A variable with \"%s\" as name already exists in this pou!") % new_name
Laurent@814:                     else:
Laurent@814:                         words = item_infos["tagname"].split("::")
Laurent@814:                         self.Controler.ChangePouActionName(words[1], old_name, new_name)
Edouard@1948:                         self.RefreshEditorNames(ComputePouActionName(words[1], old_name),
Edouard@1948:                                                 ComputePouActionName(words[1], new_name))
Laurent@814:                         self.RefreshPageTitles()
Laurent@814:                 elif item_infos["type"] == ITEM_CONFIGURATION:
Laurent@814:                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]:
andrej@1734:                         message = _("\"%s\" config already exists!") % new_name
Laurent@814:                         abort = True
Laurent@814:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
andrej@1745:                         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)
Laurent@814:                         if messageDialog.ShowModal() == wx.ID_NO:
Laurent@814:                             abort = True
Laurent@814:                         messageDialog.Destroy()
Laurent@1171:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames()]:
andrej@1745:                         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)
Laurent@814:                         if messageDialog.ShowModal() == wx.ID_NO:
Laurent@814:                             abort = True
Laurent@814:                         messageDialog.Destroy()
Laurent@814:                     if not abort:
Laurent@814:                         self.Controler.ChangeConfigurationName(old_name, new_name)
Edouard@1948:                         self.RefreshEditorNames(ComputeConfigurationName(old_name),
Edouard@1948:                                                 ComputeConfigurationName(new_name))
Laurent@814:                         self.RefreshPageTitles()
Laurent@814:                 elif item_infos["type"] == ITEM_RESOURCE:
Laurent@814:                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]:
andrej@1734:                         message = _("\"%s\" config already exists!") % new_name
Laurent@814:                         abort = True
Laurent@814:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
andrej@1745:                         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)
Laurent@814:                         if messageDialog.ShowModal() == wx.ID_NO:
Laurent@814:                             abort = True
Laurent@814:                         messageDialog.Destroy()
Laurent@1171:                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames()]:
andrej@1745:                         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)
Laurent@814:                         if messageDialog.ShowModal() == wx.ID_NO:
Laurent@814:                             abort = True
Laurent@814:                         messageDialog.Destroy()
Laurent@814:                     if not abort:
Laurent@814:                         words = item_infos["tagname"].split("::")
Laurent@814:                         self.Controler.ChangeConfigurationResourceName(words[1], old_name, new_name)
Edouard@1948:                         self.RefreshEditorNames(ComputeConfigurationResourceName(words[1], old_name),
Edouard@1948:                                                 ComputeConfigurationResourceName(words[1], new_name))
Laurent@814:                         self.RefreshPageTitles()
Laurent@814:             if message or abort:
Laurent@814:                 if message:
Laurent@814:                     self.ShowErrorMessage(message)
Laurent@814:                 event.Veto()
Laurent@814:             else:
Laurent@814:                 wx.CallAfter(self.RefreshProjectTree)
Laurent@814:                 self.RefreshEditor()
Laurent@814:                 self._Refresh(TITLE, FILEMENU, EDITMENU)
Laurent@814:                 event.Skip()
Edouard@1408: 
Laurent@814:     def OnProjectTreeItemActivated(self, event):
Laurent@814:         selected = event.GetItem()
kinsamanka@3789:         item_infos = self.ProjectTree.GetItemData(selected)
Laurent@814:         if item_infos["type"] == ITEM_PROJECT:
Laurent@814:             self.EditProjectSettings()
Laurent@814:         else:
Laurent@814:             if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
andrej@1768:                                       ITEM_CONFIGURATION, ITEM_RESOURCE,
andrej@1768:                                       ITEM_TRANSITION, ITEM_ACTION]:
Laurent@814:                 self.EditProjectElement(item_infos["type"], item_infos["tagname"])
Laurent@814:             event.Skip()
Edouard@1408: 
Laurent@814:     def ProjectTreeItemSelect(self, select_item):
Laurent@1164:         if select_item is not None and select_item.IsOk():
kinsamanka@3789:             item_infos = self.ProjectTree.GetItemData(select_item)
Laurent@1112:             if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
Laurent@1112:                                       ITEM_CONFIGURATION, ITEM_RESOURCE,
Laurent@1112:                                       ITEM_TRANSITION, ITEM_ACTION]:
Laurent@1112:                 self.EditProjectElement(item_infos["type"], item_infos["tagname"], True)
Laurent@1112:                 self.PouInstanceVariablesPanel.SetPouType(item_infos["tagname"])
Edouard@1408: 
Laurent@814:     def OnProjectTreeLeftUp(self, event):
Laurent@814:         if self.SelectedItem is not None:
Laurent@814:             self.ProjectTree.SelectItem(self.SelectedItem)
Laurent@814:             self.ProjectTreeItemSelect(self.SelectedItem)
Laurent@1240:             self.ResetSelectedItem()
Laurent@814:         event.Skip()
Edouard@1408: 
Laurent@1106:     def OnProjectTreeMotion(self, event):
Laurent@1106:         if not event.Dragging():
Laurent@1106:             pt = wx.Point(event.GetX(), event.GetY())
Laurent@1106:             item, flags = self.ProjectTree.HitTest(pt)
Laurent@1164:             if item is not None and item.IsOk() and flags & wx.TREE_HITTEST_ONITEMLABEL:
kinsamanka@3789:                 item_infos = self.ProjectTree.GetItemData(item)
Laurent@1106:                 if item != self.LastToolTipItem and self.LastToolTipItem is not None:
Laurent@1106:                     self.ProjectTree.SetToolTip(None)
Laurent@1106:                     self.LastToolTipItem = None
andrej@1766:                 if self.LastToolTipItem != item and \
andrej@1766:                    item_infos["type"] in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
Laurent@1106:                     bodytype = self.Controler.GetEditedElementBodyType(
andrej@1878:                         item_infos["tagname"])
Laurent@1106:                     if item_infos["type"] == ITEM_POU:
Laurent@1106:                         block_type = {
Laurent@1106:                             "program": _("Program"),
Laurent@1106:                             "functionBlock": _("Function Block"),
Laurent@1106:                             "function": _("Function")
Laurent@1106:                         }[self.Controler.GetPouType(item_infos["name"])]
Laurent@1106:                     elif item_infos["type"] == ITEM_TRANSITION:
Laurent@1106:                         block_type = "Transition"
Laurent@1106:                     else:
Laurent@1106:                         block_type = "Action"
Laurent@1106:                     self.LastToolTipItem = item
edouard@3303:                     wx.CallAfter(self.ProjectTree.SetToolTip,
andrej@1768:                                  "%s : %s : %s" % (
andrej@1768:                                      block_type, bodytype, item_infos["name"]))
Laurent@1106:             elif self.LastToolTipItem is not None:
Laurent@1106:                 self.ProjectTree.SetToolTip(None)
Laurent@1106:                 self.LastToolTipItem = None
Laurent@1106:         event.Skip()
Edouard@1408: 
Laurent@814:     def OnProjectTreeItemChanging(self, event):
kinsamanka@3789:         if self.ProjectTree.GetItemData(event.GetItem())["type"] not in ITEMS_UNEDITABLE and self.SelectedItem is None:
Laurent@814:             self.SelectedItem = event.GetItem()
Laurent@814:             event.Veto()
Laurent@814:         else:
Laurent@814:             event.Skip()
Edouard@1408: 
Edouard@2524:     def GetProjectElementWindow(self, element, tagname):
Edouard@2524:         new_window = None
Edouard@2524:         if self.Controler.GetEditedElement(tagname) is not None:
Edouard@2524:             new_window = None
Edouard@2524:             if element == ITEM_CONFIGURATION:
Edouard@2524:                 new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                 new_window.SetIcon(GetBitmap("CONFIGURATION"))
Edouard@2524:             elif element == ITEM_RESOURCE:
Edouard@2524:                 new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                 new_window.SetIcon(GetBitmap("RESOURCE"))
Edouard@2524:             elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
Edouard@2524:                 bodytype = self.Controler.GetEditedElementBodyType(tagname)
Edouard@2524:                 if bodytype == "FBD":
Edouard@2524:                     new_window = Viewer(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                     new_window.RefreshScaling(False)
Edouard@2524:                 elif bodytype == "LD":
Edouard@2524:                     new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                     new_window.RefreshScaling(False)
Edouard@2524:                 elif bodytype == "SFC":
Edouard@2524:                     new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                     new_window.RefreshScaling(False)
Edouard@2524:                 else:
Edouard@2524:                     new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                     new_window.SetTextSyntax(bodytype)
Edouard@2524:                     if bodytype == "IL":
Edouard@2524:                         new_window.SetKeywords(IL_KEYWORDS)
Edouard@2524:                     else:
Edouard@2524:                         new_window.SetKeywords(ST_KEYWORDS)
Edouard@2524:                 if element == ITEM_POU:
Edouard@2524:                     pou_type = self.Controler.GetEditedElementType(tagname)[1].upper()
Edouard@2524:                     icon = GetBitmap(pou_type, bodytype)
Edouard@2524:                 elif element == ITEM_TRANSITION:
Edouard@2524:                     icon = GetBitmap("TRANSITION", bodytype)
Edouard@2524:                 elif element == ITEM_ACTION:
Edouard@2524:                     icon = GetBitmap("ACTION", bodytype)
Edouard@2524:                 new_window.SetIcon(icon)
Edouard@2524:             elif element == ITEM_DATATYPE:
Edouard@2524:                 new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler)
Edouard@2524:                 new_window.SetIcon(GetBitmap("DATATYPE"))
Edouard@2524:         return new_window
Edouard@2524: 
andrej@1744:     def EditProjectElement(self, element, tagname, onlyopened=False):
Laurent@814:         openedidx = self.IsOpened(tagname)
Laurent@814:         if openedidx is not None:
Laurent@814:             old_selected = self.TabsOpened.GetSelection()
Laurent@814:             if old_selected != openedidx:
Laurent@814:                 if old_selected >= 0:
Laurent@814:                     self.TabsOpened.GetPage(old_selected).ResetBuffer()
Laurent@814:                 self.TabsOpened.SetSelection(openedidx)
Laurent@814:             self._Refresh(FILEMENU, EDITMENU, EDITORTOOLBAR, PAGETITLES)
Laurent@814:         elif not onlyopened:
Laurent@870:             if isinstance(element, EditorPanel):
Laurent@814:                 new_window = element
Edouard@2524:             else:
Edouard@2524:                 new_window = self.GetProjectElementWindow(element, tagname)
Edouard@2524: 
Laurent@814:             if new_window is not None:
Edouard@2524:                 self.AddPage(new_window, "")
Laurent@814:                 openedidx = self.IsOpened(tagname)
Laurent@814:                 old_selected = self.TabsOpened.GetSelection()
Laurent@814:                 if old_selected != openedidx:
Laurent@814:                     if old_selected >= 0:
Laurent@814:                         self.TabsOpened.GetPage(old_selected).ResetBuffer()
kinsamanka@3750:                 for i in range(self.TabsOpened.GetPageCount()):
Laurent@814:                     window = self.TabsOpened.GetPage(i)
Laurent@814:                     if window == new_window:
Laurent@814:                         self.TabsOpened.SetSelection(i)
Laurent@814:                         window.SetFocus()
Laurent@814:                 self.RefreshPageTitles()
Laurent@814:             return new_window
Edouard@1408: 
Laurent@814:     def OnProjectTreeRightUp(self, event):
Laurent@1240:         item = event.GetItem()
Laurent@814:         self.ProjectTree.SelectItem(item)
Laurent@814:         self.ProjectTreeItemSelect(item)
Laurent@814:         name = self.ProjectTree.GetItemText(item)
kinsamanka@3789:         item_infos = self.ProjectTree.GetItemData(item)
Edouard@1408: 
Laurent@814:         menu = None
Laurent@814:         if item_infos["type"] in ITEMS_UNEDITABLE + [ITEM_PROJECT]:
Laurent@814:             if item_infos["type"] == ITEM_PROJECT:
Laurent@814:                 name = "Project"
Laurent@814:             else:
andrej@2301:                 name = self.UNEDITABLE_NAMES_DICT[name]
Edouard@1408: 
Laurent@814:             if name == "Data Types":
Laurent@814:                 menu = wx.Menu(title='')
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add DataType"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, new_item)
Edouard@1408: 
Laurent@814:             elif name in ["Functions", "Function Blocks", "Programs", "Project"]:
Laurent@814:                 menu = wx.Menu(title='')
Edouard@1408: 
Laurent@814:                 if name != "Project":
Edouard@2737:                     new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add POU"))
Edouard@2737:                     self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions": "function", "Function Blocks": "functionBlock", "Programs": "program"}[name]), new_item)
Edouard@2737: 
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Paste POU"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.OnPastePou, new_item)
Laurent@814:                 if self.GetCopyBuffer() is None:
edouard@3716:                     new_item.Enable(False)
Laurent@814: 
Laurent@814:             elif name == "Configurations":
Laurent@814:                 menu = wx.Menu(title='')
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Configuration"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, new_item)
Edouard@1408: 
Laurent@814:             elif name == "Transitions":
Laurent@814:                 menu = wx.Menu(title='')
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Transition"))
Laurent@1010:                 parent = self.ProjectTree.GetItemParent(item)
kinsamanka@3789:                 parent_type = self.ProjectTree.GetItemData(parent)["type"]
Laurent@814:                 while parent_type != ITEM_POU:
Laurent@814:                     parent = self.ProjectTree.GetItemParent(parent)
kinsamanka@3789:                     parent_type = self.ProjectTree.GetItemData(parent)["type"]
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.ProjectTree.GetItemText(parent)), new_item)
Edouard@1408: 
Laurent@814:             elif name == "Actions":
Laurent@814:                 menu = wx.Menu(title='')
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Action"))
Laurent@814:                 parent = self.ProjectTree.GetItemParent(item)
kinsamanka@3789:                 parent_type = self.ProjectTree.GetItemData(parent)["type"]
Laurent@814:                 while parent_type != ITEM_POU:
Laurent@814:                     parent = self.ProjectTree.GetItemParent(parent)
kinsamanka@3789:                     parent_type = self.ProjectTree.GetItemData(parent)["type"]
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.ProjectTree.GetItemText(parent)), new_item)
Edouard@1408: 
Laurent@814:             elif name == "Resources":
Laurent@814:                 menu = wx.Menu(title='')
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Resource"))
Laurent@814:                 parent = self.ProjectTree.GetItemParent(item)
kinsamanka@3789:                 parent_type = self.ProjectTree.GetItemData(parent)["type"]
Laurent@814:                 while parent_type not in [ITEM_CONFIGURATION, ITEM_PROJECT]:
Laurent@814:                     parent = self.ProjectTree.GetItemParent(parent)
kinsamanka@3789:                     parent_type = self.ProjectTree.GetItemData(parent)["type"]
Laurent@1024:                 parent_name = None
Laurent@814:                 if parent_type == ITEM_PROJECT:
Laurent@1024:                     config_names = self.Controler.GetProjectConfigNames()
Laurent@1024:                     if len(config_names) > 0:
Laurent@1024:                         parent_name = config_names[0]
Laurent@814:                 else:
Laurent@814:                     parent_name = self.ProjectTree.GetItemText(parent)
Laurent@1024:                 if parent_name is not None:
Edouard@2737:                     self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(parent_name), new_item)
Edouard@1408: 
Laurent@814:         else:
Laurent@814:             if item_infos["type"] == ITEM_POU:
Laurent@814:                 menu = wx.Menu(title='')
Laurent@814:                 if self.Controler.GetPouBodyType(name) == "SFC":
Edouard@2737:                     new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Transition"))
Edouard@2737:                     self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), new_item)
Edouard@2737:                     new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Action"))
Edouard@2737:                     self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), new_item)
Laurent@814:                     menu.AppendSeparator()
Edouard@1408: 
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Copy POU"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.OnCopyPou, new_item)
Edouard@1408: 
Laurent@814:                 pou_type = self.Controler.GetPouType(name)
Laurent@814:                 if pou_type in ["function", "functionBlock"]:
Laurent@814:                     change_menu = wx.Menu(title='')
Laurent@814:                     if pou_type == "function":
Edouard@2737:                         new_item = AppendMenu(change_menu, help='', kind=wx.ITEM_NORMAL, text=_("Function Block"))
Edouard@2737:                         self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "functionBlock"), new_item)
Edouard@2737:                     new_item = AppendMenu(change_menu, help='', kind=wx.ITEM_NORMAL, text=_("Program"))
Edouard@2737:                     self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "program"), new_item)
Edouard@3439:                     menu.AppendMenu(wx.ID_ANY, _("Duplicate as..."), change_menu)
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Rename"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, new_item)
Edouard@1408: 
Laurent@814:             elif item_infos["type"] == ITEM_CONFIGURATION:
Laurent@814:                 menu = wx.Menu(title='')
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Resource"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(name), new_item)
Edouard@1408: 
Laurent@814:             elif item_infos["type"] in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]:
Laurent@814:                 menu = wx.Menu(title='')
Edouard@1408: 
Laurent@814:             if menu is not None:
Edouard@2737:                 new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Delete"))
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.OnDeleteMenu, new_item)
Edouard@1408: 
Laurent@814:         if menu is not None:
andrej@1480:             self.FindFocus().PopupMenu(menu)
Laurent@814:             menu.Destroy()
Edouard@1408: 
Laurent@1240:         self.ResetSelectedItem()
Edouard@1408: 
Laurent@814:         event.Skip()
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                         Instances Tree Management Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def GetTreeImage(self, var_class):
Laurent@814:         return self.TreeImageDict[var_class]
Edouard@1408: 
Laurent@814:     def RefreshPouInstanceVariablesPanel(self):
Laurent@814:         self.PouInstanceVariablesPanel.RefreshView()
Laurent@814: 
Laurent@814:     def OpenDebugViewer(self, instance_category, instance_path, instance_type):
Laurent@814:         openedidx = self.IsOpened(instance_path)
Laurent@930:         new_window = None
Laurent@814:         if openedidx is not None:
Laurent@814:             old_selected = self.TabsOpened.GetSelection()
Laurent@814:             if old_selected != openedidx:
Laurent@814:                 if old_selected >= 0:
Laurent@814:                     self.TabsOpened.GetPage(old_selected).ResetBuffer()
Laurent@814:                 self.TabsOpened.SetSelection(openedidx)
Edouard@1408: 
Laurent@814:         elif instance_category in ITEMS_VARIABLE:
Laurent@887:             if self.Controler.IsNumType(instance_type, True):
Laurent@1364:                 self.AddDebugVariable(instance_path, True)
Edouard@1408: 
Laurent@814:         else:
Laurent@814:             bodytype = self.Controler.GetEditedElementBodyType(instance_type, True)
Laurent@814:             if bodytype == "FBD":
Laurent@814:                 new_window = Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
Laurent@814:                 new_window.RefreshScaling(False)
Laurent@814:             elif bodytype == "LD":
Laurent@814:                 new_window = LD_Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
Laurent@814:                 new_window.RefreshScaling(False)
Laurent@814:             elif bodytype == "SFC":
Laurent@814:                 new_window = SFC_Viewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
Laurent@814:                 new_window.RefreshScaling(False)
Laurent@814:             else:
Laurent@814:                 new_window = TextViewer(self.TabsOpened, instance_type, self, self.Controler, True, instance_path)
Laurent@814:                 new_window.SetTextSyntax(bodytype)
Laurent@814:                 if bodytype == "IL":
Laurent@814:                     new_window.SetKeywords(IL_KEYWORDS)
Laurent@814:                 else:
Laurent@814:                     new_window.SetKeywords(ST_KEYWORDS)
Edouard@1408: 
Laurent@814:             if new_window is not None:
Laurent@814:                 if instance_category in [ITEM_FUNCTIONBLOCK, ITEM_PROGRAM]:
Laurent@814:                     pou_type = self.Controler.GetEditedElementType(instance_type, True)[1].upper()
Laurent@814:                     icon = GetBitmap(pou_type, bodytype)
Laurent@814:                 elif instance_category == ITEM_TRANSITION:
Laurent@814:                     icon = GetBitmap("TRANSITION", bodytype)
Laurent@814:                 elif instance_category == ITEM_ACTION:
Laurent@814:                     icon = GetBitmap("ACTION", bodytype)
Edouard@1408: 
Laurent@885:         if new_window is not None:
Laurent@885:             new_window.SetIcon(icon)
Laurent@885:             self.AddPage(new_window, "")
Laurent@885:             new_window.RefreshView()
Laurent@885:             new_window.SetFocus()
Laurent@885:             self.RefreshPageTitles()
Laurent@814:         return new_window
Laurent@814: 
Laurent@814:     def ResetGraphicViewers(self):
Laurent@887:         if self.EnableDebug:
Laurent@887:             self.DebugVariablePanel.ResetGraphicsValues()
Laurent@814: 
Laurent@814:     def CloseObsoleteDebugTabs(self):
Laurent@814:         if self.EnableDebug:
kinsamanka@3750:             idxs = list(range(self.TabsOpened.GetPageCount()))
Laurent@814:             idxs.reverse()
Laurent@814:             for idx in idxs:
Laurent@814:                 editor = self.TabsOpened.GetPage(idx)
Laurent@1364:                 if isinstance(editor, Viewer) and editor.IsDebugging():
Laurent@814:                     instance_infos = self.Controler.GetInstanceInfos(editor.GetInstancePath(), self.EnableDebug)
Laurent@814:                     if instance_infos is None:
Laurent@814:                         self.TabsOpened.DeletePage(idx)
Laurent@814:                     else:
Laurent@1176:                         editor.SubscribeAllDataConsumers()
surkovsv93@1710:                 elif editor.IsDebugging() and hasattr(editor, 'SubscribeAllDataConsumers'):
Laurent@1176:                     editor.SubscribeAllDataConsumers()
Laurent@1207:             self.DebugVariablePanel.SubscribeAllDataConsumers()
Edouard@1408: 
Laurent@1214:     def AddDebugVariable(self, iec_path, force=False, graph=False):
Laurent@814:         if self.EnableDebug:
Laurent@1214:             self.DebugVariablePanel.InsertValue(iec_path, force=force, graph=graph)
Laurent@814:             self.EnsureTabVisible(self.DebugVariablePanel)
Edouard@1408: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                         Library Panel Management Function
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def RefreshLibraryPanel(self):
Laurent@814:         self.LibraryPanel.RefreshTree()
Edouard@1408: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                          ToolBars Management Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def AddToMenuToolBar(self, items):
Laurent@814:         MenuToolBar = self.Panes["MenuToolBar"]
Laurent@814:         if MenuToolBar.GetToolsCount() > 0:
Laurent@814:             MenuToolBar.AddSeparator()
Laurent@814:         for toolbar_item in items:
Laurent@814:             if toolbar_item is None:
Laurent@814:                 MenuToolBar.AddSeparator()
Laurent@814:             else:
Laurent@814:                 id, bitmap, help, callback = toolbar_item
edouard@3588:                 MenuToolBar.AddTool(id, help, GetBitmap(bitmap), help)
Laurent@814:                 if callback is not None:
Laurent@814:                     self.Bind(wx.EVT_TOOL, callback, id=id)
Laurent@814:         MenuToolBar.Realize()
Laurent@814:         self.AUIManager.GetPane("MenuToolBar").BestSize(MenuToolBar.GetBestSize())
Laurent@814: 
Laurent@814:     def ResetEditorToolBar(self):
Laurent@814:         EditorToolBar = self.Panes["EditorToolBar"]
Edouard@1408: 
Laurent@814:         for item in self.CurrentEditorToolBar:
andrej@2177:             self.Unbind(wx.EVT_MENU, id=item)
Edouard@1408: 
Laurent@814:             if EditorToolBar:
Laurent@814:                 EditorToolBar.DeleteTool(item)
Edouard@1408: 
Laurent@814:         if EditorToolBar:
Laurent@814:             EditorToolBar.Realize()
Laurent@814:             self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
Laurent@814:             self.AUIManager.GetPane("EditorToolBar").Hide()
Laurent@814:             self.AUIManager.Update()
Laurent@814: 
Laurent@814:     def RefreshEditorToolBar(self):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         menu = None
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@1364:             if isinstance(window, (Viewer, TextViewer)):
Laurent@814:                 if not window.IsDebugging():
Laurent@814:                     menu = self.Controler.GetEditedElementBodyType(window.GetTagName())
Laurent@814:                 else:
Laurent@814:                     menu = "debug"
Laurent@814:         if menu is not None and menu != self.CurrentMenu:
Laurent@814:             self.ResetEditorToolBar()
Laurent@814:             self.CurrentMenu = menu
Laurent@814:             self.CurrentEditorToolBar = []
Laurent@814:             EditorToolBar = self.Panes["EditorToolBar"]
Laurent@814:             if EditorToolBar:
edouard@3588:                 for radio, modes, id, method_name, picture, help in self.EditorToolBarItems[menu]:
Laurent@814:                     if modes & self.DrawingMode:
Laurent@814:                         if radio or self.DrawingMode == FREEDRAWING_MODE:
edouard@3588:                             EditorToolBar.AddRadioTool(id, method_name, GetBitmap(picture), wx.NullBitmap, help)
Laurent@814:                         else:
edouard@3588:                             EditorToolBar.AddTool(id, method_name, GetBitmap(picture), help)
edouard@3588:                         self.Bind(wx.EVT_MENU, getattr(self, method_name), id=id)
Laurent@814:                         self.CurrentEditorToolBar.append(id)
Laurent@814:                 EditorToolBar.Realize()
Laurent@814:                 self.AUIManager.GetPane("EditorToolBar").Show()
Laurent@814:                 self.AUIManager.Update()
andrej@2256:                 self.AUIManager.GetPane("EditorToolBar").BestSize(EditorToolBar.GetBestSize())
andrej@2302:                 self.AUIManager.Update()
Laurent@814:         elif menu is None:
Laurent@814:             self.ResetEditorToolBar()
Laurent@814:             self.CurrentMenu = menu
Laurent@814:         self.ResetCurrentMode()
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                           EditorToolBar Items Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def ResetCurrentMode(self):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             window = self.TabsOpened.GetPage(selected)
Laurent@814:             window.SetMode(MODE_SELECTION)
Laurent@814:         EditorToolBar = self.Panes["EditorToolBar"]
Laurent@814:         if EditorToolBar:
Laurent@814:             EditorToolBar.ToggleTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, False)
Laurent@814:             EditorToolBar.ToggleTool(ID_PLCOPENEDITOREDITORTOOLBARSELECTION, True)
Edouard@1408: 
Laurent@814:     def ResetToolToggle(self, id):
kinsamanka@3763:         tool = self.Panes["EditorToolBar"]
kinsamanka@3763:         tool.ToggleTool(toolId=id, toggle=False)
Laurent@814: 
Laurent@814:     def OnSelectionTool(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION)
Edouard@1408: 
Laurent@814:     def OnMotionTool(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_MOTION)
Edouard@1408: 
Laurent@814:     def OnCommentTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCOMMENT)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT)
Edouard@1408: 
Laurent@814:     def OnVariableTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARVARIABLE)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE)
Edouard@1408: 
Laurent@814:     def OnBlockTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARBLOCK)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK)
Edouard@1408: 
Laurent@814:     def OnConnectionTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCONNECTION)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION)
Edouard@1408: 
Laurent@814:     def OnPowerRailTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARPOWERRAIL)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_POWERRAIL)
Edouard@1408: 
Laurent@814:     def OnRungTool(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).AddLadderRung()
Laurent@814:         event.Skip()
Edouard@1408: 
Laurent@814:     def OnCoilTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCOIL)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_COIL)
Laurent@814:         event.Skip()
Edouard@1408: 
Laurent@814:     def OnContactTool(self, event):
Laurent@814:         if self.DrawingMode == FREEDRAWING_MODE:
Laurent@814:             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARCONTACT)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             if self.DrawingMode == FREEDRAWING_MODE:
Laurent@814:                 self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT)
Laurent@814:             else:
Laurent@814:                 self.TabsOpened.GetPage(selected).AddLadderContact()
Edouard@1408: 
Edouard@1408:     def OnBranchTool(self, event):
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).AddLadderBranch()
Edouard@1408: 
Laurent@814:     def OnInitialStepTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARINITIALSTEP)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_INITIALSTEP)
Edouard@1408: 
Laurent@814:     def OnStepTool(self, event):
Laurent@814:         if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARSTEP)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:                 self.TabsOpened.GetPage(selected).SetMode(MODE_STEP)
Laurent@814:             else:
Laurent@814:                 self.TabsOpened.GetPage(selected).AddStep()
Edouard@1408: 
Laurent@814:     def OnActionBlockTool(self, event):
Laurent@814:         if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARACTIONBLOCK)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:                 self.TabsOpened.GetPage(selected).SetMode(MODE_ACTION)
Laurent@814:             else:
Laurent@814:                 self.TabsOpened.GetPage(selected).AddStepAction()
Edouard@1408: 
Laurent@814:     def OnTransitionTool(self, event):
Laurent@814:         self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARTRANSITION)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             self.TabsOpened.GetPage(selected).SetMode(MODE_TRANSITION)
Edouard@1408: 
Laurent@814:     def OnDivergenceTool(self, event):
Laurent@814:         if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARDIVERGENCE)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:                 self.TabsOpened.GetPage(selected).SetMode(MODE_DIVERGENCE)
Laurent@814:             else:
Laurent@814:                 self.TabsOpened.GetPage(selected).AddDivergence()
Edouard@1408: 
Laurent@814:     def OnJumpTool(self, event):
Laurent@814:         if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:             self.ResetToolToggle(ID_PLCOPENEDITOREDITORTOOLBARJUMP)
Laurent@814:         selected = self.TabsOpened.GetSelection()
Laurent@814:         if selected != -1:
Laurent@814:             if self.GetDrawingMode() == FREEDRAWING_MODE:
Laurent@814:                 self.TabsOpened.GetPage(selected).SetMode(MODE_JUMP)
Laurent@814:             else:
Laurent@814:                 self.TabsOpened.GetPage(selected).AddJump()
Edouard@1408: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                         Add Project Elements Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
surkovsv93@1708:     def OnAddNewProject(self, event):
surkovsv93@1708:         # Asks user to create main program after creating new project
surkovsv93@1708:         AddProgramDialog = self.GenerateAddPouFunction('program', True)
surkovsv93@1708:         # Checks that user created main program
surkovsv93@1708:         if AddProgramDialog(event):
surkovsv93@1708:             self.Controler.SetProjectDefaultConfiguration()
surkovsv93@1708: 
Laurent@814:     def OnAddDataTypeMenu(self, event):
Laurent@814:         tagname = self.Controler.ProjectAddDataType()
Laurent@814:         if tagname is not None:
Laurent@814:             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
Laurent@814:             self.EditProjectElement(ITEM_DATATYPE, tagname)
Edouard@1408: 
andrej@1744:     def GenerateAddPouFunction(self, pou_type, type_readonly=False):
Laurent@814:         def OnAddPouMenu(event):
surkovsv93@1708:             dialog = PouDialog(self, pou_type, type_readonly)
Laurent@814:             dialog.SetPouNames(self.Controler.GetProjectPouNames())
Laurent@1171:             dialog.SetPouElementNames(self.Controler.GetProjectPouVariableNames())
Laurent@814:             dialog.SetValues({"pouName": self.Controler.GenerateNewName(None, None, "%s%%d" % pou_type)})
surkovsv93@1708:             pou_created = False
Laurent@814:             if dialog.ShowModal() == wx.ID_OK:
Laurent@814:                 values = dialog.GetValues()
Laurent@814:                 tagname = self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"])
Laurent@814:                 if tagname is not None:
Laurent@814:                     self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
Laurent@814:                     self.EditProjectElement(ITEM_POU, tagname)
surkovsv93@1708:                     dialog.Destroy()
surkovsv93@1708:                     pou_created = True
Laurent@814:             dialog.Destroy()
surkovsv93@1708:             return pou_created
Laurent@814:         return OnAddPouMenu
Laurent@814: 
Laurent@814:     def GenerateAddTransitionFunction(self, pou_name):
Laurent@814:         def OnAddTransitionMenu(event):
Laurent@814:             dialog = PouTransitionDialog(self)
Laurent@814:             dialog.SetPouNames(self.Controler.GetProjectPouNames())
Laurent@1171:             dialog.SetPouElementNames(self.Controler.GetProjectPouVariableNames(pou_name))
Laurent@814:             dialog.SetValues({"transitionName": self.Controler.GenerateNewName(None, None, "transition%d")})
Edouard@1408:             if dialog.ShowModal() == wx.ID_OK:
Laurent@814:                 values = dialog.GetValues()
Laurent@814:                 tagname = self.Controler.ProjectAddPouTransition(pou_name, values["transitionName"], values["language"])
Laurent@814:                 if tagname is not None:
Laurent@814:                     self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
Laurent@814:                     self.EditProjectElement(ITEM_TRANSITION, tagname)
Laurent@814:             dialog.Destroy()
Laurent@814:         return OnAddTransitionMenu
Laurent@814: 
Laurent@814:     def GenerateAddActionFunction(self, pou_name):
Laurent@814:         def OnAddActionMenu(event):
Laurent@814:             dialog = PouActionDialog(self)
Laurent@814:             dialog.SetPouNames(self.Controler.GetProjectPouNames())
Laurent@1171:             dialog.SetPouElementNames(self.Controler.GetProjectPouVariableNames(pou_name))
Laurent@814:             dialog.SetValues({"actionName": self.Controler.GenerateNewName(None, None, "action%d")})
Laurent@814:             if dialog.ShowModal() == wx.ID_OK:
Laurent@814:                 values = dialog.GetValues()
Laurent@814:                 tagname = self.Controler.ProjectAddPouAction(pou_name, values["actionName"], values["language"])
Laurent@814:                 if tagname is not None:
Laurent@814:                     self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
Laurent@814:                     self.EditProjectElement(ITEM_ACTION, tagname)
Laurent@814:             dialog.Destroy()
Laurent@814:         return OnAddActionMenu
Laurent@814: 
Laurent@814:     def OnAddConfigurationMenu(self, event):
Laurent@814:         tagname = self.Controler.ProjectAddConfiguration()
Laurent@814:         if tagname is not None:
Laurent@814:             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
Laurent@814:             self.EditProjectElement(ITEM_CONFIGURATION, tagname)
Laurent@814: 
Edouard@1408:     def AddResourceMenu(self, event):
Edouard@1408:         config_names = self.Controler.GetProjectConfigNames()
Edouard@1408:         if len(config_names) > 0:
Edouard@1408:             tagname = self.Controler.ProjectAddConfigurationResource(config_names[0])
Edouard@1408:             if tagname is not None:
Edouard@1408:                 self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
Edouard@1408:                 self.EditProjectElement(ITEM_RESOURCE, tagname)
Edouard@1408: 
Laurent@814:     def GenerateAddResourceFunction(self, config_name):
Laurent@814:         def OnAddResourceMenu(event):
Laurent@814:             tagname = self.Controler.ProjectAddConfigurationResource(config_name)
Laurent@814:             if tagname is not None:
Laurent@814:                 self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
Laurent@814:                 self.EditProjectElement(ITEM_RESOURCE, tagname)
Laurent@814:         return OnAddResourceMenu
Laurent@814: 
Laurent@814:     def GenerateChangePouTypeFunction(self, name, new_type):
Laurent@814:         def OnChangePouTypeMenu(event):
Laurent@814:             selected = self.ProjectTree.GetSelection()
kinsamanka@3789:             if self.ProjectTree.GetItemData(selected)["type"] == ITEM_POU:
Laurent@814:                 self.Controler.ProjectChangePouType(name, new_type)
Laurent@814:                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
Laurent@814:         return OnChangePouTypeMenu
Laurent@814: 
Laurent@814:     def OnCopyPou(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
Laurent@814:         pou_name = self.ProjectTree.GetItemText(selected)
Edouard@1408: 
Laurent@814:         pou_xml = self.Controler.GetPouXml(pou_name)
Laurent@814:         if pou_xml is not None:
Laurent@814:             self.SetCopyBuffer(pou_xml)
Laurent@814:             self._Refresh(EDITMENU)
Laurent@814: 
Laurent@814:     def OnPastePou(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
Edouard@1408: 
kinsamanka@3789:         if self.ProjectTree.GetItemData(selected)["type"] != ITEM_PROJECT:
Laurent@814:             pou_type = self.ProjectTree.GetItemText(selected)
andrej@2301:             pou_type = self.UNEDITABLE_NAMES_DICT[pou_type]  # one of 'Functions', 'Function Blocks' or 'Programs'
Laurent@814:             pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type]
Laurent@814:         else:
Laurent@814:             pou_type = None
Edouard@1408: 
Laurent@814:         pou_xml = self.GetCopyBuffer()
Laurent@814: 
Laurent@814:         result = self.Controler.PastePou(pou_type, pou_xml)
Laurent@814: 
andrej@2450:         if not isinstance(result, tuple):
Laurent@1129:             self.ShowErrorMessage(result)
Laurent@814:         else:
Laurent@814:             self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
Laurent@814:             self.EditProjectElement(ITEM_POU, result[0])
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                        Remove Project Elements Functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@1129:     def CheckElementIsUsedBeforeDeletion(self, check_function, title, name):
Laurent@1129:         if not check_function(name):
Laurent@1129:             return True
Edouard@1408: 
andrej@1768:         dialog = wx.MessageDialog(
andrej@1768:             self,
Edouard@1408:             _("\"%s\" is used by one or more POUs. Do you wish to continue?") % name,
andrej@1745:             title, wx.YES_NO | wx.ICON_QUESTION)
Laurent@1129:         answer = dialog.ShowModal()
Laurent@1129:         dialog.Destroy()
Laurent@1129:         return answer == wx.ID_YES
Laurent@1129: 
Laurent@1129:     def CheckDataTypeIsUsedBeforeDeletion(self, name):
Laurent@1129:         return self.CheckElementIsUsedBeforeDeletion(
Laurent@1129:             self.Controler.DataTypeIsUsed,
Laurent@1129:             _("Remove Datatype"), name)
Edouard@1408: 
Laurent@1129:     def CheckPouIsUsedBeforeDeletion(self, name):
Laurent@1129:         return self.CheckElementIsUsedBeforeDeletion(
Laurent@1129:             self.Controler.PouIsUsed,
Laurent@1129:             _("Remove Pou"), name)
Edouard@1408: 
Laurent@814:     def OnRemoveDataTypeMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         if self.ProjectTree.GetItemData(selected)["type"] == ITEM_DATATYPE:
Laurent@814:             name = self.ProjectTree.GetItemText(selected)
Laurent@1129:             if self.CheckDataTypeIsUsedBeforeDeletion(name):
Laurent@814:                 self.Controler.ProjectRemoveDataType(name)
Edouard@1948:                 tagname = ComputeDataTypeName(name)
Laurent@814:                 idx = self.IsOpened(tagname)
Laurent@814:                 if idx is not None:
Laurent@814:                     self.TabsOpened.DeletePage(idx)
Laurent@814:                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE)
Edouard@1408: 
Laurent@814:     def OnRenamePouMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         if self.ProjectTree.GetItemData(selected)["type"] == ITEM_POU:
Laurent@814:             wx.CallAfter(self.ProjectTree.EditLabel, selected)
Laurent@814: 
Laurent@814:     def OnRemovePouMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         if self.ProjectTree.GetItemData(selected)["type"] == ITEM_POU:
Laurent@814:             name = self.ProjectTree.GetItemText(selected)
Laurent@1129:             if self.CheckPouIsUsedBeforeDeletion(name):
Laurent@814:                 self.Controler.ProjectRemovePou(name)
Edouard@1948:                 tagname = ComputePouName(name)
Laurent@814:                 idx = self.IsOpened(tagname)
Laurent@814:                 if idx is not None:
Laurent@814:                     self.TabsOpened.DeletePage(idx)
Laurent@814:                 self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
Laurent@814: 
Laurent@814:     def OnRemoveTransitionMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         item_infos = self.ProjectTree.GetItemData(selected)
Edouard@1408:         if item_infos["type"] == ITEM_TRANSITION:
Laurent@814:             transition = self.ProjectTree.GetItemText(selected)
Laurent@814:             pou_name = item_infos["tagname"].split("::")[1]
Laurent@814:             self.Controler.ProjectRemovePouTransition(pou_name, transition)
Edouard@1948:             tagname = ComputePouTransitionName(pou_name, transition)
Laurent@814:             idx = self.IsOpened(tagname)
Laurent@814:             if idx is not None:
Laurent@814:                 self.TabsOpened.DeletePage(idx)
Laurent@814:             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
Laurent@814: 
Laurent@814:     def OnRemoveActionMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         item_infos = self.ProjectTree.GetItemData(selected)
Edouard@1408:         if item_infos["type"] == ITEM_ACTION:
Laurent@814:             action = self.ProjectTree.GetItemText(selected)
Laurent@814:             pou_name = item_infos["tagname"].split("::")[1]
Laurent@814:             self.Controler.ProjectRemovePouAction(pou_name, action)
Edouard@1948:             tagname = ComputePouActionName(pou_name, action)
Laurent@814:             idx = self.IsOpened(tagname)
Laurent@814:             if idx is not None:
Laurent@814:                 self.TabsOpened.DeletePage(idx)
Laurent@814:             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE)
Laurent@814: 
Laurent@814:     def OnRemoveConfigurationMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         if self.ProjectTree.GetItemData(selected)["type"] == ITEM_CONFIGURATION:
Laurent@814:             name = self.ProjectTree.GetItemText(selected)
Laurent@814:             self.Controler.ProjectRemoveConfiguration(name)
Edouard@1948:             tagname = ComputeConfigurationName(name)
Laurent@814:             idx = self.IsOpened(tagname)
Laurent@814:             if idx is not None:
Laurent@814:                 self.TabsOpened.DeletePage(idx)
Laurent@814:             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
Laurent@814: 
Laurent@814:     def OnRemoveResourceMenu(self, event):
Laurent@814:         selected = self.ProjectTree.GetSelection()
kinsamanka@3789:         item_infos = self.ProjectTree.GetItemData(selected)
Laurent@814:         if item_infos["type"] == ITEM_RESOURCE:
Laurent@814:             resource = self.ProjectTree.GetItemText(selected)
Laurent@814:             config_name = item_infos["tagname"].split("::")[1]
Laurent@814:             self.Controler.ProjectRemoveConfigurationResource(config_name, resource)
Edouard@1948:             tagname = ComputeConfigurationResourceName(config_name, selected)
Laurent@814:             idx = self.IsOpened(tagname)
Laurent@814:             if idx is not None:
Laurent@814:                 self.TabsOpened.DeletePage(idx)
Laurent@814:             self._Refresh(TITLE, FILEMENU, EDITMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL)
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                        Highlights showing functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def ShowHighlight(self, infos, start, end, highlight_type):
Laurent@814:         self.SelectProjectTreeItem(infos[0])
Laurent@814:         if infos[1] == "name":
Laurent@814:             self.Highlights[infos[0]] = highlight_type
Laurent@814:             self.RefreshProjectTree()
Laurent@814:             self.ProjectTree.Unselect()
Laurent@814:         else:
Edouard@1948:             self.EditProjectElement(GetElementType(infos[0]), infos[0])
Laurent@814:             selected = self.TabsOpened.GetSelection()
Laurent@814:             if selected != -1:
Laurent@814:                 viewer = self.TabsOpened.GetPage(selected)
Laurent@814:                 viewer.AddHighlight(infos[1:], start, end, highlight_type)
Laurent@814: 
Laurent@814:     def ShowError(self, infos, start, end):
Laurent@814:         self.ShowHighlight(infos, start, end, ERROR_HIGHLIGHT)
Laurent@814: 
Laurent@814:     def ShowSearchResult(self, infos, start, end):
Laurent@814:         self.ShowHighlight(infos, start, end, SEARCH_RESULT_HIGHLIGHT)
Laurent@814: 
Laurent@814:     def ClearHighlights(self, highlight_type=None):
Laurent@814:         if highlight_type is None:
Laurent@814:             self.Highlights = {}
Laurent@814:         else:
kinsamanka@3750:             self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.items() if highlight != highlight_type])
Laurent@814:         self.RefreshProjectTree()
kinsamanka@3750:         for i in range(self.TabsOpened.GetPageCount()):
Laurent@814:             viewer = self.TabsOpened.GetPage(i)
Laurent@814:             viewer.ClearHighlights(highlight_type)
Laurent@814: 
Laurent@814:     def ClearErrors(self):
Laurent@814:         self.ClearHighlights(ERROR_HIGHLIGHT)
Laurent@814: 
Laurent@814:     def ClearSearchResults(self):
Laurent@814:         self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
laurent@838: 
andrej@1782: # -------------------------------------------------------------------------------
laurent@838: #                               Viewer Printout
andrej@1782: # -------------------------------------------------------------------------------
laurent@838: 
andrej@1749: 
andrej@1762: def UPPER_DIV(x, y):
andrej@2437:     return (x // y) + {True: 0, False: 1}[(x % y) == 0]
laurent@838: 
andrej@1736: 
laurent@838: class GraphicPrintout(wx.Printout):
andrej@1744:     def __init__(self, viewer, page_size, margins, preview=False):
laurent@838:         wx.Printout.__init__(self)
laurent@838:         self.Viewer = viewer
laurent@838:         self.PageSize = page_size
laurent@838:         if self.PageSize[0] == 0 or self.PageSize[1] == 0:
laurent@838:             self.PageSize = (1050, 1485)
edouard@3966:         self.IsPreview = lambda *_x : preview
laurent@838:         self.Margins = margins
laurent@838:         self.FontSize = 5
laurent@838:         self.TextMargin = 3
Edouard@1408: 
laurent@838:         maxx, maxy = viewer.GetMaxSize()
Edouard@1408:         self.PageGrid = (UPPER_DIV(maxx, self.PageSize[0]),
laurent@838:                          UPPER_DIV(maxy, self.PageSize[1]))
Edouard@1408: 
laurent@838:     def GetPageNumber(self):
laurent@838:         return self.PageGrid[0] * self.PageGrid[1]
Edouard@1408: 
laurent@838:     def HasPage(self, page):
laurent@838:         return page <= self.GetPageNumber()
Edouard@1408: 
laurent@838:     def GetPageInfo(self):
laurent@838:         page_number = self.GetPageNumber()
laurent@838:         return (1, page_number, 1, page_number)
laurent@838: 
laurent@838:     def OnBeginDocument(self, startPage, endPage):
laurent@838:         dc = self.GetDC()
edouard@3966:         if not self.IsPreview() and isinstance(dc, wx.PostScriptDC):
laurent@838:             dc.SetResolution(720)
edouard@3966:         return super(GraphicPrintout, self).OnBeginDocument(startPage, endPage)
laurent@838: 
laurent@838:     def OnPrintPage(self, page):
laurent@838:         dc = self.GetDC()
andrej@2342:         dc.SetBackground(wx.WHITE_BRUSH)
andrej@2342:         dc.Clear()
laurent@838:         dc.SetUserScale(1.0, 1.0)
laurent@838:         dc.SetDeviceOrigin(0, 0)
edouard@3966:         dc.printing = not self.IsPreview()
Edouard@1408: 
laurent@838:         # Get the size of the DC in pixels
laurent@838:         ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
laurent@838:         pw, ph = self.GetPageSizePixels()
edouard@3966:         dw, dh = dc.GetSize().Get()
andrej@2437:         Xscale = (dw * ppiPrinterX) / (pw * 25.4)
andrej@2437:         Yscale = (dh * ppiPrinterY) / (ph * 25.4)
Edouard@1408: 
edouard@3966:         fontsize = round(self.FontSize * Yscale)
edouard@3966: 
edouard@3966:         margin_left = round(self.Margins[0].x * Xscale)
edouard@3966:         margin_top = round(self.Margins[0].y * Yscale)
edouard@3966:         area_width = dw - round(self.Margins[1].x * Xscale) - margin_left
edouard@3966:         area_height = dh - round(self.Margins[1].y * Yscale) - margin_top
Edouard@1408: 
laurent@838:         dc.SetPen(MiterPen(wx.BLACK))
Edouard@1408:         dc.SetBrush(wx.TRANSPARENT_BRUSH)
laurent@838:         dc.DrawRectangle(margin_left, margin_top, area_width, area_height)
Edouard@1408: 
laurent@838:         dc.SetFont(wx.Font(fontsize, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
laurent@838:         dc.SetTextForeground(wx.BLACK)
laurent@838:         block_name = " - ".join(self.Viewer.GetTagName().split("::")[1:])
andrej@1847:         _text_width, text_height = dc.GetTextExtent(block_name)
laurent@838:         dc.DrawText(block_name, margin_left, margin_top - text_height - self.TextMargin)
laurent@838:         dc.DrawText(_("Page: %d") % page, margin_left, margin_top + area_height + self.TextMargin)
Edouard@1408: 
laurent@838:         # Calculate the position on the DC for centering the graphic
laurent@838:         posX = area_width * ((page - 1) % self.PageGrid[0])
andrej@2437:         posY = area_height * ((page - 1) // self.PageGrid[0])
andrej@2437: 
andrej@2437:         scaleX = area_width / self.PageSize[0]
andrej@2437:         scaleY = area_height / self.PageSize[1]
laurent@838:         scale = min(scaleX, scaleY)
laurent@838: 
laurent@838:         # Set the scale and origin
laurent@838:         dc.SetDeviceOrigin(-posX + margin_left, -posY + margin_top)
edouard@3966:         dc.SetClippingRegion(posX, posY, round(self.PageSize[0] * scale), round(self.PageSize[1] * scale))
laurent@838:         dc.SetUserScale(scale, scale)
Edouard@1408: 
laurent@838:         self.Viewer.DoDrawing(dc, True)
Edouard@1408: 
laurent@838:         return True