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