etisserant@0: #!/usr/bin/env python etisserant@0: # -*- coding: utf-8 -*- etisserant@0: etisserant@0: #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor etisserant@0: #based on the plcopen standard. etisserant@0: # lbessard@58: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD etisserant@0: # etisserant@0: #See COPYING file for copyrights details. etisserant@0: # etisserant@0: #This library is free software; you can redistribute it and/or etisserant@5: #modify it under the terms of the GNU General Public etisserant@0: #License as published by the Free Software Foundation; either etisserant@0: #version 2.1 of the License, or (at your option) any later version. etisserant@0: # etisserant@0: #This library is distributed in the hope that it will be useful, etisserant@0: #but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lbessard@58: #General Public License for more details. etisserant@0: # etisserant@5: #You should have received a copy of the GNU General Public etisserant@0: #License along with this library; if not, write to the Free Software etisserant@0: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@0: etisserant@0: from datetime import datetime lbessard@120: import wx, wx.grid lbessard@120: lbessard@120: if wx.VERSION >= (2, 8, 0): lbessard@120: import wx.aui lbessard@292: USE_AUI = True lbessard@292: else: lbessard@292: USE_AUI = False etisserant@0: laurent@391: import os, re, platform, sys, time, traceback, getopt laurent@391: import cPickle laurent@391: laurent@391: CWD = os.path.split(os.path.realpath(__file__))[0] laurent@391: base_folder = os.path.split(CWD)[0] laurent@391: sys.path.append(base_folder) laurent@391: from docutils import * laurent@391: laurent@391: from types import TupleType laurent@391: laurent@391: __version__ = "$Revision: 1.130 $" laurent@391: laurent@391: if __name__ == '__main__': laurent@391: # Usage message displayed when help request or when error detected in laurent@391: # command line laurent@391: def usage(): laurent@391: print "\nUsage of PLCOpenEditor.py :" laurent@391: print "\n %s [Filepath]\n"%sys.argv[0] laurent@391: laurent@391: # Parse options given to PLCOpenEditor in command line laurent@391: try: laurent@391: opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) laurent@391: except getopt.GetoptError: laurent@391: # print help information and exit: laurent@391: usage() laurent@391: sys.exit(2) laurent@391: laurent@391: # Extract if help has been requested laurent@391: for o, a in opts: laurent@391: if o in ("-h", "--help"): laurent@391: usage() laurent@391: sys.exit() laurent@391: laurent@391: # Extract the optional filename to open laurent@391: fileOpen = None laurent@391: if len(args) > 1: laurent@391: usage() laurent@391: sys.exit() laurent@391: elif len(args) == 1: laurent@391: fileOpen = args[0] laurent@391: laurent@391: # Create wxApp (Need to create App before internationalization because of laurent@391: # Windows) laurent@391: app = wx.PySimpleApp() laurent@391: laurent@391: # Import module for internationalization laurent@391: import gettext laurent@391: import __builtin__ laurent@391: laurent@391: # Get folder containing translation files laurent@391: localedir = os.path.join(CWD,"locale") laurent@391: # Get the default language laurent@537: langid = wx.LANGUAGE_DEFAULT laurent@391: # Define translation domain (name of translation files) laurent@391: domain = "PLCOpenEditor" laurent@391: laurent@391: # Define locale for wx laurent@391: loc = __builtin__.__dict__.get('loc', None) laurent@391: if loc is None: laurent@513: test_loc = wx.Locale(langid) laurent@513: test_loc.AddCatalogLookupPathPrefix(localedir) laurent@513: if test_loc.AddCatalog(domain): laurent@513: loc = wx.Locale(langid) laurent@513: else: laurent@513: loc = wx.Locale(wx.LANGUAGE_ENGLISH) laurent@391: __builtin__.__dict__['loc'] = loc laurent@391: # Define location for searching translation files laurent@391: loc.AddCatalogLookupPathPrefix(localedir) laurent@391: # Define locale domain laurent@391: loc.AddCatalog(domain) laurent@391: laurent@391: if __name__ == '__main__': laurent@391: __builtin__.__dict__['_'] = wx.GetTranslation laurent@391: etisserant@0: from SFCViewer import * etisserant@0: from LDViewer import * etisserant@0: from Viewer import * lbessard@27: from TextViewer import * lbessard@301: from GraphicViewer import * lbessard@27: from RessourceEditor import * lbessard@125: from DataTypeEditor import * etisserant@0: from PLCControler import * b@418: from VariablePanel import VariablePanel laurent@566: from SearchResultPanel import SearchResultPanel etisserant@0: laurent@391: # Define PLCOpenEditor controls id laurent@407: [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, laurent@407: ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, lbessard@235: ID_PLCOPENEDITORTYPESTREE, ID_PLCOPENEDITORINSTANCESTREE, lbessard@121: ID_PLCOPENEDITORMAINSPLITTER, ID_PLCOPENEDITORSECONDSPLITTER, lbessard@239: ID_PLCOPENEDITORTHIRDSPLITTER, ID_PLCOPENEDITORLIBRARYPANEL, lbessard@239: ID_PLCOPENEDITORLIBRARYTREE, ID_PLCOPENEDITORLIBRARYCOMMENT, lbessard@239: ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTABSOPENED, lbessard@121: ID_PLCOPENEDITORTOOLBAR, ID_PLCOPENEDITORDEFAULTTOOLBAR, lbessard@121: ID_PLCOPENEDITORSFCTOOLBAR, ID_PLCOPENEDITORFBDTOOLBAR, lbessard@121: ID_PLCOPENEDITORLDTOOLBAR, laurent@407: ] = [wx.NewId() for _init_ctrls in range(19)] lbessard@6: laurent@390: # Define PLCOpenEditor FileMenu extra items id lbessard@185: [ID_PLCOPENEDITORFILEMENUGENERATE, lbessard@185: ] = [wx.NewId() for _init_coll_FileMenu_Items in range(1)] lbessard@185: laurent@390: # Define PLCOpenEditor EditMenu extra items id greg@350: [ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, ID_PLCOPENEDITOREDITMENUADDDATATYPE, greg@350: ID_PLCOPENEDITOREDITMENUADDFUNCTION, ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, laurent@566: ID_PLCOPENEDITOREDITMENUADDPROGRAM, ID_PLCOPENEDITOREDITMENUADDCONFIGURATION, laurent@566: ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, laurent@566: ] = [wx.NewId() for _init_coll_EditMenu_Items in range(7)] etisserant@0: lbessard@27: lbessard@27: #------------------------------------------------------------------------------- lbessard@27: # ToolBars definitions lbessard@27: #------------------------------------------------------------------------------- lbessard@27: laurent@390: # Define PLCOpenEditor Toolbar items id lbessard@64: [ID_PLCOPENEDITORTOOLBARSELECTION, ID_PLCOPENEDITORTOOLBARCOMMENT, lbessard@64: ID_PLCOPENEDITORTOOLBARVARIABLE, ID_PLCOPENEDITORTOOLBARBLOCK, lbessard@64: ID_PLCOPENEDITORTOOLBARCONNECTION, ID_PLCOPENEDITORTOOLBARWIRE, lbessard@64: ID_PLCOPENEDITORTOOLBARPOWERRAIL, ID_PLCOPENEDITORTOOLBARRUNG, lbessard@64: ID_PLCOPENEDITORTOOLBARCOIL, ID_PLCOPENEDITORTOOLBARCONTACT, lbessard@64: ID_PLCOPENEDITORTOOLBARBRANCH, ID_PLCOPENEDITORTOOLBARINITIALSTEP, lbessard@64: ID_PLCOPENEDITORTOOLBARSTEP, ID_PLCOPENEDITORTOOLBARTRANSITION, lbessard@64: ID_PLCOPENEDITORTOOLBARACTIONBLOCK, ID_PLCOPENEDITORTOOLBARDIVERGENCE, lbessard@64: ID_PLCOPENEDITORTOOLBARJUMP, lbessard@27: ] = [wx.NewId() for _init_coll_DefaultToolBar_Items in range(17)] lbessard@27: laurent@390: # Define behaviour of each Toolbar item according to current POU body type laurent@390: # Informations meaning are in this order: laurent@390: # - Item is toggled laurent@390: # - PLCOpenEditor mode where item is displayed (could be more then one) laurent@390: # - Item id laurent@390: # - Item callback function name laurent@390: # - Item icon filename laurent@390: # - Item tooltip text lbessard@27: ToolBarItems = { etisserant@184: "FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", laurent@391: "add_comment.png", _("Create a new comment")), etisserant@184: (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", laurent@391: "add_variable.png", _("Create a new variable")), etisserant@184: (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", laurent@391: "add_block.png", _("Create a new block")), etisserant@184: (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", laurent@391: "add_connection.png", _("Create a new connection"))], etisserant@184: "LD" : [(True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", laurent@391: "add_comment.png", _("Create a new comment")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", laurent@391: "add_powerrail.png", _("Create a new power rail")), etisserant@184: (False, DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARRUNG, "OnRungTool", laurent@391: "add_rung.png", _("Create a new rung")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCOIL, "OnCoilTool", laurent@391: "add_coil.png", _("Create a new coil")), etisserant@184: (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", laurent@391: "add_contact.png", _("Create a new contact")), etisserant@184: (False, DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARBRANCH, "OnBranchTool", laurent@391: "add_branch.png", _("Create a new branch")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", laurent@391: "add_variable.png", _("Create a new variable")), etisserant@184: (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", laurent@391: "add_block.png", _("Create a new block")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", laurent@391: "add_connection.png", _("Create a new connection"))], etisserant@184: "SFC" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", laurent@391: "add_comment.png", _("Create a new comment")), etisserant@184: (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARINITIALSTEP, "OnInitialStepTool", laurent@391: "add_initial_step.png", _("Create a new initial step")), etisserant@184: (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARSTEP, "OnStepTool", laurent@391: "add_step.png", _("Create a new step")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARTRANSITION, "OnTransitionTool", laurent@391: "add_transition.png", _("Create a new transition")), etisserant@184: (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARACTIONBLOCK, "OnActionBlockTool", laurent@391: "add_action.png", _("Create a new action block")), etisserant@184: (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARDIVERGENCE, "OnDivergenceTool", laurent@391: "add_divergence.png", _("Create a new divergence")), etisserant@184: (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARJUMP, "OnJumpTool", laurent@391: "add_jump.png", _("Create a new jump")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", laurent@391: "add_variable.png", _("Create a new variable")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", laurent@391: "add_block.png", _("Create a new block")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", laurent@391: "add_connection.png", _("Create a new connection")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", laurent@391: "add_powerrail.png", _("Create a new power rail")), etisserant@184: (True, FREEDRAWING_MODE, etisserant@184: ID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", laurent@391: "add_contact.png", _("Create a new contact"))], lbessard@82: "ST" : [], lbessard@82: "IL" : [] lbessard@27: } lbessard@27: laurent@390: #------------------------------------------------------------------------------- laurent@390: # Helper Functions laurent@390: #------------------------------------------------------------------------------- laurent@390: laurent@390: # Compatibility function for wx versions < 2.6 lbessard@114: def AppendMenu(parent, help, id, kind, text): lbessard@114: if wx.VERSION >= (2, 6, 0): lbessard@114: parent.Append(help=help, id=id, kind=kind, text=text) lbessard@114: else: lbessard@114: parent.Append(helpString=help, id=id, kind=kind, item=text) lbessard@114: laurent@390: [TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, laurent@390: INSTANCESTREE, LIBRARYTREE, SCALING laurent@431: ] = range(9) laurent@390: laurent@390: def GetShortcutKeyCallbackFunction(viewer_function): laurent@390: def ShortcutKeyFunction(self, event): laurent@390: control = self.FindFocus() laurent@390: if isinstance(control, (Viewer, TextViewer)): laurent@390: getattr(control, viewer_function)() laurent@390: elif isinstance(control, wx.TextCtrl): laurent@390: control.ProcessEvent(event) laurent@390: return ShortcutKeyFunction laurent@390: laurent@390: def GetParentName(tree, item, parent_type): laurent@390: parent_item = tree.GetItemParent(item) laurent@390: parent_item_type = tree.GetPyData(parent_item) laurent@390: while parent_item_type != parent_type: laurent@390: parent_item = tree.GetItemParent(parent_item) laurent@390: parent_item_type = tree.GetPyData(parent_item) laurent@390: return tree.GetItemText(parent_item) laurent@390: laurent@390: def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None): laurent@390: def DeleteElementFunction(self, selected): laurent@390: name = self.TypesTree.GetItemText(selected) laurent@407: if check_function is None or not check_function(self.Controler, name): laurent@390: if parent_type is not None: laurent@390: parent_name = GetParentName(self.TypesTree, selected, parent_type) laurent@390: remove_function(self.Controler, parent_name, name) laurent@390: else: laurent@390: remove_function(self.Controler, name) laurent@390: else: laurent@391: self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")%name) laurent@390: return DeleteElementFunction laurent@390: laurent@401: laurent@390: #------------------------------------------------------------------------------- laurent@407: # IDEFrame Base Class laurent@390: #------------------------------------------------------------------------------- laurent@390: laurent@391: UNEDITABLE_NAMES_DICT = dict([(_(name), name) for name in UNEDITABLE_NAMES]) laurent@391: laurent@407: class IDEFrame(wx.Frame): etisserant@0: laurent@384: # Compatibility function for wx versions < 2.6 lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: lbessard@185: def _init_coll_MenuBar_Menus(self, parent): laurent@391: parent.Append(menu=self.FileMenu, title=_(u'File')) laurent@407: parent.Append(menu=self.EditMenu, title=_(u'Edit')) laurent@391: parent.Append(menu=self.DisplayMenu, title=_(u'Display')) laurent@391: parent.Append(menu=self.HelpMenu, title=_(u'Help')) etisserant@0: lbessard@185: def _init_coll_FileMenu_Items(self, parent): laurent@407: pass lbessard@185: lbessard@185: def _init_coll_EditMenu_Items(self, parent): lbessard@332: AppendMenu(parent, help='', id=wx.ID_UNDO, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Undo\tCTRL+Z')) lbessard@332: AppendMenu(parent, help='', id=wx.ID_REDO, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Redo\tCTRL+Y')) laurent@559: #AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, laurent@559: # kind=wx.ITEM_CHECK, text=_(u'Enable Undo/Redo')) laurent@560: enable_undo_redo = _(u'Enable Undo/Redo') # Keeping text in translations for possible menu reactivation lbessard@332: parent.AppendSeparator() lbessard@332: AppendMenu(parent, help='', id=wx.ID_CUT, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Cut\tCTRL+X')) lbessard@332: AppendMenu(parent, help='', id=wx.ID_COPY, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Copy\tCTRL+C')) lbessard@332: AppendMenu(parent, help='', id=wx.ID_PASTE, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Paste\tCTRL+V')) lbessard@332: parent.AppendSeparator() laurent@566: AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, laurent@566: kind=wx.ITEM_NORMAL, text=_(u'Search in Project')) laurent@566: parent.AppendSeparator() lbessard@332: addmenu = wx.Menu(title='') laurent@391: parent.AppendMenu(wx.ID_ADD, _("Add Element"), addmenu) lbessard@332: AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Data Type')) lbessard@332: AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Function')) lbessard@332: AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Function Block')) lbessard@332: AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Program')) lbessard@332: AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Configuration')) lbessard@332: AppendMenu(parent, help='', id=wx.ID_SELECTALL, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Select All\tCTRL+A')) lbessard@332: AppendMenu(parent, help='', id=wx.ID_DELETE, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Delete')) lbessard@332: self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO) lbessard@332: self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO) laurent@562: #self.Bind(wx.EVT_MENU, self.OnEnableUndoRedoMenu, id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO) lbessard@332: self.Bind(wx.EVT_MENU, self.OnCutMenu, id=wx.ID_CUT) lbessard@332: self.Bind(wx.EVT_MENU, self.OnCopyMenu, id=wx.ID_COPY) lbessard@332: self.Bind(wx.EVT_MENU, self.OnPasteMenu, id=wx.ID_PASTE) laurent@566: self.Bind(wx.EVT_MENU, self.OnSearchInProjectMenu, laurent@566: id=ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT) lbessard@332: self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, lbessard@332: id=ID_PLCOPENEDITOREDITMENUADDDATATYPE) lbessard@332: self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("function"), lbessard@332: id=ID_PLCOPENEDITOREDITMENUADDFUNCTION) lbessard@332: self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("functionBlock"), lbessard@332: id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK) lbessard@332: self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("program"), lbessard@332: id=ID_PLCOPENEDITOREDITMENUADDPROGRAM) lbessard@332: self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, lbessard@332: id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION) lbessard@332: self.Bind(wx.EVT_MENU, self.OnSelectAllMenu, id=wx.ID_SELECTALL) lbessard@332: self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE) lbessard@332: lbessard@332: def _init_coll_DisplayMenu_Items(self, parent): lbessard@185: AppendMenu(parent, help='', id=wx.ID_REFRESH, Edouard@569: kind=wx.ITEM_NORMAL, text=_(u'Refresh\tCTRL+R')) laurent@407: if self.EnableDebug: lbessard@332: AppendMenu(parent, help='', id=wx.ID_CLEAR, laurent@391: kind=wx.ITEM_NORMAL, text=_(u'Clear Errors\tCTRL+K')) lbessard@332: parent.AppendSeparator() lbessard@332: zoommenu = wx.Menu(title='') laurent@391: parent.AppendMenu(wx.ID_ZOOM_FIT, _("Zoom"), zoommenu) lbessard@332: for idx, value in enumerate(ZOOM_FACTORS): lbessard@332: new_id = wx.NewId() lbessard@332: AppendMenu(zoommenu, help='', id=new_id, lbessard@332: kind=wx.ITEM_RADIO, text=str(int(round(value * 100))) + "%") lbessard@332: self.Bind(wx.EVT_MENU, self.GenerateZoomFunction(idx), id=new_id) lbessard@185: self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH) laurent@407: if self.EnableDebug: lbessard@332: self.Bind(wx.EVT_MENU, self.OnClearErrorsMenu, id=wx.ID_CLEAR) lbessard@185: etisserant@0: def _init_coll_HelpMenu_Items(self, parent): laurent@407: pass etisserant@0: etisserant@0: def _init_utils(self): lbessard@185: self.MenuBar = wx.MenuBar() etisserant@0: etisserant@220: self.FileMenu = wx.Menu(title='') laurent@407: self.EditMenu = wx.Menu(title='') lbessard@332: self.DisplayMenu = wx.Menu(title='') etisserant@0: self.HelpMenu = wx.Menu(title='') lbessard@163: lbessard@185: self._init_coll_MenuBar_Menus(self.MenuBar) etisserant@220: self._init_coll_FileMenu_Items(self.FileMenu) laurent@407: self._init_coll_EditMenu_Items(self.EditMenu) lbessard@332: self._init_coll_DisplayMenu_Items(self.DisplayMenu) etisserant@0: self._init_coll_HelpMenu_Items(self.HelpMenu) lbessard@239: lbessard@239: def _init_coll_MainLibrarySizer_Items(self, parent): lbessard@239: parent.AddWindow(self.LibraryTree, 0, border=0, flag=wx.GROW) lbessard@239: parent.AddSizer(self.LibraryComment, 0, border=0, flag=wx.GROW) lbessard@239: lbessard@239: def _init_coll_MainLibrarySizer_Growables(self, parent): lbessard@239: parent.AddGrowableCol(0) lbessard@239: parent.AddGrowableRow(0) lbessard@239: lbessard@239: def _init_sizers(self): lbessard@239: self.MainLibrarySizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) lbessard@239: lbessard@239: self._init_coll_MainLibrarySizer_Growables(self.MainLibrarySizer) lbessard@239: self._init_coll_MainLibrarySizer_Items(self.MainLibrarySizer) lbessard@239: lbessard@239: self.LibraryPanel.SetSizer(self.MainLibrarySizer) lbessard@163: etisserant@0: def _init_ctrls(self, prnt): laurent@407: wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name='IDEFrame', lbessard@235: parent=prnt, pos=wx.DefaultPosition, size=wx.Size(1000, 600), laurent@407: style=wx.DEFAULT_FRAME_STYLE) etisserant@0: self._init_utils() etisserant@0: self.SetClientSize(wx.Size(1000, 600)) lbessard@185: self.SetMenuBar(self.MenuBar) laurent@407: laurent@407: self.TabsImageList = wx.ImageList(31, 16) laurent@407: self.TabsImageListIndexes = {} laurent@407: laurent@407: #----------------------------------------------------------------------- laurent@407: # Creating main structure laurent@407: #----------------------------------------------------------------------- lbessard@64: lbessard@292: if USE_AUI: lbessard@120: self.AUIManager = wx.aui.AuiManager(self) lbessard@121: self.AUIManager.SetDockSizeConstraint(0.5, 0.5) lbessard@120: self.Panes = {} laurent@407: laurent@407: self.LeftNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORLEFTNOTEBOOK, laurent@407: style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE| laurent@407: wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE) laurent@407: self.AUIManager.AddPane(self.LeftNoteBook, laurent@407: wx.aui.AuiPaneInfo().Caption(_("Project")).Left().Layer(1). laurent@407: BestSize(wx.Size(300, 500)).CloseButton(False)) laurent@407: laurent@407: self.BottomNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORBOTTOMNOTEBOOK, laurent@407: style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE| laurent@407: wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE) laurent@407: self.AUIManager.AddPane(self.BottomNoteBook, laurent@407: wx.aui.AuiPaneInfo().Bottom().Layer(0). laurent@438: BestSize(wx.Size(800, 300)).CloseButton(False)) laurent@407: laurent@407: self.RightNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORRIGHTNOTEBOOK, laurent@407: style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE| laurent@407: wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE) laurent@407: self.AUIManager.AddPane(self.RightNoteBook, laurent@407: wx.aui.AuiPaneInfo().Right().Layer(0). laurent@407: BestSize(wx.Size(250, 400)).CloseButton(False)) laurent@407: laurent@407: self.TabsOpened = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORTABSOPENED, laurent@407: style=wx.aui.AUI_NB_DEFAULT_STYLE|wx.aui.AUI_NB_WINDOWLIST_BUTTON) laurent@407: self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, laurent@407: self.OnPouSelectedChanged) laurent@407: self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, laurent@407: self.OnPageClose) laurent@407: self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_END_DRAG, laurent@407: self.OnPageDragged) laurent@407: self.AUIManager.AddPane(self.TabsOpened, wx.aui.AuiPaneInfo().CentrePane()) lbessard@292: lbessard@292: else: lbessard@120: self.MainSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORMAINSPLITTER, lbessard@120: name='MainSplitter', parent=self, point=wx.Point(0, 0), lbessard@120: size=wx.Size(0, 0), style=wx.SP_3D) lbessard@120: self.MainSplitter.SetNeedUpdating(True) lbessard@120: self.MainSplitter.SetMinimumPaneSize(1) lbessard@120: laurent@407: self.LeftNoteBook = wx.Notebook(id=ID_PLCOPENEDITORLEFTNOTEBOOK, laurent@407: name='LeftNoteBook', parent=self.MainSplitter, pos=wx.Point(0, laurent@407: 0), size=wx.Size(0, 0), style=0) laurent@407: laurent@407: self.SecondSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORSECONDSPLITTER, laurent@407: name='SecondSplitter', parent=self.MainSplitter, point=wx.Point(0, 0), laurent@407: size=wx.Size(0, 0), style=wx.SP_3D) laurent@407: self.SecondSplitter.SetMinimumPaneSize(1) laurent@407: laurent@407: self.MainSplitter.SplitVertically(self.LeftNoteBook, self.SecondSplitter, 200) laurent@407: laurent@407: self.ThirdSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORTHIRDSPLITTER, laurent@407: name='ThirdSplitter', parent=self.SecondSplitter, point=wx.Point(0, 0), laurent@407: size=wx.Size(0, 0), style=wx.SP_3D) laurent@407: self.ThirdSplitter.SetMinimumPaneSize(1) laurent@407: laurent@407: self.BottomNoteBook = wx.Notebook(id=ID_PLCOPENEDITORBOTTOMNOTEBOOK, laurent@407: name='BottomNoteBook', parent=self.SecondSplitter, pos=wx.Point(0, lbessard@235: 0), size=wx.Size(0, 0), style=0) lbessard@292: laurent@407: self.SecondSplitter.SplitHorizontally(self.ThirdSplitter, self.BottomNoteBook, -200) laurent@407: laurent@407: self.TabsOpened = wx.Notebook(id=ID_PLCOPENEDITORTABSOPENED, laurent@407: name='TabsOpened', parent=self.ThirdSplitter, pos=wx.Point(0, laurent@407: 0), size=wx.Size(0, 0), style=0) laurent@407: self.TabsOpened.SetImageList(self.TabsImageList) laurent@407: if wx.VERSION >= (2, 6, 0): laurent@407: self.TabsOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, laurent@407: self.OnPouSelectedChanged, id=ID_PLCOPENEDITORTABSOPENED) laurent@407: else: laurent@407: wx.EVT_NOTEBOOK_PAGE_CHANGED(self.TabsOpened, ID_PLCOPENEDITORTABSOPENED, laurent@407: self.OnPouSelectedChanged) laurent@407: laurent@407: self.RightNoteBook = wx.Notebook(id=ID_PLCOPENEDITORRIGHTNOTEBOOK, laurent@407: name='RightNoteBook', parent=self.ThirdSplitter, pos=wx.Point(0, laurent@407: 0), size=wx.Size(0, 0), style=0) laurent@407: laurent@407: self.ThirdSplitter.SplitVertically(self.TabsOpened, self.RightNoteBook, -250) laurent@407: laurent@407: #----------------------------------------------------------------------- laurent@407: # Creating PLCopen Project tree laurent@407: #----------------------------------------------------------------------- laurent@407: lbessard@235: self.TypesTree = wx.TreeCtrl(id=ID_PLCOPENEDITORTYPESTREE, laurent@407: name='TypesTree', parent=self.LeftNoteBook, lbessard@235: pos=wx.Point(0, 0), size=wx.Size(0, 0), laurent@407: style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_EDIT_LABELS) laurent@407: if wx.Platform == '__WXMSW__': laurent@407: self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnTypesTreeRightUp, laurent@407: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTypesTreeItemSelected, laurent@407: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: else: laurent@407: if wx.VERSION >= (2, 6, 0): laurent@407: self.TypesTree.Bind(wx.EVT_RIGHT_UP, self.OnTypesTreeRightUp) laurent@407: self.TypesTree.Bind(wx.EVT_LEFT_UP, self.OnTypesTreeLeftUp) lbessard@249: else: laurent@407: wx.EVT_RIGHT_UP(self.TypesTree, self.OnTypesTreeRightUp) laurent@407: wx.EVT_LEFT_UP(self.TypesTree, self.OnTypesTreeLeftUp) laurent@407: self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnTypesTreeItemChanging, lbessard@235: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnTypesTreeBeginDrag, laurent@407: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTypesTreeItemBeginEdit, laurent@407: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTypesTreeItemEndEdit, laurent@407: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTypesTreeItemActivated, laurent@407: id=ID_PLCOPENEDITORTYPESTREE) laurent@407: self.LeftNoteBook.AddPage(self.TypesTree, _("Types")) laurent@407: laurent@407: #----------------------------------------------------------------------- laurent@407: # Creating PLCopen Project tree laurent@407: #----------------------------------------------------------------------- lbessard@235: lbessard@235: self.InstancesTree = wx.TreeCtrl(id=ID_PLCOPENEDITORINSTANCESTREE, laurent@407: name='InstancesTree', parent=self.LeftNoteBook, lbessard@235: pos=wx.Point(0, 0), size=wx.Size(0, 0), lbessard@249: style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) laurent@407: if self.EnableDebug: lbessard@301: if wx.VERSION >= (2, 6, 0): lbessard@301: self.InstancesTree.Bind(wx.EVT_RIGHT_UP, self.OnInstancesTreeRightUp) lbessard@301: else: lbessard@301: wx.EVT_RIGHT_UP(self.InstancesTree, self.OnInstancesTreeRightUp) lbessard@249: self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnInstancesTreeBeginDrag, lbessard@249: id=ID_PLCOPENEDITORINSTANCESTREE) lbessard@249: self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnInstancesTreeItemActivated, lbessard@249: id=ID_PLCOPENEDITORINSTANCESTREE) laurent@407: self.LeftNoteBook.AddPage(self.InstancesTree, _("Instances")) laurent@407: laurent@407: #----------------------------------------------------------------------- laurent@407: # Creating Tool Bar laurent@407: #----------------------------------------------------------------------- laurent@407: laurent@407: if USE_AUI: laurent@407: ToolBar = wx.ToolBar(self, ID_PLCOPENEDITORTOOLBAR, wx.DefaultPosition, wx.DefaultSize, laurent@407: wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER) laurent@407: ToolBar.SetToolBitmapSize(wx.Size(25, 25)) laurent@407: ToolBar.AddRadioTool(ID_PLCOPENEDITORTOOLBARSELECTION, laurent@407: wx.Bitmap(os.path.join(CWD, 'Images', 'select.png')), wx.NullBitmap, _("Select an object")) laurent@407: ToolBar.Realize() laurent@407: self.Panes["ToolBar"] = ToolBar laurent@407: self.AUIManager.AddPane(ToolBar, wx.aui.AuiPaneInfo(). laurent@407: Name("ToolBar").Caption(_("Toolbar")). laurent@407: ToolbarPane().Top(). laurent@407: LeftDockable(False).RightDockable(False)) lbessard@249: else: laurent@407: self.ToolBar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.TB_FLAT|wx.NO_BORDER, laurent@407: ID_PLCOPENEDITORTOOLBAR, 'ToolBar') laurent@407: self.ToolBar.SetToolBitmapSize(wx.Size(25, 25)) laurent@407: self.ToolBar.AddRadioTool(ID_PLCOPENEDITORTOOLBARSELECTION, laurent@407: wx.Bitmap(os.path.join(CWD, 'Images', 'select.png')), wx.NullBitmap, _("Select an object")) laurent@407: self.ToolBar.Realize() lbessard@121: lbessard@249: self.Bind(wx.EVT_TOOL, self.OnSelectionTool, lbessard@249: id=ID_PLCOPENEDITORTOOLBARSELECTION) laurent@407: laurent@407: self.VariablePanelIndexer = VariablePanelIndexer(self.BottomNoteBook, self) laurent@407: self.BottomNoteBook.AddPage(self.VariablePanelIndexer, _("Variables")) laurent@407: laurent@566: self.SearchResultPanel = SearchResultPanel(self.BottomNoteBook, self) laurent@566: self.BottomNoteBook.AddPage(self.SearchResultPanel, _("Search")) laurent@566: laurent@407: self.LibraryPanel = wx.Panel(id=ID_PLCOPENEDITORLIBRARYPANEL, laurent@407: name='LibraryPanel', parent=self.RightNoteBook, pos=wx.Point(0, laurent@407: 0), size=wx.Size(0, 0), style=0) laurent@407: self.RightNoteBook.AddPage(self.LibraryPanel, _("Library")) laurent@407: laurent@407: if wx.Platform == '__WXMSW__': laurent@407: librarytreestyle = wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER laurent@407: else: laurent@407: librarytreestyle = wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER laurent@407: self.LibraryTree = wx.TreeCtrl(id=ID_PLCOPENEDITORLIBRARYTREE, laurent@407: name='LibraryTree', parent=self.LibraryPanel, laurent@407: pos=wx.Point(0, 0), size=wx.Size(0, 0), laurent@407: style=librarytreestyle) laurent@407: self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnLibraryTreeItemSelected, laurent@407: id=ID_PLCOPENEDITORLIBRARYTREE) laurent@407: self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnLibraryTreeBeginDrag, laurent@407: id=ID_PLCOPENEDITORLIBRARYTREE) laurent@407: laurent@407: self.LibraryComment = wx.TextCtrl(id=ID_PLCOPENEDITORLIBRARYCOMMENT, laurent@566: name='LibraryComment', parent=self.LibraryPanel, laurent@566: pos=wx.Point(0, 0), size=wx.Size(0, 160), laurent@566: style=wx.TE_READONLY|wx.TE_MULTILINE) laurent@407: laurent@407: self._init_sizers() laurent@407: laurent@407: if self.EnableDebug: laurent@407: self.DebugVariablePanel = DebugVariablePanel(self.RightNoteBook, self.Controler) laurent@407: self.RightNoteBook.AddPage(self.DebugVariablePanel, _("Debugger")) lbessard@239: lbessard@292: if USE_AUI: lbessard@241: self.AUIManager.Update() lbessard@241: laurent@390: ## Constructor of the PLCOpenEditor class. laurent@390: # @param parent The parent window. laurent@390: # @param controler The controler been used by PLCOpenEditor (default: None). laurent@390: # @param fileOpen The filepath to open if no controler defined (default: None). laurent@390: # @param debug The filepath to open if no controler defined (default: False). laurent@407: def __init__(self, parent, enable_debug = False): laurent@407: self.Controler = None laurent@535: self.Config = wx.ConfigBase.Get() laurent@407: self.EnableDebug = enable_debug lbessard@121: etisserant@0: self._init_ctrls(parent) etisserant@0: laurent@390: # Define Tree item icon list laurent@390: self.TreeImageList = wx.ImageList(16, 16) laurent@390: self.TreeImageDict = {} laurent@390: laurent@390: # Icons for languages etisserant@184: for language in LANGUAGES: laurent@390: self.TreeImageDict[language]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%language))) laurent@390: laurent@390: # Icons for other items etisserant@184: for imgname, itemtype in [ etisserant@184: #editables etisserant@184: ("PROJECT", ITEM_PROJECT), etisserant@184: #("POU", ITEM_POU), etisserant@184: #("VARIABLE", ITEM_VARIABLE), etisserant@184: ("TRANSITION", ITEM_TRANSITION), etisserant@184: ("ACTION", ITEM_ACTION), etisserant@184: ("CONFIGURATION", ITEM_CONFIGURATION), etisserant@184: ("RESOURCE", ITEM_RESOURCE), etisserant@184: ("DATATYPE", ITEM_DATATYPE), etisserant@184: # uneditables etisserant@184: ("DATATYPES", ITEM_DATATYPES), etisserant@184: ("FUNCTION", ITEM_FUNCTION), etisserant@184: ("FUNCTIONBLOCK", ITEM_FUNCTIONBLOCK), etisserant@184: ("PROGRAM", ITEM_PROGRAM), lbessard@235: ("VAR_LOCAL", ITEM_VAR_LOCAL), lbessard@235: ("VAR_LOCAL", ITEM_VAR_GLOBAL), lbessard@235: ("VAR_LOCAL", ITEM_VAR_EXTERNAL), lbessard@235: ("VAR_LOCAL", ITEM_VAR_TEMP), lbessard@235: ("VAR_INPUT", ITEM_VAR_INPUT), lbessard@235: ("VAR_OUTPUT", ITEM_VAR_OUTPUT), lbessard@235: ("VAR_INOUT", ITEM_VAR_INOUT), etisserant@184: ("TRANSITIONS", ITEM_TRANSITIONS), etisserant@184: ("ACTIONS", ITEM_ACTIONS), etisserant@184: ("CONFIGURATIONS", ITEM_CONFIGURATIONS), etisserant@184: ("RESOURCES", ITEM_RESOURCES), etisserant@184: ("PROPERTIES", ITEM_PROPERTIES)]: laurent@390: self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname))) laurent@390: laurent@390: # Assign icon list to TreeCtrls laurent@390: self.TypesTree.SetImageList(self.TreeImageList) laurent@390: self.InstancesTree.SetImageList(self.TreeImageList) lbessard@9: lbessard@6: self.CurrentToolBar = [] lbessard@27: self.CurrentLanguage = "" lbessard@122: self.SelectedItem = None laurent@566: self.Highlights = {} lbessard@71: self.DrawingMode = FREEDRAWING_MODE lbessard@71: #self.DrawingMode = DRIVENDRAWING_MODE lbessard@341: if USE_AUI: lbessard@341: self.AuiTabCtrl = [] lbessard@6: laurent@390: # Initialize Printing configuring elements lbessard@213: self.PrintData = wx.PrintData() lbessard@213: self.PrintData.SetPaperId(wx.PAPER_A4) lbessard@213: self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER) lbessard@213: self.PageSetupData = wx.PageSetupDialogData(self.PrintData) lbessard@213: self.PageSetupData.SetMarginTopLeft(wx.Point(10, 15)) lbessard@213: self.PageSetupData.SetMarginBottomRight(wx.Point(10, 20)) lbessard@213: laurent@407: self.SetRefreshFunctions() laurent@535: laurent@535: def Show(self): laurent@535: wx.Frame.Show(self) laurent@535: wx.CallAfter(self.RestoreFrameSize) laurent@535: laurent@535: def RestoreFrameSize(self): laurent@535: frame_size = None laurent@535: if self.Config.HasEntry("framesize"): laurent@535: frame_size = cPickle.loads(str(self.Config.Read("framesize"))) laurent@535: laurent@535: if frame_size is None: laurent@535: self.Maximize() laurent@535: else: laurent@535: self.SetClientSize(frame_size) laurent@535: laurent@535: def SaveFrameSize(self): laurent@535: if not self.IsMaximized(): laurent@535: self.Config.Write("framesize", cPickle.dumps(self.GetClientSize())) laurent@535: elif self.Config.HasEntry("framesize"): laurent@535: self.Config.DeleteEntry("framesize") laurent@535: self.Config.Flush() laurent@390: laurent@390: #------------------------------------------------------------------------------- laurent@390: # General Functions laurent@390: #------------------------------------------------------------------------------- laurent@390: laurent@407: def SetRefreshFunctions(self): laurent@407: self.RefreshFunctions = { laurent@407: TITLE : self.RefreshTitle, laurent@407: TOOLBAR : self.RefreshToolBar, laurent@407: FILEMENU : self.RefreshFileMenu, laurent@407: EDITMENU : self.RefreshEditMenu, laurent@407: DISPLAYMENU : self.RefreshDisplayMenu, laurent@407: TYPESTREE : self.RefreshTypesTree, laurent@407: INSTANCESTREE : self.RefreshInstancesTree, laurent@407: LIBRARYTREE : self.RefreshLibraryTree, laurent@407: SCALING : self.RefreshScaling} laurent@407: laurent@390: ## Call PLCOpenEditor refresh functions. laurent@390: # @param elements List of elements to refresh. laurent@390: def _Refresh(self, *elements): laurent@390: for element in elements: laurent@407: self.RefreshFunctions[element]() laurent@390: laurent@390: ## Callback function when AUINotebook Page closed with CloseButton laurent@390: # @param event AUINotebook Event. lbessard@121: def OnPageClose(self, event): laurent@390: # Get Selected Tab lbessard@294: selected = event.GetSelection() lbessard@121: if selected >= 0: laurent@390: # Remove corresponding VariablePanel laurent@407: window = self.TabsOpened.GetPage(selected) laurent@407: if not window.IsDebugging(): laurent@407: self.VariablePanelIndexer.RemoveVariablePanel(window.GetTagName()) laurent@514: lbessard@341: wx.CallAfter(self.RefreshTabCtrlEvent) lbessard@341: event.Skip() lbessard@341: lbessard@114: def GetCopyBuffer(self): laurent@384: data = None laurent@402: if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open(): laurent@384: dataobj = wx.TextDataObject() laurent@384: if wx.TheClipboard.GetData(dataobj): laurent@384: data = dataobj.GetText() laurent@403: if wx.TheClipboard.IsOpened(): laurent@384: wx.TheClipboard.Close() laurent@384: return data laurent@384: laurent@384: def SetCopyBuffer(self, text): laurent@402: if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open(): laurent@384: data = wx.TextDataObject() laurent@384: data.SetText(text) laurent@384: wx.TheClipboard.SetData(data) laurent@384: wx.TheClipboard.Flush() laurent@403: if wx.TheClipboard.IsOpened(): laurent@384: wx.TheClipboard.Close() lbessard@114: self.RefreshEditMenu() lbessard@114: lbessard@27: def GetDrawingMode(self): lbessard@27: return self.DrawingMode lbessard@27: lbessard@331: def RefreshScaling(self): lbessard@331: for i in xrange(self.TabsOpened.GetPageCount()): lbessard@331: editor = self.TabsOpened.GetPage(i) lbessard@331: editor.RefreshScaling() lbessard@331: lbessard@27: def ShowProperties(self): laurent@407: old_values = self.Controler.GetProjectProperties() lbessard@27: dialog = ProjectDialog(self) lbessard@27: dialog.SetValues(old_values) lbessard@64: if dialog.ShowModal() == wx.ID_OK: lbessard@27: new_values = dialog.GetValues() lbessard@27: new_values["creationDateTime"] = old_values["creationDateTime"] lbessard@145: if new_values != old_values: lbessard@145: self.Controler.SetProjectProperties(None, new_values) laurent@390: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, laurent@390: TYPESTREE, INSTANCESTREE, SCALING) lbessard@27: dialog.Destroy() lbessard@27: laurent@390: #------------------------------------------------------------------------------- laurent@390: # Notebook Unified Functions laurent@390: #------------------------------------------------------------------------------- laurent@390: laurent@390: ## Function that generate bitmap for laurent@390: # for wx.aui.AUINotebook. laurent@390: # @param window Panel to display in tab. laurent@390: # @param text title for the tab ctrl. laurent@390: def GenerateBitmap(self, icon1_name, icon2_name = None): laurent@390: # Find index of bitmap if already created laurent@390: index = self.TabsImageListIndexes.get((icon1_name, icon2_name), None) laurent@390: # Return index or bitmap if found laurent@390: if index is not None: laurent@390: if USE_AUI: laurent@390: return self.TabsImageList.GetBitmap(index) lbessard@80: else: lbessard@292: return index lbessard@292: if icon2_name is None: laurent@390: # Bitmap with only one icon laurent@401: bitmap = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon1_name)) lbessard@292: else: laurent@390: # Bitmap with two icon lbessard@292: icon1 = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon1_name)) lbessard@292: icon2 = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon2_name)) laurent@401: laurent@390: # Calculate bitmap size lbessard@292: width = icon1.GetWidth() + icon2.GetWidth() - 1 lbessard@292: height = max(icon1.GetHeight(), icon2.GetHeight()) laurent@390: # Create bitmap with both icons laurent@401: bitmap = wx.EmptyBitmap(width, height) lbessard@292: dc = wx.MemoryDC() laurent@401: dc.SelectObject(bitmap) lbessard@292: dc.Clear() lbessard@292: dc.DrawBitmap(icon1, 0, 0) lbessard@292: dc.DrawBitmap(icon2, icon1.GetWidth() - 1, 0) laurent@401: dc.Destroy() laurent@401: laurent@397: # Store bitmap in ImageList laurent@401: index = self.TabsImageList.Add(bitmap) laurent@397: # Save bitmap index in ImageList in dictionary laurent@397: self.TabsImageListIndexes[(icon1_name, icon2_name)] = index lbessard@292: if USE_AUI: laurent@401: return bitmap lbessard@292: else: lbessard@292: return index lbessard@337: laurent@390: ## Function that add a tab in Notebook, calling refresh for tab DClick event laurent@390: # for wx.aui.AUINotebook. laurent@390: # @param window Panel to display in tab. laurent@390: # @param text title for the tab ctrl. lbessard@337: def AddPage(self, window, text): lbessard@337: self.TabsOpened.AddPage(window, text) lbessard@341: self.RefreshTabCtrlEvent() lbessard@341: laurent@390: ## Function that fix difference in deleting all tabs between laurent@390: # wx.Notebook and wx.aui.AUINotebook. lbessard@163: def DeleteAllPages(self): lbessard@292: if USE_AUI: lbessard@235: for idx in xrange(self.TabsOpened.GetPageCount()): lbessard@235: self.TabsOpened.DeletePage(0) lbessard@163: else: lbessard@163: self.TabsOpened.DeleteAllPages() laurent@390: self.RefreshTabCtrlEvent() laurent@390: laurent@390: ## Function that fix difference in setting picture on tab between laurent@390: # wx.Notebook and wx.aui.AUINotebook. laurent@390: # @param idx Tab index. laurent@390: # @param bitmap wx.Bitmap to define on tab. laurent@390: # @return True if operation succeeded lbessard@203: def SetPageBitmap(self, idx, bitmap): lbessard@292: if USE_AUI: lbessard@235: return self.TabsOpened.SetPageBitmap(idx, bitmap) lbessard@203: else: lbessard@203: return self.TabsOpened.SetPageImage(idx, bitmap) lbessard@203: laurent@390: #------------------------------------------------------------------------------- laurent@390: # Dialog Message Functions laurent@390: #------------------------------------------------------------------------------- laurent@390: laurent@390: ## Function displaying an Error dialog in PLCOpenEditor. laurent@390: # @param message The message to display. laurent@390: def ShowErrorMessage(self, message): laurent@391: dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) laurent@390: dialog.ShowModal() laurent@390: dialog.Destroy() laurent@390: laurent@390: ## Function displaying an Error dialog in PLCOpenEditor. laurent@390: # @return False if closing cancelled. laurent@450: def CheckSaveBeforeClosing(self, title=_("Close Project")): laurent@390: if not self.Controler.ProjectIsSaved(): laurent@450: dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), title, wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) lbessard@56: answer = dialog.ShowModal() lbessard@56: dialog.Destroy() lbessard@64: if answer == wx.ID_YES: lbessard@56: self.SaveProject() laurent@390: elif answer == wx.ID_CANCEL: laurent@390: return False laurent@390: return True lbessard@163: lbessard@163: #------------------------------------------------------------------------------- lbessard@163: # File Menu Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: lbessard@163: def RefreshFileMenu(self): laurent@407: pass etisserant@0: laurent@411: def ResetView(self): laurent@411: self.DeleteAllPages() laurent@411: self.VariablePanelIndexer.RemoveAllPanels() laurent@411: self.TypesTree.DeleteAllItems() laurent@411: self.InstancesTree.DeleteAllItems() laurent@411: self.LibraryTree.DeleteAllItems() laurent@411: self.Controler = None etisserant@0: etisserant@0: def OnCloseTabMenu(self, event): lbessard@235: selected = self.TabsOpened.GetSelection() etisserant@0: if selected >= 0: laurent@407: window = self.TabsOpened.GetPage(selected) laurent@407: if not window.IsDebugging(): laurent@407: self.VariablePanelIndexer.RemoveVariablePanel(window.GetTagName()) lbessard@294: self.TabsOpened.DeletePage(selected) lbessard@235: if self.TabsOpened.GetPageCount() > 0: lbessard@235: new_index = min(selected, self.TabsOpened.GetPageCount() - 1) lbessard@235: self.TabsOpened.SetSelection(new_index) laurent@407: window = self.TabsOpened.GetPage(new_index) laurent@407: if not window.IsDebugging(): laurent@407: self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName()) laurent@478: # Refresh all window elements that have changed laurent@478: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU) laurent@478: self.RefreshTabCtrlEvent() etisserant@0: lbessard@213: def OnPageSetupMenu(self, event): lbessard@213: dialog = wx.PageSetupDialog(self, self.PageSetupData) lbessard@213: if dialog.ShowModal() == wx.ID_OK: lbessard@213: self.PageSetupData = wx.PageSetupDialogData(dialog.GetPageSetupData()) lbessard@213: self.PrintData = wx.PrintData(self.PageSetupData.GetPrintData()) lbessard@213: dialog.Destroy() lbessard@213: lbessard@213: def OnPreviewMenu(self, event): lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@213: if selected != -1: laurent@407: window = self.TabsOpened.GetPage(selected) lbessard@213: data = wx.PrintDialogData(self.PrintData) laurent@407: properties = self.Controler.GetProjectProperties(window.IsDebugging()) lbessard@213: page_size = map(int, properties["pageSize"]) lbessard@213: margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight()) laurent@407: printout = GraphicPrintout(window, page_size, margins, True) laurent@407: printout2 = GraphicPrintout(window, page_size, margins, True) lbessard@213: preview = wx.PrintPreview(printout, printout2, data) lbessard@213: lbessard@213: if preview.Ok(): laurent@559: preview_frame = wx.PreviewFrame(preview, self, _("Print preview"), style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT) lbessard@213: lbessard@213: preview_frame.Initialize() lbessard@213: laurent@559: preview_canvas = preview.GetCanvas() laurent@559: preview_canvas.SetMinSize(preview_canvas.GetVirtualSize()) laurent@559: preview_frame.Fit() laurent@559: lbessard@213: preview_frame.Show(True) lbessard@213: lbessard@213: def OnPrintMenu(self, event): lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@213: if selected != -1: laurent@407: window = self.TabsOpened.GetPage(selected) lbessard@213: dialog_data = wx.PrintDialogData(self.PrintData) lbessard@213: dialog_data.SetToPage(1) laurent@407: properties = self.Controler.GetProjectProperties(window.IsDebugging()) lbessard@213: page_size = map(int, properties["pageSize"]) lbessard@213: margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight()) lbessard@213: printer = wx.Printer(dialog_data) laurent@407: printout = GraphicPrintout(window, page_size, margins) lbessard@213: laurent@559: if not printer.Print(self, printout, True) and printer.GetLastError() != wx.PRINTER_CANCELLED: laurent@391: self.ShowErrorMessage(_("There was a problem printing.\nPerhaps your current printer is not set correctly?")) lbessard@213: printout.Destroy() lbessard@213: lbessard@27: def OnPropertiesMenu(self, event): lbessard@27: self.ShowProperties() lbessard@27: etisserant@0: def OnQuitMenu(self, event): etisserant@0: self.Close() etisserant@0: lbessard@163: #------------------------------------------------------------------------------- lbessard@332: # Edit Menu Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: lbessard@163: def RefreshEditMenu(self): laurent@407: if self.Controler is not None: laurent@407: undo, redo = self.Controler.GetBufferState() laurent@407: self.EditMenu.Enable(wx.ID_UNDO, undo) laurent@407: self.EditMenu.Enable(wx.ID_REDO, redo) laurent@562: #self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, True) laurent@562: #self.EditMenu.Check(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, laurent@562: # self.Controler.IsProjectBufferEnabled()) laurent@566: self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True) laurent@407: self.EditMenu.Enable(wx.ID_ADD, True) laurent@407: self.EditMenu.Enable(wx.ID_DELETE, True) laurent@407: if self.TabsOpened.GetPageCount() > 0: laurent@407: self.EditMenu.Enable(wx.ID_CUT, True) laurent@407: self.EditMenu.Enable(wx.ID_COPY, True) laurent@407: if self.GetCopyBuffer() is not None: laurent@407: self.EditMenu.Enable(wx.ID_PASTE, True) lbessard@331: else: lbessard@331: self.EditMenu.Enable(wx.ID_PASTE, False) laurent@407: self.EditMenu.Enable(wx.ID_SELECTALL, True) lbessard@332: else: lbessard@331: self.EditMenu.Enable(wx.ID_CUT, False) lbessard@331: self.EditMenu.Enable(wx.ID_COPY, False) lbessard@331: self.EditMenu.Enable(wx.ID_PASTE, False) lbessard@331: self.EditMenu.Enable(wx.ID_SELECTALL, False) laurent@407: else: laurent@407: self.EditMenu.Enable(wx.ID_UNDO, False) laurent@407: self.EditMenu.Enable(wx.ID_REDO, False) laurent@562: #self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, False) laurent@407: self.EditMenu.Enable(wx.ID_CUT, False) laurent@407: self.EditMenu.Enable(wx.ID_COPY, False) laurent@407: self.EditMenu.Enable(wx.ID_PASTE, False) laurent@407: self.EditMenu.Enable(wx.ID_SELECTALL, False) laurent@566: self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False) laurent@407: self.EditMenu.Enable(wx.ID_ADD, False) laurent@407: self.EditMenu.Enable(wx.ID_DELETE, False) lbessard@331: laurent@390: def CloseTabsWithoutModel(self): lbessard@235: idxs = range(self.TabsOpened.GetPageCount()) lbessard@163: idxs.reverse() lbessard@163: for idx in idxs: laurent@407: window = self.TabsOpened.GetPage(idx) laurent@407: if not window.IsDebugging(): laurent@407: tagname = window.GetTagName() laurent@407: if self.Controler.GetEditedElement(tagname) is None: laurent@407: self.VariablePanelIndexer.RemoveVariablePanel(tagname) laurent@407: self.TabsOpened.DeletePage(idx) laurent@407: laurent@390: def OnUndoMenu(self, event): laurent@390: self.Controler.LoadPrevious() laurent@390: self.CloseTabsWithoutModel() laurent@390: self.RefreshEditor() laurent@488: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, laurent@390: SCALING) lbessard@163: lbessard@163: def OnRedoMenu(self, event): lbessard@163: self.Controler.LoadNext() laurent@390: self.CloseTabsWithoutModel() laurent@390: self.RefreshEditor() laurent@488: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, laurent@390: SCALING) laurent@390: greg@350: def OnEnableUndoRedoMenu(self, event): greg@350: self.Controler.EnableProjectBuffer(event.IsChecked()) greg@350: self.RefreshEditMenu() greg@350: laurent@390: OnCutMenu = GetShortcutKeyCallbackFunction("Cut") laurent@390: OnCopyMenu = GetShortcutKeyCallbackFunction("Copy") laurent@390: OnPasteMenu = GetShortcutKeyCallbackFunction("Paste") laurent@390: lbessard@331: def OnSelectAllMenu(self, event): lbessard@341: control = self.FindFocus() lbessard@341: if isinstance(control, (Viewer, TextViewer)): lbessard@341: control.SelectAll() lbessard@341: elif isinstance(control, wx.TextCtrl): lbessard@341: control.SetSelection(0, control.GetLastPosition()) lbessard@341: elif isinstance(control, wx.ComboBox): lbessard@341: control.SetMark(0, control.GetLastPosition() + 1) lbessard@331: laurent@390: DeleteFunctions = { laurent@390: ITEM_DATATYPE: GetDeleteElementFunction(PLCControler.ProjectRemoveDataType, check_function=PLCControler.DataTypeIsUsed), laurent@390: ITEM_POU: GetDeleteElementFunction(PLCControler.ProjectRemovePou, check_function=PLCControler.PouIsUsed), laurent@390: ITEM_TRANSITION: GetDeleteElementFunction(PLCControler.ProjectRemovePouTransition, ITEM_POU), laurent@390: ITEM_ACTION: GetDeleteElementFunction(PLCControler.ProjectRemovePouAction, ITEM_POU), laurent@390: ITEM_CONFIGURATION: GetDeleteElementFunction(PLCControler.ProjectRemoveConfiguration), laurent@390: ITEM_RESOURCE: GetDeleteElementFunction(PLCControler.ProjectRemoveConfigurationResource, ITEM_CONFIGURATION) laurent@390: } laurent@390: lbessard@163: def OnDeleteMenu(self, event): lbessard@163: window = self.FindFocus() laurent@390: if window == self.TypesTree or window is None: lbessard@235: selected = self.TypesTree.GetSelection() lbessard@163: if selected.IsOk(): lbessard@235: type = self.TypesTree.GetPyData(selected) laurent@390: function = self.DeleteFunctions.get(type, None) laurent@390: if function is not None: laurent@390: function(self, selected) laurent@390: self.CloseTabsWithoutModel() laurent@498: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, TYPESTREE, laurent@390: INSTANCESTREE, LIBRARYTREE) lbessard@163: elif isinstance(window, (Viewer, TextViewer)): lbessard@163: event = wx.KeyEvent(wx.EVT_CHAR._getEvtType()) lbessard@163: event.m_keyCode = wx.WXK_DELETE lbessard@163: window.ProcessEvent(event) lbessard@163: laurent@566: def OnSearchInProjectMenu(self, event): laurent@566: dialog = SearchInProjectDialog(self) laurent@566: if dialog.ShowModal() == wx.ID_OK: laurent@566: criteria = dialog.GetCriteria() laurent@566: result = self.Controler.SearchInProject(criteria) laurent@566: self.ClearSearchResults() laurent@566: self.SearchResultPanel.SetSearchResults(criteria, result) laurent@566: self.BottomNoteBook.SetSelection(self.BottomNoteBook.GetPageIndex(self.SearchResultPanel)) laurent@566: lbessard@163: #------------------------------------------------------------------------------- lbessard@332: # Display Menu Functions lbessard@332: #------------------------------------------------------------------------------- lbessard@332: lbessard@332: def RefreshDisplayMenu(self): laurent@407: if self.Controler is not None: lbessard@332: if self.TabsOpened.GetPageCount() > 0: lbessard@332: self.DisplayMenu.Enable(wx.ID_REFRESH, True) lbessard@332: selected = self.TabsOpened.GetSelection() lbessard@332: if selected != -1: lbessard@332: window = self.TabsOpened.GetPage(selected) lbessard@332: if isinstance(window, Viewer): lbessard@332: self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, True) lbessard@332: zoommenu = self.DisplayMenu.FindItemById(wx.ID_ZOOM_FIT).GetSubMenu() lbessard@332: zoomitem = zoommenu.FindItemByPosition(window.GetScale()) lbessard@332: zoomitem.Check(True) lbessard@332: else: lbessard@332: self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) lbessard@332: else: lbessard@332: self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) lbessard@332: else: lbessard@332: self.DisplayMenu.Enable(wx.ID_REFRESH, False) lbessard@332: self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) laurent@407: if self.EnableDebug: greg@352: self.DisplayMenu.Enable(wx.ID_CLEAR, True) lbessard@332: else: lbessard@332: self.DisplayMenu.Enable(wx.ID_REFRESH, False) laurent@407: if self.EnableDebug: greg@352: self.DisplayMenu.Enable(wx.ID_CLEAR, False) lbessard@332: self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) lbessard@332: lbessard@332: def OnRefreshMenu(self, event): laurent@407: self.RefreshEditor() lbessard@332: lbessard@332: def OnClearErrorsMenu(self, event): lbessard@332: self.ClearErrors() lbessard@332: lbessard@332: def GenerateZoomFunction(self, idx): lbessard@332: def ZoomFunction(event): lbessard@332: selected = self.TabsOpened.GetSelection() lbessard@332: if selected != -1: lbessard@332: window = self.TabsOpened.GetPage(selected) lbessard@332: window.SetScale(idx) greg@361: window.RefreshVisibleElements() greg@361: window.RefreshScrollBars() lbessard@332: event.Skip() lbessard@332: return ZoomFunction lbessard@332: lbessard@332: lbessard@332: #------------------------------------------------------------------------------- lbessard@163: # Project Editor Panels Management Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: laurent@390: def OnPageDragged(self, event): laurent@390: wx.CallAfter(self.RefreshTabCtrlEvent) laurent@390: event.Skip() laurent@390: laurent@390: def RefreshTabCtrlEvent(self): laurent@390: if USE_AUI: laurent@390: auitabctrl = [] laurent@390: for child in self.TabsOpened.GetChildren(): laurent@390: if isinstance(child, wx.aui.AuiTabCtrl): laurent@390: auitabctrl.append(child) laurent@390: if child not in self.AuiTabCtrl: laurent@390: child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child)) laurent@390: self.AuiTabCtrl = auitabctrl laurent@390: if self.TabsOpened.GetPageCount() == 0: laurent@390: pane = self.AUIManager.GetPane(self.TabsOpened) laurent@390: if pane.IsMaximized(): laurent@390: self.AUIManager.RestorePane(pane) laurent@390: self.AUIManager.Update() laurent@390: etisserant@0: def OnPouSelectedChanged(self, event): lbessard@235: old_selected = self.TabsOpened.GetSelection() lbessard@235: if old_selected >= 0: laurent@407: window = self.TabsOpened.GetPage(old_selected) laurent@407: if not window.IsDebugging(): laurent@407: window.ResetBuffer() lbessard@235: selected = event.GetSelection() lbessard@235: if selected >= 0: lbessard@235: window = self.TabsOpened.GetPage(selected) laurent@407: if not window.IsDebugging(): laurent@538: wx.CallAfter(self.SelectTypesTreeItem, window.GetTagName()) lbessard@249: else: laurent@538: wx.CallAfter(self.SelectInstancesTreeItem, self.InstancesTree.GetRootItem(), window.GetInstancePath()) lbessard@235: window.RefreshView() laurent@407: if not window.IsDebugging(): lbessard@249: self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName()) laurent@390: self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, TOOLBAR) etisserant@0: event.Skip() etisserant@0: lbessard@163: def RefreshEditor(self, variablepanel = True): lbessard@235: selected = self.TabsOpened.GetSelection() laurent@489: if USE_AUI: laurent@489: for child in self.TabsOpened.GetChildren(): laurent@489: if isinstance(child, wx.aui.AuiTabCtrl): laurent@568: active_page = child.GetActivePage() laurent@568: if active_page >= 0: laurent@568: window = child.GetWindowFromIdx(child.GetActivePage()) laurent@568: window.RefreshView() laurent@568: if not window.IsDebugging() and self.TabsOpened.GetPageIndex(window) == selected and variablepanel: laurent@568: self.RefreshVariablePanel(window.GetTagName()) laurent@489: elif selected >= 0: laurent@489: window = self.TabsOpened.GetPage(idx) lbessard@163: window.RefreshView() laurent@490: if not window.IsDebugging() and variablepanel: lbessard@163: self.RefreshVariablePanel(window.GetTagName()) lbessard@163: lbessard@163: def RefreshVariablePanel(self, tagname): lbessard@163: self.VariablePanelIndexer.RefreshVariablePanel(tagname) lbessard@163: lbessard@163: def RefreshEditorNames(self, old_tagname, new_tagname): lbessard@235: for i in xrange(self.TabsOpened.GetPageCount()): lbessard@235: editor = self.TabsOpened.GetPage(i) lbessard@163: if editor.GetTagName() == old_tagname: lbessard@163: editor.SetTagName(new_tagname) lbessard@163: self.VariablePanelIndexer.UpdateVariablePanelTagName(old_tagname, new_tagname) lbessard@163: lbessard@163: def IsOpened(self, tagname): lbessard@235: for idx in xrange(self.TabsOpened.GetPageCount()): lbessard@235: if self.TabsOpened.GetPage(idx).IsViewing(tagname): lbessard@163: return idx lbessard@163: return None lbessard@163: lbessard@163: def RefreshPageTitles(self): lbessard@235: for idx in xrange(self.TabsOpened.GetPageCount()): lbessard@235: window = self.TabsOpened.GetPage(idx) laurent@407: debug = window.IsDebugging() lbessard@163: words = window.GetTagName().split("::") lbessard@203: if words[0] == "P": laurent@407: pou_type = self.Controler.GetEditedElementType(window.GetTagName(), debug)[1].upper() laurent@407: pou_body_type = self.Controler.GetEditedElementBodyType(window.GetTagName(), debug) lbessard@292: self.SetPageBitmap(idx, self.GenerateBitmap(pou_type, pou_body_type)) lbessard@203: elif words[0] == "T": laurent@407: pou_body_type = self.Controler.GetEditedElementBodyType(window.GetTagName(), debug) lbessard@292: self.SetPageBitmap(idx, self.GenerateBitmap("TRANSITION", pou_body_type)) lbessard@203: elif words[0] == "A": laurent@407: pou_body_type = self.Controler.GetEditedElementBodyType(window.GetTagName(), debug) lbessard@292: self.SetPageBitmap(idx, self.GenerateBitmap("ACTION", pou_body_type)) lbessard@203: elif words[0] == "C": lbessard@292: self.SetPageBitmap(idx, self.GenerateBitmap("CONFIGURATION")) lbessard@203: elif words[0] == "R": lbessard@292: self.SetPageBitmap(idx, self.GenerateBitmap("RESOURCE")) lbessard@203: elif words[0] == "D": lbessard@292: self.SetPageBitmap(idx, self.GenerateBitmap("DATATYPE")) laurent@407: if debug: laurent@407: text = window.GetInstancePath() laurent@407: if len(text) > 15: laurent@407: text = "..." + text[-12:] laurent@407: self.TabsOpened.SetPageText(idx, text) lbessard@249: else: lbessard@249: self.TabsOpened.SetPageText(idx, "-".join(words[1:])) lbessard@163: lbessard@335: def GetTabsOpenedDClickFunction(self, tabctrl): lbessard@331: def OnTabsOpenedDClick(event): lbessard@335: pos = event.GetPosition() lbessard@335: if tabctrl.TabHitTest(pos.x, pos.y, None): lbessard@335: pane = self.AUIManager.GetPane(self.TabsOpened) lbessard@335: if pane.IsMaximized(): lbessard@335: self.AUIManager.RestorePane(pane) lbessard@335: else: lbessard@335: self.AUIManager.MaximizePane(pane) lbessard@335: self.AUIManager.Update() lbessard@331: event.Skip() lbessard@331: return OnTabsOpenedDClick lbessard@163: lbessard@163: #------------------------------------------------------------------------------- lbessard@239: # Types Tree Management Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: lbessard@235: def RefreshTypesTree(self): laurent@407: infos = self.Controler.GetProjectInfos() lbessard@235: root = self.TypesTree.GetRootItem() lbessard@163: if not root.IsOk(): lbessard@235: root = self.TypesTree.AddRoot(infos["name"]) lbessard@235: self.GenerateTypesTreeBranch(root, infos) lbessard@239: self.TypesTree.Expand(root) lbessard@235: laurent@390: def ResetSelectedItem(self): laurent@390: self.SelectedItem = None laurent@390: lbessard@235: def GenerateTypesTreeBranch(self, root, infos, topology=False): lbessard@163: to_delete = [] laurent@391: item_name = infos["name"] laurent@512: if infos["type"] in ITEMS_UNEDITABLE: laurent@512: item_name = _(item_name) laurent@512: self.TypesTree.SetItemText(root, item_name) lbessard@235: self.TypesTree.SetPyData(root, infos["type"]) laurent@566: highlight_colours = self.Highlights.get(infos.get("tagname", None), (wx.WHITE, wx.BLACK)) laurent@566: self.TypesTree.SetItemBackgroundColour(root, highlight_colours[0]) laurent@566: self.TypesTree.SetItemTextColour(root, highlight_colours[1]) lbessard@235: if infos["type"] == ITEM_POU: laurent@407: self.TypesTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])]) laurent@390: else: laurent@390: self.TypesTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) etisserant@184: lbessard@163: if wx.VERSION >= (2, 6, 0): lbessard@235: item, root_cookie = self.TypesTree.GetFirstChild(root) lbessard@235: else: lbessard@235: item, root_cookie = self.TypesTree.GetFirstChild(root, 0) lbessard@163: for values in infos["values"]: lbessard@163: if not item.IsOk(): lbessard@235: item = self.TypesTree.AppendItem(root, "") lbessard@163: if wx.Platform != '__WXMSW__': lbessard@235: item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) lbessard@235: self.GenerateTypesTreeBranch(item, values) lbessard@235: item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) lbessard@163: while item.IsOk(): lbessard@163: to_delete.append(item) lbessard@235: item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) lbessard@163: for item in to_delete: lbessard@235: self.TypesTree.Delete(item) lbessard@235: lbessard@235: def SelectTypesTreeItem(self, tagname): lbessard@249: if self.TypesTree is not None: lbessard@235: root = self.TypesTree.GetRootItem() lbessard@231: words = tagname.split("::") lbessard@231: if words[0] == "D": lbessard@235: return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_DATATYPE)]) lbessard@231: elif words[0] == "P": lbessard@235: return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU)]) lbessard@231: elif words[0] == "T": lbessard@235: return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)]) lbessard@231: elif words[0] == "A": lbessard@235: return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)]) lbessard@231: elif words[0] == "C": lbessard@235: return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)]) lbessard@231: elif words[0] == "R": lbessard@235: return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)]) lbessard@231: return False lbessard@231: lbessard@235: def RecursiveTypesTreeItemSelection(self, root, items): lbessard@122: found = False lbessard@249: if self.TypesTree is not None: lbessard@122: if wx.VERSION >= (2, 6, 0): lbessard@235: item, root_cookie = self.TypesTree.GetFirstChild(root) lbessard@122: else: lbessard@235: item, root_cookie = self.TypesTree.GetFirstChild(root, 0) lbessard@122: while item.IsOk() and not found: lbessard@235: if (self.TypesTree.GetItemText(item), self.TypesTree.GetPyData(item)) == items[0]: lbessard@122: if len(items) == 1: lbessard@122: self.SelectedItem = item lbessard@235: self.TypesTree.SelectItem(item) lbessard@122: wx.CallAfter(self.ResetSelectedItem) lbessard@122: return True lbessard@122: else: lbessard@235: found = self.RecursiveTypesTreeItemSelection(item, items[1:]) lbessard@122: else: lbessard@235: found = self.RecursiveTypesTreeItemSelection(item, items) lbessard@235: item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) lbessard@122: return found lbessard@122: lbessard@235: def OnTypesTreeBeginDrag(self, event): lbessard@131: if wx.Platform == '__WXMSW__': lbessard@134: self.SelectedItem = event.GetItem() lbessard@235: if self.SelectedItem is not None and self.TypesTree.GetPyData(self.SelectedItem) == ITEM_POU: lbessard@235: block_name = self.TypesTree.GetItemText(self.SelectedItem) laurent@407: block_type = self.Controler.GetPouType(block_name) lbessard@53: if block_type != "program": lbessard@64: data = wx.TextDataObject(str((block_name, block_type, ""))) lbessard@235: dragSource = wx.DropSource(self.TypesTree) lbessard@53: dragSource.SetData(data) lbessard@53: dragSource.DoDragDrop() lbessard@122: self.ResetSelectedItem() lbessard@7: lbessard@235: def OnTypesTreeItemBeginEdit(self, event): lbessard@163: selected = event.GetItem() lbessard@235: if self.TypesTree.GetPyData(selected) in ITEMS_UNEDITABLE: lbessard@163: event.Veto() lbessard@163: else: lbessard@163: event.Skip() lbessard@107: lbessard@235: def OnTypesTreeItemEndEdit(self, event): lbessard@6: message = None lbessard@6: abort = False etisserant@0: new_name = event.GetLabel() etisserant@0: if new_name != "": lbessard@6: if not TestIdentifier(new_name): laurent@391: message = _("\"%s\" is not a valid identifier!")%new_name lbessard@6: elif new_name.upper() in IEC_KEYWORDS: laurent@391: message = _("\"%s\" is a keyword. It can't be used!")%new_name lbessard@6: else: etisserant@0: item = event.GetItem() lbessard@235: old_name = self.TypesTree.GetItemText(item) lbessard@235: itemtype = self.TypesTree.GetPyData(item) etisserant@0: if itemtype == ITEM_PROJECT: lbessard@56: self.Controler.SetProjectProperties(name = new_name) lbessard@125: elif itemtype == ITEM_DATATYPE: laurent@407: if new_name.upper() in [name.upper() for name in self.Controler.GetProjectDataTypeNames() if name != old_name]: laurent@391: message = _("\"%s\" data type already exists!")%new_name lbessard@125: abort = True lbessard@125: if not abort: lbessard@125: self.Controler.ChangeDataTypeName(old_name, new_name) lbessard@145: self.RefreshEditorNames(self.Controler.ComputeDataTypeName(old_name), lbessard@145: self.Controler.ComputeDataTypeName(new_name)) lbessard@125: self.RefreshPageTitles() etisserant@0: elif itemtype == ITEM_POU: laurent@407: if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]: laurent@391: message = _("\"%s\" pou already exists!")%new_name lbessard@6: abort = True laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: b@427: 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) lbessard@64: if messageDialog.ShowModal() == wx.ID_NO: lbessard@6: abort = True lbessard@6: messageDialog.Destroy() lbessard@6: if not abort: lbessard@6: self.Controler.ChangePouName(old_name, new_name) lbessard@145: self.RefreshEditorNames(self.Controler.ComputePouName(old_name), lbessard@145: self.Controler.ComputePouName(new_name)) greg@357: self.RefreshLibraryTree() lbessard@121: self.RefreshPageTitles() etisserant@0: elif itemtype == ITEM_TRANSITION: laurent@390: pou_name = GetParentName(self.TypesTree, item, ITEM_POU) laurent@407: if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: b@427: message = _("A POU named \"%s\" already exists!")%new_name laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]: laurent@391: message = _("A variable with \"%s\" as name already exists in this pou!")%new_name lbessard@6: else: lbessard@6: self.Controler.ChangePouTransitionName(pou_name, old_name, new_name) lbessard@145: self.RefreshEditorNames(self.Controler.ComputePouTransitionName(pou_name, old_name), lbessard@145: self.Controler.ComputePouTransitionName(pou_name, new_name)) lbessard@121: self.RefreshPageTitles() etisserant@0: elif itemtype == ITEM_ACTION: laurent@390: pou_name = GetParentName(self.TypesTree, item, ITEM_POU) laurent@407: if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: b@427: message = _("A POU named \"%s\" already exists!")%new_name laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]: laurent@391: message = _("A variable with \"%s\" as name already exists in this pou!")%new_name lbessard@6: else: lbessard@6: self.Controler.ChangePouActionName(pou_name, old_name, new_name) lbessard@145: self.RefreshEditorNames(self.Controler.ComputePouActionName(pou_name, old_name), lbessard@145: self.Controler.ComputePouActionName(pou_name, new_name)) lbessard@121: self.RefreshPageTitles() lbessard@107: elif itemtype == ITEM_CONFIGURATION: laurent@407: if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]: laurent@391: message = _("\"%s\" config already exists!")%new_name lbessard@107: abort = True laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: b@427: 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) lbessard@107: if messageDialog.ShowModal() == wx.ID_NO: lbessard@107: abort = True lbessard@107: messageDialog.Destroy() laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: b@427: 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) lbessard@107: if messageDialog.ShowModal() == wx.ID_NO: lbessard@107: abort = True lbessard@107: messageDialog.Destroy() lbessard@107: if not abort: lbessard@107: self.Controler.ChangeConfigurationName(old_name, new_name) lbessard@145: self.RefreshEditorNames(self.Controler.ComputeConfigurationName(old_name), lbessard@145: self.Controler.ComputeConfigurationName(new_name)) lbessard@121: self.RefreshPageTitles() lbessard@107: elif itemtype == ITEM_RESOURCE: laurent@390: config_name = GetParentName(self.TypesTree, item, ITEM_CONFIGURATION) laurent@407: if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]: laurent@391: message = _("\"%s\" config already exists!")%new_name lbessard@107: abort = True laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: b@427: 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) lbessard@107: if messageDialog.ShowModal() == wx.ID_NO: lbessard@107: abort = True lbessard@107: messageDialog.Destroy() laurent@407: elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: b@427: 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) lbessard@107: if messageDialog.ShowModal() == wx.ID_NO: lbessard@107: abort = True lbessard@107: messageDialog.Destroy() lbessard@107: if not abort: lbessard@107: self.Controler.ChangeConfigurationResourceName(config_name, old_name, new_name) lbessard@145: self.RefreshEditorNames(self.Controler.ComputeConfigurationResourceName(config_name, old_name), lbessard@145: self.Controler.ComputeConfigurationResourceName(config_name, new_name)) lbessard@121: self.RefreshPageTitles() lbessard@6: if message or abort: lbessard@6: if message: laurent@390: self.ShowErrorMessage(message) etisserant@0: item = event.GetItem() lbessard@235: wx.CallAfter(self.TypesTree.EditLabel, item) etisserant@0: event.Veto() lbessard@6: else: lbessard@235: wx.CallAfter(self.RefreshTypesTree) greg@350: self.RefreshEditor() laurent@390: self._Refresh(TITLE, FILEMENU, EDITMENU) lbessard@6: event.Skip() etisserant@0: lbessard@235: def OnTypesTreeItemActivated(self, event): etisserant@0: selected = event.GetItem() lbessard@235: name = self.TypesTree.GetItemText(selected) lbessard@235: data = self.TypesTree.GetPyData(selected) laurent@391: if UNEDITABLE_NAMES_DICT.get(name, name) == "Properties": lbessard@27: self.ShowProperties() lbessard@125: if data == ITEM_DATATYPE: lbessard@125: self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name)) lbessard@125: elif data == ITEM_POU: lbessard@121: self.EditProjectElement(data, self.Controler.ComputePouName(name)) lbessard@121: elif data == ITEM_CONFIGURATION: lbessard@121: self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name)) lbessard@102: elif data == ITEM_RESOURCE: laurent@390: config_name = GetParentName(self.TypesTree, selected, ITEM_CONFIGURATION) lbessard@121: self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name)) lbessard@102: elif data in [ITEM_TRANSITION, ITEM_ACTION]: laurent@390: pou_name = GetParentName(self.TypesTree, selected, ITEM_POU) lbessard@121: if data == ITEM_TRANSITION: lbessard@121: tagname = self.Controler.ComputePouTransitionName(pou_name, name) lbessard@121: elif data == ITEM_ACTION: lbessard@121: tagname = self.Controler.ComputePouActionName(pou_name, name) lbessard@121: self.EditProjectElement(data, tagname) lbessard@129: event.Skip() lbessard@102: lbessard@235: def TypesTreeItemSelect(self, select_item): lbessard@235: name = self.TypesTree.GetItemText(select_item) lbessard@235: data = self.TypesTree.GetPyData(select_item) lbessard@131: if data == ITEM_DATATYPE: lbessard@131: self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name), True) lbessard@131: elif data == ITEM_POU: lbessard@131: self.EditProjectElement(data, self.Controler.ComputePouName(name), True) lbessard@131: elif data == ITEM_CONFIGURATION: lbessard@131: self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name), True) lbessard@131: elif data == ITEM_RESOURCE: laurent@390: config_name = GetParentName(self.TypesTree, select_item, ITEM_CONFIGURATION) lbessard@131: self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name), True) lbessard@131: elif data in [ITEM_TRANSITION, ITEM_ACTION]: laurent@390: pou_name = GetParentName(self.TypesTree, select_item, ITEM_POU) lbessard@131: if data == ITEM_TRANSITION: lbessard@131: tagname = self.Controler.ComputePouTransitionName(pou_name, name) lbessard@131: elif data == ITEM_ACTION: lbessard@131: tagname = self.Controler.ComputePouActionName(pou_name, name) lbessard@131: self.EditProjectElement(data, tagname, True) lbessard@131: lbessard@235: def OnTypesTreeLeftUp(self, event): lbessard@122: if self.SelectedItem is not None: lbessard@235: self.TypesTree.SelectItem(self.SelectedItem) lbessard@235: self.TypesTreeItemSelect(self.SelectedItem) lbessard@122: wx.CallAfter(self.ResetSelectedItem) lbessard@122: event.Skip() lbessard@122: lbessard@235: def OnTypesTreeItemSelected(self, event): lbessard@235: self.TypesTreeItemSelect(event.GetItem()) lbessard@235: event.Skip() lbessard@235: lbessard@235: def OnTypesTreeItemChanging(self, event): lbessard@235: if self.TypesTree.GetPyData(event.GetItem()) not in ITEMS_UNEDITABLE and self.SelectedItem is None: lbessard@122: self.SelectedItem = event.GetItem() lbessard@122: event.Veto() lbessard@122: else: lbessard@122: event.Skip() lbessard@121: lbessard@121: def EditProjectElement(self, elementtype, tagname, onlyopened = False): lbessard@121: openedidx = self.IsOpened(tagname) lbessard@121: if openedidx is not None: lbessard@235: old_selected = self.TabsOpened.GetSelection() lbessard@121: if old_selected != openedidx: lbessard@121: if old_selected >= 0: lbessard@235: self.TabsOpened.GetPage(old_selected).ResetBuffer() lbessard@235: self.TabsOpened.SetSelection(openedidx) lbessard@121: self.VariablePanelIndexer.ChangeVariablePanel(tagname) lbessard@121: self.RefreshPageTitles() laurent@390: self._Refresh(FILEMENU, EDITMENU, TOOLBAR) lbessard@121: elif not onlyopened: lbessard@125: if elementtype == ITEM_CONFIGURATION: lbessard@235: new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler) lbessard@337: self.AddPage(new_window, "") lbessard@125: self.VariablePanelIndexer.AddVariablePanel(tagname, "config") lbessard@125: elif elementtype == ITEM_RESOURCE: lbessard@235: new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler) lbessard@337: self.AddPage(new_window, "") lbessard@125: self.VariablePanelIndexer.AddVariablePanel(tagname, "resource") lbessard@125: elif elementtype in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]: laurent@407: bodytype = self.Controler.GetEditedElementBodyType(tagname) lbessard@235: if bodytype == "FBD": lbessard@235: new_window = Viewer(self.TabsOpened, tagname, self, self.Controler) lbessard@235: new_window.RefreshScaling(False) lbessard@235: elif bodytype == "LD": lbessard@235: new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler) lbessard@235: new_window.RefreshScaling(False) lbessard@235: elif bodytype == "SFC": lbessard@235: new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler) lbessard@235: new_window.RefreshScaling(False) lbessard@235: else: lbessard@235: new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler) lbessard@249: new_window.SetTextSyntax(bodytype) lbessard@235: if bodytype == "IL": lbessard@235: new_window.SetKeywords(IL_KEYWORDS) lbessard@235: else: lbessard@235: new_window.SetKeywords(ST_KEYWORDS) lbessard@337: self.AddPage(new_window, "") lbessard@121: words = tagname.split("::") laurent@407: self.VariablePanelIndexer.AddVariablePanel(tagname, self.Controler.GetPouType(words[1])) laurent@451: elif elementtype == ITEM_DATATYPE: laurent@451: new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler) lbessard@337: self.AddPage(new_window, "") lbessard@121: self.VariablePanelIndexer.ChangeVariablePanel(tagname) lbessard@121: openedidx = self.IsOpened(tagname) lbessard@235: old_selected = self.TabsOpened.GetSelection() lbessard@121: if old_selected != openedidx: lbessard@121: if old_selected >= 0: lbessard@235: self.TabsOpened.GetPage(old_selected).ResetBuffer() lbessard@235: for i in xrange(self.TabsOpened.GetPageCount()): lbessard@235: window = self.TabsOpened.GetPage(i) lbessard@121: if window.GetTagName() == tagname: lbessard@235: self.TabsOpened.SetSelection(i) lbessard@129: window.SetFocus() lbessard@121: self.RefreshPageTitles() etisserant@0: lbessard@235: def OnTypesTreeRightUp(self, event): lbessard@159: if wx.Platform == '__WXMSW__': lbessard@163: item = event.GetItem() lbessard@163: else: laurent@444: item, flags = self.TypesTree.HitTest(wx.Point(event.GetX(), event.GetY())) laurent@444: self.TypesTree.SelectItem(item) laurent@445: self.TypesTreeItemSelect(item) lbessard@235: name = self.TypesTree.GetItemText(item) lbessard@235: type = self.TypesTree.GetPyData(item) lbessard@163: if type == ITEM_POU: lbessard@163: menu = wx.Menu(title='') laurent@407: if self.Controler.GetPouBodyType(name) == "SFC": lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition")) lbessard@163: self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), id=new_id) lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action")) lbessard@163: self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id) lbessard@163: menu.AppendSeparator() b@428: lbessard@163: new_id = wx.NewId() laurent@447: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Copy POU")) laurent@447: self.Bind(wx.EVT_MENU, self.OnCopyPou, id=new_id) b@428: laurent@407: pou_type = self.Controler.GetPouType(name) lbessard@275: if pou_type in ["function", "functionBlock"]: lbessard@275: change_menu = wx.Menu(title='') lbessard@275: if pou_type == "function": lbessard@275: new_id = wx.NewId() laurent@391: AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Function Block")) lbessard@275: self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "functionBlock"), id=new_id) lbessard@275: new_id = wx.NewId() laurent@391: AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Program")) lbessard@275: self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "program"), id=new_id) laurent@391: menu.AppendMenu(wx.NewId(), _("Change POU Type To"), change_menu) lbessard@274: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Rename")) lbessard@311: self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, id=new_id) lbessard@311: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) laurent@390: self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: elif type == ITEM_CONFIGURATION: lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource")) lbessard@163: self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(name), id=new_id) lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) laurent@390: self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: elif type in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]: lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) laurent@390: self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id) lbessard@163: self.PopupMenu(menu) etisserant@184: elif type in ITEMS_UNEDITABLE: laurent@391: name = UNEDITABLE_NAMES_DICT[name] lbessard@163: if name == "Data Types": lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add DataType")) lbessard@163: self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: elif name in ["Functions", "Function Blocks", "Programs"]: lbessard@163: menu = wx.Menu(title='') b@428: lbessard@163: new_id = wx.NewId() laurent@447: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add POU")) lbessard@163: self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id) b@428: laurent@447: new_id = wx.NewId() laurent@447: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Paste POU")) laurent@447: self.Bind(wx.EVT_MENU, self.OnPastePou, id=new_id) b@428: if self.GetCopyBuffer() is None: laurent@447: menu.Enable(new_id, False) b@428: lbessard@163: self.PopupMenu(menu) lbessard@163: elif name == "Configurations": lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Configuration")) lbessard@163: self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: elif name == "Transitions": lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition")) lbessard@235: parent = self.TypesTree.GetItemParent(item) lbessard@235: parent_type = self.TypesTree.GetPyData(parent) lbessard@163: while parent_type != ITEM_POU: lbessard@235: parent = self.TypesTree.GetItemParent(parent) lbessard@235: parent_type = self.TypesTree.GetPyData(parent) lbessard@235: self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.TypesTree.GetItemText(parent)), id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: elif name == "Actions": lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action")) lbessard@235: parent = self.TypesTree.GetItemParent(item) lbessard@235: parent_type = self.TypesTree.GetPyData(parent) lbessard@163: while parent_type != ITEM_POU: lbessard@235: parent = self.TypesTree.GetItemParent(parent) lbessard@235: parent_type = self.TypesTree.GetPyData(parent) lbessard@235: self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.TypesTree.GetItemText(parent)), id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: elif name == "Resources": lbessard@163: menu = wx.Menu(title='') lbessard@163: new_id = wx.NewId() laurent@391: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource")) lbessard@235: parent = self.TypesTree.GetItemParent(item) lbessard@235: parent_type = self.TypesTree.GetPyData(parent) lbessard@163: while parent_type != ITEM_CONFIGURATION: lbessard@235: parent = self.TypesTree.GetItemParent(parent) lbessard@235: parent_type = self.TypesTree.GetPyData(parent) lbessard@235: self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(self.TypesTree.GetItemText(parent)), id=new_id) lbessard@163: self.PopupMenu(menu) lbessard@163: event.Skip() lbessard@163: lbessard@163: lbessard@163: #------------------------------------------------------------------------------- lbessard@239: # Instances Tree Management Functions lbessard@235: #------------------------------------------------------------------------------- lbessard@235: lbessard@235: def RefreshInstancesTree(self): laurent@407: infos = self.Controler.GetProjectTopology(self.EnableDebug) lbessard@235: root = self.InstancesTree.GetRootItem() lbessard@235: if not root.IsOk(): lbessard@235: root = self.InstancesTree.AddRoot(infos["name"]) lbessard@235: self.GenerateInstancesTreeBranch(root, infos) lbessard@239: self.InstancesTree.Expand(root) lbessard@235: lbessard@235: def GenerateInstancesTreeBranch(self, root, infos): lbessard@235: to_delete = [] lbessard@235: if infos.get("elmt_type", None) is not None: lbessard@249: self.InstancesTree.SetItemText(root, "%s (%s)"%(infos["name"], infos["elmt_type"])) lbessard@235: else: lbessard@235: self.InstancesTree.SetItemText(root, infos["name"]) lbessard@249: self.InstancesTree.SetPyData(root, (infos["type"], infos.get("tagname", None))) laurent@390: self.InstancesTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) lbessard@235: lbessard@235: if wx.VERSION >= (2, 6, 0): lbessard@235: item, root_cookie = self.InstancesTree.GetFirstChild(root) lbessard@235: else: lbessard@235: item, root_cookie = self.InstancesTree.GetFirstChild(root, 0) lbessard@235: for values in infos["values"]: lbessard@235: if not item.IsOk(): lbessard@235: item = self.InstancesTree.AppendItem(root, "") lbessard@235: if wx.Platform != '__WXMSW__': lbessard@235: item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) lbessard@235: self.GenerateInstancesTreeBranch(item, values) lbessard@235: item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) lbessard@235: while item.IsOk(): lbessard@235: to_delete.append(item) lbessard@235: item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) lbessard@235: for item in to_delete: lbessard@235: self.InstancesTree.Delete(item) laurent@472: if infos["type"] in [ITEM_CONFIGURATION, ITEM_RESOURCE]: laurent@472: self.InstancesTree.Expand(root) lbessard@235: lbessard@249: def OnInstancesTreeBeginDrag(self, event): laurent@407: if self.Controler.DebugAvailable(): laurent@407: selected_item = event.GetItem() laurent@407: selected_infos = self.InstancesTree.GetPyData(selected_item) laurent@407: if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: laurent@407: var_path = self.InstancesTree.GetItemText(selected_item).split(" (")[0] lbessard@301: parent_item = self.InstancesTree.GetItemParent(selected_item) lbessard@301: while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: lbessard@301: parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] lbessard@301: var_path = "%s.%s"%(parent_name, var_path) lbessard@301: parent_item = self.InstancesTree.GetItemParent(parent_item) laurent@407: data = wx.TextDataObject(str((var_path, "debug"))) laurent@407: dragSource = wx.DropSource(self.InstancesTree) laurent@407: dragSource.SetData(data) laurent@407: dragSource.DoDragDrop() laurent@407: event.Skip() laurent@407: else: laurent@407: event.Veto() laurent@407: laurent@407: def OnInstancesTreeItemActivated(self, event): laurent@407: if self.Controler.DebugAvailable(): laurent@407: selected_item = event.GetItem() laurent@407: selected_infos = self.InstancesTree.GetPyData(selected_item) laurent@407: if selected_item is not None and selected_infos[0] in [ITEM_FUNCTIONBLOCK, ITEM_PROGRAM, ITEM_TRANSITION, ITEM_ACTION]: laurent@407: instance_path = self.InstancesTree.GetItemText(selected_item).split(" (")[0] laurent@407: parent_item = self.InstancesTree.GetItemParent(selected_item) laurent@407: while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: laurent@407: parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] laurent@407: instance_path = "%s.%s"%(parent_name, instance_path) laurent@407: parent_item = self.InstancesTree.GetItemParent(parent_item) laurent@407: openedidx = self.IsOpened(instance_path) laurent@407: if openedidx is not None: laurent@407: old_selected = self.TabsOpened.GetSelection() laurent@407: if old_selected != openedidx: laurent@407: if old_selected >= 0: laurent@407: self.TabsOpened.GetPage(old_selected).ResetBuffer() laurent@407: self.TabsOpened.SetSelection(openedidx) laurent@407: elif selected_infos[1] is not None: laurent@407: bodytype = self.Controler.GetEditedElementBodyType(selected_infos[1], True) laurent@407: if bodytype == "FBD": laurent@407: new_window = Viewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) laurent@407: new_window.RefreshScaling(False) laurent@407: elif bodytype == "LD": laurent@407: new_window = LD_Viewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) laurent@407: new_window.RefreshScaling(False) laurent@407: elif bodytype == "SFC": laurent@407: new_window = SFC_Viewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) laurent@407: new_window.RefreshScaling(False) laurent@407: else: laurent@407: new_window = TextViewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) laurent@407: new_window.SetTextSyntax(bodytype) laurent@407: if bodytype == "IL": laurent@407: new_window.SetKeywords(IL_KEYWORDS) laurent@407: else: laurent@407: new_window.SetKeywords(ST_KEYWORDS) laurent@407: self.AddPage(new_window, "") laurent@407: new_window.SetFocus() laurent@407: self.RefreshPageTitles() laurent@407: if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: laurent@407: var_path, var_type = self.InstancesTree.GetItemText(selected_item).split(" (") laurent@407: var_type = var_type.split(")")[0] lbessard@301: laurent@407: if self.Controler.IsOfType(var_type, "ANY_NUM", True) or\ laurent@407: self.Controler.IsOfType(var_type, "ANY_BIT", True): laurent@407: parent_item = self.InstancesTree.GetItemParent(selected_item) laurent@407: while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: laurent@407: parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] laurent@407: var_path = "%s.%s"%(parent_name, var_path) laurent@407: parent_item = self.InstancesTree.GetItemParent(parent_item) laurent@407: laurent@407: self.OpenGraphicViewer(var_path) lbessard@341: event.Skip() lbessard@341: lbessard@341: def OpenGraphicViewer(self, var_path): lbessard@341: new_window = GraphicViewer(self.TabsOpened, self, self.Controler, var_path) lbessard@341: self.AddPage(new_window, "") lbessard@341: new_window.SetFocus() lbessard@341: self.RefreshPageTitles() lbessard@301: lbessard@301: def OnInstancesTreeRightUp(self, event): laurent@407: if self.Controler.DebugAvailable(): laurent@407: if wx.Platform == '__WXMSW__': laurent@407: selected_item = event.GetItem() laurent@407: else: laurent@407: selected_item = self.InstancesTree.GetSelection() laurent@407: selected_infos = self.InstancesTree.GetPyData(selected_item) laurent@407: if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: laurent@407: var_path, var_type = self.InstancesTree.GetItemText(selected_item).split(" (") laurent@407: var_type = var_type.split(")")[0] lbessard@301: laurent@407: if self.Controler.IsOfType(var_type, "ANY_NUM", True) or\ laurent@407: self.Controler.IsOfType(var_type, "ANY_BIT", True): laurent@407: parent_item = self.InstancesTree.GetItemParent(selected_item) laurent@407: while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: laurent@407: parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] laurent@407: var_path = "%s.%s"%(parent_name, var_path) laurent@407: parent_item = self.InstancesTree.GetItemParent(parent_item) laurent@407: laurent@407: menu = wx.Menu(title='') laurent@407: new_id = wx.NewId() laurent@407: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Graphic Panel")) laurent@407: self.Bind(wx.EVT_MENU, self.AddVariableGraphicFunction(var_path), id=new_id) laurent@407: new_id = wx.NewId() laurent@407: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("CSV Log")) laurent@407: self.PopupMenu(menu) lbessard@301: event.Skip() lbessard@301: lbessard@301: def AddVariableGraphicFunction(self, iec_path): lbessard@301: def AddVariableGraphic(event): lbessard@341: self.OpenGraphicViewer(iec_path) lbessard@301: event.Skip() lbessard@301: return AddVariableGraphic lbessard@249: lbessard@249: def SelectInstancesTreeItem(self, root, instancepath): lbessard@249: found = False lbessard@249: if self.InstancesTree is not None: lbessard@262: paths = instancepath.split(".", 1) lbessard@249: if wx.VERSION >= (2, 6, 0): lbessard@249: item, root_cookie = self.InstancesTree.GetFirstChild(root) lbessard@249: else: lbessard@249: item, root_cookie = self.InstancesTree.GetFirstChild(root, 0) lbessard@249: while item.IsOk() and not found: lbessard@262: name = self.InstancesTree.GetItemText(item).split(" (")[0] lbessard@262: if name == paths[0]: lbessard@249: if len(paths) == 1: lbessard@249: self.InstancesTree.SelectItem(item) lbessard@249: return True lbessard@249: else: lbessard@262: found = self.SelectInstancesTreeItem(item, paths[1]) lbessard@262: item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) lbessard@249: return found lbessard@249: lbessard@337: def ResetGraphicViewers(self): lbessard@337: for i in xrange(self.TabsOpened.GetPageCount()): lbessard@337: editor = self.TabsOpened.GetPage(i) lbessard@337: if isinstance(editor, GraphicViewer): lbessard@337: editor.ResetView() lbessard@337: laurent@479: def CloseDebugTabs(self): laurent@479: if self.EnableDebug: laurent@479: idxs = range(self.TabsOpened.GetPageCount()) laurent@479: idxs.reverse() laurent@479: for idx in idxs: laurent@479: window = self.TabsOpened.GetPage(idx) laurent@479: if window.IsDebugging(): laurent@479: self.TabsOpened.DeletePage(idx) laurent@479: self.DebugVariablePanel.ResetGrid() laurent@479: laurent@479: def AddDebugVariable(self, iec_path): laurent@479: if self.EnableDebug: laurent@479: self.DebugVariablePanel.InsertValue(iec_path) laurent@479: lbessard@235: #------------------------------------------------------------------------------- lbessard@239: # Library Tree Management Functions lbessard@239: #------------------------------------------------------------------------------- lbessard@239: lbessard@239: def RefreshLibraryTree(self): laurent@407: to_delete = [] laurent@407: blocktypes = self.Controler.GetBlockTypes() laurent@407: root = self.LibraryTree.GetRootItem() laurent@407: if not root.IsOk(): laurent@407: if wx.Platform == '__WXMSW__': laurent@407: root = self.LibraryTree.AddRoot(_("Block Types")) laurent@407: self.LibraryTree.SetPyData(root, {"type" : CATEGORY}) laurent@407: else: laurent@407: root = self.LibraryTree.AddRoot("") laurent@407: if wx.VERSION >= (2, 6, 0): laurent@407: category_item, root_cookie = self.LibraryTree.GetFirstChild(root) laurent@407: else: laurent@407: category_item, root_cookie = self.LibraryTree.GetFirstChild(root, 0) laurent@407: for category in blocktypes: laurent@407: category_name = category["name"] laurent@407: if not category_item.IsOk(): laurent@407: category_item = self.LibraryTree.AppendItem(root, _(category_name)) laurent@407: if wx.Platform != '__WXMSW__': laurent@407: category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) laurent@407: else: laurent@407: self.LibraryTree.SetItemText(category_item, _(category_name)) laurent@407: self.LibraryTree.SetPyData(category_item, {"type" : CATEGORY}) laurent@407: if wx.VERSION >= (2, 6, 0): laurent@407: blocktype_item, category_cookie = self.LibraryTree.GetFirstChild(category_item) laurent@407: else: laurent@407: blocktype_item, category_cookie = self.LibraryTree.GetFirstChild(category_item, 0) laurent@407: for blocktype in category["list"]: laurent@407: if not blocktype_item.IsOk(): laurent@407: blocktype_item = self.LibraryTree.AppendItem(category_item, blocktype["name"]) laurent@407: if wx.Platform != '__WXMSW__': laurent@407: blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) lbessard@249: else: laurent@407: self.LibraryTree.SetItemText(blocktype_item, blocktype["name"]) laurent@407: self.LibraryTree.SetPyData(blocktype_item, {"type" : BLOCK, "block_type" : blocktype["type"], "inputs" : tuple([type for name, type, modifier in blocktype["inputs"]])}) laurent@407: blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) laurent@407: while blocktype_item.IsOk(): laurent@407: to_delete.append(blocktype_item) laurent@407: blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) laurent@407: category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) laurent@407: while category_item.IsOk(): laurent@407: to_delete.append(category_item) laurent@407: category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) laurent@407: for item in to_delete: laurent@407: self.LibraryTree.Delete(item) laurent@407: if wx.Platform == '__WXMSW__': laurent@407: self.LibraryTree.Expand(root) lbessard@239: lbessard@239: def OnLibraryTreeItemSelected(self, event): lbessard@239: selected = event.GetItem() lbessard@239: pydata = self.LibraryTree.GetPyData(selected) greg@366: if pydata is not None and pydata["type"] != CATEGORY: laurent@407: blocktype = self.Controler.GetBlockType(self.LibraryTree.GetItemText(selected), pydata["inputs"]) lbessard@239: if blocktype: laurent@391: comment = blocktype["comment"] laurent@391: self.LibraryComment.SetValue(_(comment) + blocktype.get("usage", "")) lbessard@239: else: lbessard@239: self.LibraryComment.SetValue("") lbessard@239: else: lbessard@239: self.LibraryComment.SetValue("") lbessard@239: event.Skip() lbessard@239: lbessard@239: def OnLibraryTreeBeginDrag(self, event): lbessard@239: selected = event.GetItem() lbessard@239: pydata = self.LibraryTree.GetPyData(selected) greg@366: if pydata is not None and pydata["type"] == BLOCK: lbessard@239: data = wx.TextDataObject(str((self.LibraryTree.GetItemText(selected), lbessard@239: pydata["block_type"], "", pydata["inputs"]))) lbessard@239: dragSource = wx.DropSource(self.LibraryTree) lbessard@239: dragSource.SetData(data) lbessard@239: dragSource.DoDragDrop() lbessard@239: lbessard@239: #------------------------------------------------------------------------------- lbessard@163: # ToolBar Management Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: lbessard@6: def ResetToolBar(self): laurent@407: for item in self.CurrentToolBar: laurent@407: if wx.VERSION >= (2, 6, 0): laurent@407: self.Unbind(wx.EVT_MENU, id=item) laurent@407: else: laurent@407: self.Disconnect(id=item, eventType=wx.wxEVT_COMMAND_MENU_SELECTED) laurent@407: laurent@407: if USE_AUI: laurent@407: ToolBar = self.Panes["ToolBar"] laurent@407: else: laurent@407: ToolBar = self.ToolBar laurent@407: if ToolBar: laurent@407: ToolBar.DeleteTool(item) laurent@407: ToolBar.Realize() lbessard@292: if USE_AUI: laurent@407: self.AUIManager.GetPane("ToolBar").BestSize(ToolBar.GetBestSize()) laurent@407: self.AUIManager.Update() lbessard@249: lbessard@249: def RefreshToolBar(self): laurent@407: selected = self.TabsOpened.GetSelection() laurent@407: language = None laurent@407: if selected != -1: laurent@407: window = self.TabsOpened.GetPage(selected) laurent@407: if not window.IsDebugging(): laurent@407: language = self.Controler.GetEditedElementBodyType(window.GetTagName()) laurent@407: if language is not None and language != self.CurrentLanguage: laurent@407: self.ResetToolBar() laurent@407: self.CurrentLanguage = language laurent@407: self.CurrentToolBar = [] laurent@407: if USE_AUI: laurent@407: ToolBar = self.Panes["ToolBar"] lbessard@114: else: laurent@407: ToolBar = self.ToolBar laurent@407: if ToolBar: laurent@407: for radio, modes, id, method, picture, help in ToolBarItems[language]: laurent@407: if modes & self.DrawingMode: laurent@407: if radio or self.DrawingMode == FREEDRAWING_MODE: laurent@407: ToolBar.AddRadioTool(id, wx.Bitmap(os.path.join(CWD, "Images", picture)), wx.NullBitmap, help) laurent@407: else: laurent@407: ToolBar.AddSimpleTool(id, wx.Bitmap(os.path.join(CWD, "Images", picture)), help) laurent@407: self.Bind(wx.EVT_TOOL, getattr(self, method), id=id) laurent@407: self.CurrentToolBar.append(id) laurent@407: ToolBar.Realize() lbessard@292: if USE_AUI: laurent@407: self.AUIManager.GetPane("ToolBar").BestSize(ToolBar.GetBestSize()) laurent@407: self.AUIManager.Update() laurent@407: elif not language: laurent@407: self.ResetToolBar() laurent@407: self.CurrentLanguage = language laurent@407: self.ResetCurrentMode() etisserant@0: lbessard@163: lbessard@163: #------------------------------------------------------------------------------- lbessard@231: # ToolBar Items Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: lbessard@163: def ResetCurrentMode(self): lbessard@235: selected = self.TabsOpened.GetSelection() etisserant@0: if selected != -1: lbessard@235: window = self.TabsOpened.GetPage(selected) lbessard@163: window.SetMode(MODE_SELECTION) lbessard@292: if USE_AUI: lbessard@292: ToolBar = self.Panes["ToolBar"] lbessard@292: else: lbessard@163: ToolBar = self.ToolBar lbessard@163: if ToolBar: lbessard@324: ToolBar.ToggleTool(ID_PLCOPENEDITORTOOLBARSELECTION, False) lbessard@163: ToolBar.ToggleTool(ID_PLCOPENEDITORTOOLBARSELECTION, True) lbessard@163: lbessard@163: def ResetToolToggle(self, id): lbessard@292: if USE_AUI: lbessard@292: tool = self.Panes["ToolBar"].FindById(id) lbessard@292: else: lbessard@163: tool = self.ToolBar.FindById(id) lbessard@163: tool.SetToggle(False) lbessard@163: lbessard@163: def OnSelectionTool(self, event): lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@56: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnCommentTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCOMMENT) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@56: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnVariableTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARVARIABLE) lbessard@235: selected = self.TabsOpened.GetSelection() etisserant@0: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnBlockTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARBLOCK) lbessard@235: selected = self.TabsOpened.GetSelection() etisserant@0: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnConnectionTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCONNECTION) lbessard@235: selected = self.TabsOpened.GetSelection() etisserant@0: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnPowerRailTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARPOWERRAIL) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_POWERRAIL) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnRungTool(self, event): lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).AddLadderRung() lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnCoilTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCOIL) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_COIL) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnContactTool(self, event): lbessard@163: if self.DrawingMode == FREEDRAWING_MODE: lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCONTACT) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@163: if self.DrawingMode == FREEDRAWING_MODE: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT) lbessard@163: else: lbessard@235: self.TabsOpened.GetPage(selected).AddLadderContact() lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnBranchTool(self, event): lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).AddLadderBranch() lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnInitialStepTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARINITIALSTEP) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_INITIALSTEP) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnStepTool(self, event): lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARSTEP) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_STEP) lbessard@163: else: lbessard@235: self.TabsOpened.GetPage(selected).AddStep() lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnActionBlockTool(self, event): lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARACTIONBLOCK) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_ACTION) lbessard@163: else: lbessard@235: self.TabsOpened.GetPage(selected).AddStepAction() lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnTransitionTool(self, event): lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARTRANSITION) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_TRANSITION) lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnDivergenceTool(self, event): lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARDIVERGENCE) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_DIVERGENCE) lbessard@163: else: lbessard@235: self.TabsOpened.GetPage(selected).AddDivergence() lbessard@163: event.Skip() lbessard@163: lbessard@163: def OnJumpTool(self, event): lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@163: self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARJUMP) lbessard@235: selected = self.TabsOpened.GetSelection() lbessard@163: if selected != -1: lbessard@163: if self.GetDrawingMode() == FREEDRAWING_MODE: lbessard@235: self.TabsOpened.GetPage(selected).SetMode(MODE_JUMP) lbessard@163: else: lbessard@235: self.TabsOpened.GetPage(selected).AddJump() lbessard@163: event.Skip() lbessard@163: lbessard@163: lbessard@163: #------------------------------------------------------------------------------- lbessard@163: # Add Project Elements Functions lbessard@163: #------------------------------------------------------------------------------- lbessard@163: lbessard@125: def OnAddDataTypeMenu(self, event): laurent@391: dialog = DataTypeDialog(self, _("Add a new data type"), _("Please enter data type name"), "", wx.OK|wx.CANCEL) laurent@407: dialog.SetDataTypeNames(self.Controler.GetProjectDataTypeNames()) lbessard@125: if dialog.ShowModal() == wx.ID_OK: laurent@555: tagname = self.Controler.ProjectAddDataType(dialog.GetValue()) laurent@555: if tagname is not None: laurent@555: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) laurent@555: self.EditProjectElement(ITEM_DATATYPE, tagname) lbessard@125: dialog.Destroy() lbessard@163: lbessard@163: def GenerateAddPouFunction(self, pou_type): lbessard@163: def OnAddPouMenu(event): lbessard@163: dialog = PouDialog(self, pou_type) laurent@407: dialog.SetPouNames(self.Controler.GetProjectPouNames()) laurent@407: dialog.SetPouElementNames(self.Controler.GetProjectPouVariables()) lbessard@163: if dialog.ShowModal() == wx.ID_OK: lbessard@163: values = dialog.GetValues() laurent@555: tagname = self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"]) laurent@555: if tagname is not None: laurent@555: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, LIBRARYTREE) laurent@555: self.EditProjectElement(ITEM_POU, tagname) lbessard@163: dialog.Destroy() lbessard@163: return OnAddPouMenu lbessard@163: lbessard@163: def GenerateAddTransitionFunction(self, pou_name): lbessard@163: def OnAddTransitionMenu(event): lbessard@163: dialog = PouTransitionDialog(self) laurent@407: dialog.SetPouNames(self.Controler.GetProjectPouNames()) laurent@407: dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name)) lbessard@163: if dialog.ShowModal() == wx.ID_OK: lbessard@163: values = dialog.GetValues() laurent@555: tagname = self.Controler.ProjectAddPouTransition(pou_name, values["transitionName"], values["language"]) laurent@555: if tagname is not None: laurent@555: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) laurent@555: self.EditProjectElement(ITEM_TRANSITION, tagname) laurent@555: dialog.Destroy() lbessard@163: return OnAddTransitionMenu lbessard@163: lbessard@163: def GenerateAddActionFunction(self, pou_name): lbessard@163: def OnAddActionMenu(event): lbessard@163: dialog = PouActionDialog(self) laurent@407: dialog.SetPouNames(self.Controler.GetProjectPouNames()) laurent@407: dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name)) lbessard@163: if dialog.ShowModal() == wx.ID_OK: lbessard@163: values = dialog.GetValues() laurent@555: tagname = self.Controler.ProjectAddPouAction(pou_name, values["actionName"], values["language"]) laurent@555: if tagname is not None: laurent@555: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) laurent@555: self.EditProjectElement(ITEM_ACTION, tagname) lbessard@163: dialog.Destroy() lbessard@163: return OnAddActionMenu etisserant@0: etisserant@0: def OnAddConfigurationMenu(self, event): laurent@391: dialog = ConfigurationNameDialog(self, _("Please enter configuration name"), _("Add new configuration")) laurent@407: dialog.SetPouNames(self.Controler.GetProjectPouNames()) laurent@407: dialog.SetPouElementNames(self.Controler.GetProjectPouVariables()) lbessard@64: if dialog.ShowModal() == wx.ID_OK: etisserant@0: value = dialog.GetValue() laurent@555: tagname = self.Controler.ProjectAddConfiguration(value) laurent@555: if tagname is not None: laurent@555: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) laurent@555: self.EditProjectElement(ITEM_CONFIGURATION, tagname) etisserant@0: dialog.Destroy() etisserant@0: lbessard@163: def GenerateAddResourceFunction(self, config_name): greg@177: def OnAddResourceMenu(event): laurent@391: dialog = ResourceNameDialog(self, _("Please enter resource name"), _("Add new resource")) laurent@407: dialog.SetPouNames(self.Controler.GetProjectPouNames()) laurent@407: dialog.SetPouElementNames(self.Controler.GetProjectPouVariables()) lbessard@64: if dialog.ShowModal() == wx.ID_OK: etisserant@0: value = dialog.GetValue() laurent@555: tagname = self.Controler.ProjectAddConfigurationResource(config_name, value) laurent@555: if tagname is not None: laurent@555: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) laurent@555: self.EditProjectElement(ITEM_RESOURCE, tagname) lbessard@163: dialog.Destroy() lbessard@163: return OnAddResourceMenu lbessard@163: lbessard@275: def GenerateChangePouTypeFunction(self, name, new_type): lbessard@275: def OnChangePouTypeMenu(event): lbessard@275: selected = self.TypesTree.GetSelection() lbessard@275: if self.TypesTree.GetPyData(selected) == ITEM_POU: lbessard@275: self.Controler.ProjectChangePouType(name, new_type) laurent@498: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, TYPESTREE, LIBRARYTREE) lbessard@275: return OnChangePouTypeMenu lbessard@163: b@428: def OnCopyPou(self, event): b@428: selected = self.TypesTree.GetSelection() b@428: pou_name = self.TypesTree.GetItemText(selected) laurent@447: laurent@447: pou_xml = self.Controler.GetPouXml(pou_name) laurent@447: if pou_xml is not None: laurent@447: self.SetCopyBuffer(pou_xml) laurent@447: self._Refresh(EDITMENU) b@428: b@428: def OnPastePou(self, event): b@428: selected = self.TypesTree.GetSelection() b@428: b@428: pou_type = self.TypesTree.GetItemText(selected) b@428: pou_type = UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs' b@428: pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type] b@428: b@428: pou_xml = self.GetCopyBuffer() b@428: b@428: result = self.Controler.PastePou(pou_type, pou_xml) b@428: b@428: if result is not None: b@428: message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) b@428: message.ShowModal() b@428: message.Destroy() b@428: else: laurent@498: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, TYPESTREE, LIBRARYTREE) b@428: lbessard@275: #------------------------------------------------------------------------------- lbessard@275: # Remove Project Elements Functions lbessard@275: #------------------------------------------------------------------------------- lbessard@275: lbessard@163: def OnRemoveDataTypeMenu(self, event): lbessard@235: selected = self.TypesTree.GetSelection() lbessard@235: if self.TypesTree.GetPyData(selected) == ITEM_DATATYPE: lbessard@235: name = self.TypesTree.GetItemText(selected) laurent@407: if not self.Controler.DataTypeIsUsed(name): lbessard@163: self.Controler.ProjectRemoveDataType(name) lbessard@163: tagname = self.Controler.ComputeDataTypeName(name) lbessard@121: idx = self.IsOpened(tagname) lbessard@121: if idx is not None: lbessard@235: self.TabsOpened.DeletePage(idx) laurent@498: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, TYPESTREE) lbessard@163: else: laurent@407: self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")) lbessard@163: lbessard@311: def OnRenamePouMenu(self, event): lbessard@311: selected = self.TypesTree.GetSelection() lbessard@311: if self.TypesTree.GetPyData(selected) == ITEM_POU: lbessard@311: wx.CallAfter(self.TypesTree.EditLabel, selected) lbessard@311: lbessard@163: def OnRemovePouMenu(self, event): lbessard@235: selected = self.TypesTree.GetSelection() lbessard@315: if self.TypesTree.GetPyData(selected) == ITEM_POU: lbessard@235: name = self.TypesTree.GetItemText(selected) laurent@407: if not self.Controler.PouIsUsed(name): lbessard@163: self.Controler.ProjectRemovePou(name) lbessard@163: tagname = self.Controler.ComputePouName(name) lbessard@163: idx = self.IsOpened(tagname) lbessard@163: if idx is not None: lbessard@163: self.VariablePanelIndexer.RemoveVariablePanel(tagname) lbessard@235: self.TabsOpened.DeletePage(idx) laurent@498: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE) lbessard@163: else: laurent@407: self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")) lbessard@163: lbessard@163: def OnRemoveTransitionMenu(self, event): lbessard@235: selected = self.TypesTree.GetSelection() lbessard@235: if self.TypesTree.GetPyData(selected) == ITEM_TRANSITION: lbessard@235: transition = self.TypesTree.GetItemText(selected) lbessard@235: item = self.TypesTree.GetItemParent(selected) lbessard@235: item_type = self.TypesTree.GetPyData(item) lbessard@163: while item_type != ITEM_POU: lbessard@235: item = self.TypesTree.GetItemParent(item) lbessard@235: item_type = self.TypesTree.GetPyData(item) lbessard@235: pou_name = self.TypesTree.GetItemText(item) lbessard@163: self.Controler.ProjectRemovePouTransition(pou_name, transition) lbessard@163: tagname = self.Controler.ComputePouTransitionName(pou_name, transition) lbessard@163: idx = self.IsOpened(tagname) lbessard@163: if idx is not None: lbessard@163: self.VariablePanelIndexer.RemoveVariablePanel(tagname) lbessard@235: self.TabsOpened.DeletePage(idx) laurent@498: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) lbessard@163: lbessard@163: def OnRemoveActionMenu(self, event): lbessard@235: selected = self.TypesTree.GetSelection() lbessard@235: if self.TypesTree.GetPyData(selected) == ITEM_ACTION: lbessard@235: action = self.TypesTree.GetItemText(selected) lbessard@235: item = self.TypesTree.GetItemParent(selected) lbessard@235: item_type = self.TypesTree.GetPyData(item) lbessard@163: while item_type != ITEM_POU: lbessard@235: item = self.TypesTree.GetItemParent(item) lbessard@235: item_type = self.TypesTree.GetPyData(item) lbessard@235: pou_name = self.TypesTree.GetItemText(item) lbessard@163: self.Controler.ProjectRemovePouAction(pou_name, action) lbessard@163: tagname = self.Controler.ComputePouActionName(pou_name, action) lbessard@163: idx = self.IsOpened(tagname) lbessard@163: if idx is not None: lbessard@163: self.VariablePanelIndexer.RemoveVariablePanel(tagname) lbessard@235: self.TabsOpened.DeletePage(idx) laurent@498: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE) lbessard@163: lbessard@239: def OnRemoveConfigurationMenu(self, event): lbessard@239: selected = self.TypesTree.GetSelection() lbessard@239: if self.TypesTree.GetPyData(selected) == ITEM_CONFIGURATION: lbessard@239: name = self.TypesTree.GetItemText(selected) lbessard@239: self.Controler.ProjectRemoveConfiguration(name) lbessard@239: tagname = self.Controler.ComputeConfigurationName(name) lbessard@239: idx = self.IsOpened(tagname) lbessard@239: if idx is not None: lbessard@239: self.VariablePanelIndexer.RemoveVariablePanel(tagname) lbessard@239: self.TabsOpened.DeletePage(idx) laurent@498: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) lbessard@239: lbessard@163: def OnRemoveResourceMenu(self, event): lbessard@235: selected = self.TypesTree.GetSelection() lbessard@235: if self.TypesTree.GetPyData(selected) == ITEM_RESOURCE: lbessard@235: resource = self.TypesTree.GetItemText(selected) lbessard@235: item = self.TypesTree.GetItemParent(selected) lbessard@235: item_type = self.TypesTree.GetPyData(item) lbessard@163: while item_type != ITEM_CONFIGURATION: lbessard@235: item = self.TypesTree.GetItemParent(item) lbessard@235: item_type = self.TypesTree.GetPyData(item) lbessard@235: config_name = self.TypesTree.GetItemText(item) lbessard@163: self.Controler.ProjectRemoveConfigurationResource(config_name, resource) lbessard@163: tagname = self.Controler.ComputeConfigurationResourceName(config_name, selected) lbessard@163: idx = self.IsOpened(tagname) lbessard@163: if idx is not None: lbessard@163: self.VariablePanelIndexer.RemoveVariablePanel(tagname) lbessard@235: self.TabsOpened.DeletePage(idx) laurent@498: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE) greg@190: greg@190: def OnPLCOpenEditorMenu(self, event): laurent@391: wx.MessageBox(_("No documentation available.\nComing soon.")) greg@190: etisserant@0: def OnPLCOpenMenu(self, event): greg@190: open_pdf(os.path.join(CWD, "plcopen", "TC6_XML_V101.pdf")) greg@190: greg@190: def OnAboutMenu(self, event): laurent@391: OpenHtmlFrame(self,_("About PLCOpenEditor"), os.path.join(CWD, "doc","about.html"), wx.Size(350, 350)) lbessard@231: lbessard@231: lbessard@231: #------------------------------------------------------------------------------- laurent@566: # Highlights showing functions laurent@566: #------------------------------------------------------------------------------- laurent@566: laurent@566: def ShowHighlight(self, infos, start, end, highlight_type): laurent@566: print infos, start, end, highlight_type lbessard@235: self.SelectTypesTreeItem(infos[0]) lbessard@231: if infos[1] == "name": laurent@566: self.Highlights[infos[0]] = highlight_type lbessard@235: self.RefreshTypesTree() lbessard@235: self.TypesTree.Unselect() lbessard@231: else: laurent@566: self.EditProjectElement(self.Controler.GetElementType(infos[0]), infos[0]) laurent@566: if infos[1] in plcopen.searchResultVarTypes.values() + ["var_local"]: laurent@566: self.VariablePanelIndexer.AddVariableHighlight(infos, highlight_type) laurent@566: else: laurent@566: selected = self.TabsOpened.GetSelection() laurent@566: if selected != -1: laurent@566: viewer = self.TabsOpened.GetPage(selected) laurent@566: viewer.AddHighlight(infos[1:], start, end, highlight_type) laurent@566: laurent@566: def ShowError(self, infos, start, end): laurent@566: self.ShowHighlight(infos, start, end, ERROR_HIGHLIGHT) laurent@566: laurent@566: def ShowSearchResult(self, infos, start, end): laurent@566: self.ShowHighlight(infos, start, end, SEARCH_RESULT_HIGHLIGHT) laurent@566: laurent@566: def ClearHighlights(self, highlight_type=None): laurent@566: if highlight_type is None: laurent@566: self.Highlights = {} laurent@566: else: laurent@566: self.Highlights = dict([(name, highlight) for name, highlight in self.Highlights.iteritems() if highlight != highlight_type]) lbessard@235: self.RefreshTypesTree() laurent@566: self.VariablePanelIndexer.ClearHighlights(highlight_type) lbessard@235: for i in xrange(self.TabsOpened.GetPageCount()): lbessard@235: viewer = self.TabsOpened.GetPage(i) laurent@566: viewer.ClearHighlights(highlight_type) laurent@566: laurent@566: def ClearErrors(self): laurent@566: self.ClearHighlights(ERROR_HIGHLIGHT) laurent@566: laurent@566: def ClearSearchResults(self): laurent@566: self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT) laurent@390: laurent@407: #------------------------------------------------------------------------------- laurent@407: # PLCOpenEditor Main Class laurent@407: #------------------------------------------------------------------------------- laurent@407: laurent@407: class PLCOpenEditor(IDEFrame): laurent@407: laurent@407: # Compatibility function for wx versions < 2.6 laurent@407: if wx.VERSION < (2, 6, 0): laurent@407: def Bind(self, event, function, id = None): laurent@407: if id is not None: laurent@407: event(self, id, function) laurent@407: else: laurent@407: event(self, function) laurent@407: laurent@407: def _init_coll_FileMenu_Items(self, parent): laurent@407: AppendMenu(parent, help='', id=wx.ID_NEW, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'New\tCTRL+N')) laurent@407: AppendMenu(parent, help='', id=wx.ID_OPEN, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Open\tCTRL+O')) laurent@407: AppendMenu(parent, help='', id=wx.ID_CLOSE, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Close Tab\tCTRL+W')) laurent@407: AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Close Project')) laurent@407: parent.AppendSeparator() laurent@407: AppendMenu(parent, help='', id=wx.ID_SAVE, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S')) laurent@407: AppendMenu(parent, help='', id=wx.ID_SAVEAS, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Save As...\tCTRL+SHIFT+S')) laurent@407: AppendMenu(parent, help='', id=ID_PLCOPENEDITORFILEMENUGENERATE, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Generate Program\tCTRL+G')) laurent@407: parent.AppendSeparator() laurent@407: AppendMenu(parent, help='', id=wx.ID_PAGE_SETUP, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Page Setup')) laurent@407: AppendMenu(parent, help='', id=wx.ID_PREVIEW, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Preview')) laurent@407: AppendMenu(parent, help='', id=wx.ID_PRINT, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Print')) laurent@407: parent.AppendSeparator() laurent@407: AppendMenu(parent, help='', id=wx.ID_PROPERTIES, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Properties')) laurent@407: parent.AppendSeparator() laurent@407: AppendMenu(parent, help='', id=wx.ID_EXIT, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q')) laurent@407: laurent@407: self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW) laurent@407: self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN) laurent@407: self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE) laurent@407: self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL) laurent@407: self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE) laurent@407: self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu, id=wx.ID_SAVEAS) laurent@407: self.Bind(wx.EVT_MENU, self.OnGenerateProgramMenu, laurent@407: id=ID_PLCOPENEDITORFILEMENUGENERATE) laurent@407: self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP) laurent@407: self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW) laurent@407: self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT) laurent@407: self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, id=wx.ID_PROPERTIES) laurent@407: self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT) laurent@407: laurent@407: def _init_coll_HelpMenu_Items(self, parent): laurent@407: AppendMenu(parent, help='', id=wx.ID_HELP, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'PLCOpenEditor\tF1')) laurent@407: #AppendMenu(parent, help='', id=wx.ID_HELP_CONTENTS, laurent@407: # kind=wx.ITEM_NORMAL, text=u'PLCOpen\tF2') laurent@407: #AppendMenu(parent, help='', id=wx.ID_HELP_CONTEXT, laurent@407: # kind=wx.ITEM_NORMAL, text=u'IEC 61131-3\tF3') laurent@407: AppendMenu(parent, help='', id=wx.ID_ABOUT, laurent@407: kind=wx.ITEM_NORMAL, text=_(u'About')) laurent@407: self.Bind(wx.EVT_MENU, self.OnPLCOpenEditorMenu, id=wx.ID_HELP) laurent@407: #self.Bind(wx.EVT_MENU, self.OnPLCOpenMenu, id=wx.ID_HELP_CONTENTS) laurent@407: self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT) laurent@407: laurent@407: ## Constructor of the PLCOpenEditor class. laurent@407: # @param parent The parent window. laurent@407: # @param controler The controler been used by PLCOpenEditor (default: None). laurent@407: # @param fileOpen The filepath to open if no controler defined (default: None). laurent@407: # @param debug The filepath to open if no controler defined (default: False). laurent@407: def __init__(self, parent, fileOpen = None): laurent@407: IDEFrame.__init__(self, parent) laurent@407: laurent@500: result = None laurent@500: laurent@407: # Open the filepath if defined laurent@438: if fileOpen is not None and os.path.isfile(fileOpen): laurent@407: # Create a new controller laurent@407: self.Controler = PLCControler() laurent@500: result = self.Controler.OpenXMLFile(fileOpen) laurent@500: if result is None: laurent@500: self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE) laurent@407: laurent@407: # Define PLCOpenEditor icon laurent@407: self.SetIcon(wx.Icon(os.path.join(CWD,"Images", "poe.ico"),wx.BITMAP_TYPE_ICO)) laurent@407: laurent@407: self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) laurent@407: laurent@407: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU) laurent@500: laurent@500: if result is not None: laurent@500: self.ShowErrorMessage(result) laurent@407: laurent@407: def OnCloseFrame(self, event): laurent@450: if self.Controler is None or self.CheckSaveBeforeClosing(_("Close Application")): laurent@407: if USE_AUI: laurent@407: self.AUIManager.UnInit() laurent@535: laurent@535: self.SaveFrameSize() laurent@535: laurent@407: event.Skip() laurent@407: else: laurent@407: event.Veto() laurent@407: laurent@407: def RefreshTitle(self): laurent@407: name = _("PLCOpenEditor") laurent@407: if self.Controler is not None: laurent@407: self.SetTitle("%s - %s"%(name, self.Controler.GetFilename())) laurent@407: else: laurent@407: self.SetTitle(name) laurent@407: laurent@407: #------------------------------------------------------------------------------- laurent@407: # File Menu Functions laurent@407: #------------------------------------------------------------------------------- laurent@407: laurent@407: def RefreshFileMenu(self): laurent@407: if self.Controler is not None: laurent@407: selected = self.TabsOpened.GetSelection() laurent@407: if selected >= 0: laurent@407: graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer) laurent@407: else: laurent@407: graphic_viewer = False laurent@407: if self.TabsOpened.GetPageCount() > 0: laurent@407: self.FileMenu.Enable(wx.ID_CLOSE, True) laurent@407: if graphic_viewer: laurent@407: self.FileMenu.Enable(wx.ID_PREVIEW, True) laurent@407: self.FileMenu.Enable(wx.ID_PRINT, True) laurent@407: else: laurent@407: self.FileMenu.Enable(wx.ID_PREVIEW, False) laurent@407: self.FileMenu.Enable(wx.ID_PRINT, False) laurent@407: else: laurent@407: self.FileMenu.Enable(wx.ID_CLOSE, False) laurent@407: self.FileMenu.Enable(wx.ID_PREVIEW, False) laurent@407: self.FileMenu.Enable(wx.ID_PRINT, False) laurent@407: self.FileMenu.Enable(wx.ID_PAGE_SETUP, True) laurent@407: self.FileMenu.Enable(wx.ID_SAVE, True) laurent@407: self.FileMenu.Enable(wx.ID_PROPERTIES, True) laurent@407: self.FileMenu.Enable(wx.ID_CLOSE_ALL, True) laurent@407: self.FileMenu.Enable(wx.ID_SAVEAS, True) laurent@407: self.FileMenu.Enable(ID_PLCOPENEDITORFILEMENUGENERATE, True) laurent@407: else: laurent@407: self.FileMenu.Enable(wx.ID_CLOSE, False) laurent@407: self.FileMenu.Enable(wx.ID_PAGE_SETUP, False) laurent@407: self.FileMenu.Enable(wx.ID_PREVIEW, False) laurent@407: self.FileMenu.Enable(wx.ID_PRINT, False) laurent@407: self.FileMenu.Enable(wx.ID_SAVE, False) laurent@407: self.FileMenu.Enable(wx.ID_PROPERTIES, False) laurent@407: self.FileMenu.Enable(wx.ID_CLOSE_ALL, False) laurent@407: self.FileMenu.Enable(wx.ID_SAVEAS, False) laurent@407: self.FileMenu.Enable(ID_PLCOPENEDITORFILEMENUGENERATE, False) laurent@407: laurent@407: def OnNewProjectMenu(self, event): laurent@407: if self.Controler is not None and not self.CheckSaveBeforeClosing(): laurent@407: return laurent@407: dialog = ProjectDialog(self) laurent@407: if dialog.ShowModal() == wx.ID_OK: laurent@407: properties = dialog.GetValues() laurent@411: self.ResetView() laurent@407: self.Controler = PLCControler() laurent@407: self.Controler.CreateNewProject(properties) laurent@407: self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, laurent@407: LIBRARYTREE) laurent@407: laurent@407: def OnOpenProjectMenu(self, event): laurent@407: if self.Controler is not None and not self.CheckSaveBeforeClosing(): laurent@407: return laurent@407: filepath = "" laurent@407: if self.Controler is not None: laurent@407: filepath = self.Controler.GetFilePath() laurent@407: if filepath != "": laurent@407: directory = os.path.dirname(filepath) laurent@407: else: laurent@407: directory = os.getcwd() laurent@500: laurent@500: result = None laurent@500: laurent@407: dialog = wx.FileDialog(self, _("Choose a file"), directory, "", _("PLCOpen files (*.xml)|*.xml|All files|*.*"), wx.OPEN) laurent@407: if dialog.ShowModal() == wx.ID_OK: laurent@407: filepath = dialog.GetPath() laurent@407: if os.path.isfile(filepath): laurent@411: self.ResetView() laurent@407: self.Controler = PLCControler() laurent@500: result = self.Controler.OpenXMLFile(filepath) laurent@500: if result is None: laurent@500: self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE) laurent@407: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU) laurent@407: dialog.Destroy() laurent@500: laurent@500: if result is not None: laurent@500: self.ShowErrorMessage(result) laurent@407: laurent@407: def OnCloseProjectMenu(self, event): laurent@407: if not self.CheckSaveBeforeClosing(): laurent@407: return laurent@411: self.ResetView() laurent@407: self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU) laurent@407: laurent@407: def OnSaveProjectMenu(self, event): laurent@407: self.SaveProject() laurent@407: laurent@407: def OnSaveProjectAsMenu(self, event): laurent@407: self.SaveProjectAs() laurent@407: laurent@407: def OnGenerateProgramMenu(self, event): laurent@407: dialog = wx.FileDialog(self, _("Choose a file"), os.getcwd(), self.Controler.GetProgramFilePath(), _("ST files (*.st)|*.st|All files|*.*"), wx.SAVE|wx.CHANGE_DIR) laurent@407: if dialog.ShowModal() == wx.ID_OK: laurent@407: filepath = dialog.GetPath() laurent@407: message_text = "" laurent@407: header, icon = _("Done"), wx.ICON_INFORMATION laurent@407: if os.path.isdir(os.path.dirname(filepath)): laurent@407: program, errors, warnings = self.Controler.GenerateProgram(filepath) laurent@407: message_text += "".join([_("warning: %s\n") for warning in warnings]) laurent@407: if len(errors) > 0: laurent@540: message_text += "".join([_("error: %s\n") for error in errors]) laurent@407: message_text += _("Can't generate program to file %s!")%filepath laurent@407: header, icon = _("Error"), wx.ICON_ERROR laurent@407: else: laurent@407: message_text += _("Program was successfully generated!") laurent@407: else: laurent@407: message_text += _("\"%s\" is not a valid folder!")%os.path.dirname(filepath) laurent@407: header, icon = _("Error"), wx.ICON_ERROR laurent@407: message = wx.MessageDialog(self, message_text, header, wx.OK|icon) laurent@407: message.ShowModal() laurent@407: message.Destroy() laurent@407: dialog.Destroy() laurent@407: laurent@407: def SaveProject(self): laurent@407: result = self.Controler.SaveXMLFile() laurent@407: if not result: laurent@407: self.SaveProjectAs() laurent@407: else: laurent@407: self.RefreshTitle() laurent@502: self.RefreshFileMenu() laurent@407: laurent@407: def SaveProjectAs(self): laurent@407: filepath = self.Controler.GetFilePath() laurent@407: if filepath != "": laurent@407: directory, filename = os.path.split(filepath) laurent@407: else: laurent@407: directory, filename = os.getcwd(), "%(projectName)s.xml"%self.Controler.GetProjectProperties() laurent@407: dialog = wx.FileDialog(self, _("Choose a file"), directory, filename, _("PLCOpen files (*.xml)|*.xml|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT) laurent@407: if dialog.ShowModal() == wx.ID_OK: laurent@407: filepath = dialog.GetPath() laurent@407: if os.path.isdir(os.path.dirname(filepath)): laurent@407: result = self.Controler.SaveXMLFile(filepath) laurent@407: if not result: laurent@407: self.ShowErrorMessage(_("Can't save project to file %s!")%filepath) laurent@407: else: laurent@407: self.ShowErrorMessage(_("\"%s\" is not a valid folder!")%os.path.dirname(filepath)) laurent@407: self.RefreshTitle() laurent@502: self.RefreshFileMenu() laurent@407: dialog.Destroy() etisserant@0: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Create Project Dialog etisserant@0: #------------------------------------------------------------------------------- etisserant@0: lbessard@145: [ID_SCALINGPANEL, ID_SCALINGPANELXSCALE, lbessard@145: ID_SCALINGPANELYSCALE, ID_SCALINGPANELSTATICTEXT1, lbessard@145: ID_SCALINGPANELSTATICTEXT2, lbessard@145: ] = [wx.NewId() for _init_ctrls in range(5)] lbessard@145: lbessard@145: class ScalingPanel(wx.Panel): lbessard@145: lbessard@145: def _init_coll_ScalingPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText1, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) lbessard@145: parent.AddWindow(self.XScale, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText2, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT) lbessard@145: parent.AddWindow(self.YScale, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) lbessard@145: lbessard@145: def _init_coll_ScalingPanelSizer_Growables(self, parent): lbessard@145: parent.AddGrowableCol(1) lbessard@145: lbessard@145: def _init_sizers(self): laurent@391: self.ScalingPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5) lbessard@145: lbessard@145: self._init_coll_ScalingPanelSizer_Items(self.ScalingPanelSizer) lbessard@145: self._init_coll_ScalingPanelSizer_Growables(self.ScalingPanelSizer) lbessard@145: lbessard@145: self.SetSizer(self.ScalingPanelSizer) lbessard@145: lbessard@145: def _init_ctrls(self, prnt): lbessard@145: wx.Panel.__init__(self, id=ID_SCALINGPANEL, lbessard@145: name='ScalingPanel', parent=prnt, pos=wx.Point(0, 0), lbessard@163: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@145: lbessard@145: self.staticText1 = wx.StaticText(id=ID_SCALINGPANELSTATICTEXT1, laurent@555: label=_('Horizontal:'), name='staticText1', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.XScale = wx.SpinCtrl(id=ID_SCALINGPANELXSCALE, lbessard@145: name='XScale', parent=self, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0, min=0, max=2**16) lbessard@145: lbessard@145: self.staticText2 = wx.StaticText(id=ID_SCALINGPANELSTATICTEXT2, laurent@555: label=_('Vertical:'), name='staticText2', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.YScale = wx.SpinCtrl(id=ID_SCALINGPANELYSCALE, lbessard@145: name='YScale', parent=self, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0, min=0, max=2**16) lbessard@145: lbessard@145: self._init_sizers() lbessard@145: lbessard@145: def __init__(self, parent): lbessard@145: self._init_ctrls(parent) lbessard@145: lbessard@145: def SetScaling(self, x, y): lbessard@145: self.XScale.SetValue(x) lbessard@145: self.YScale.SetValue(y) lbessard@145: lbessard@145: def GetScaling(self): lbessard@145: return self.XScale.GetValue(), self.YScale.GetValue() lbessard@145: lbessard@145: [ID_PROJECTDIALOG, ID_PROJECTDIALOGMAINNOTEBOOK, lbessard@145: ID_PROJECTDIALOGPROJECTPANEL, ID_PROJECTDIALOGAUTHORPANEL, lbessard@145: ID_PROJECTDIALOGGRAPHICSPANEL, ID_PROJECTDIALOGMISCELLANEOUSPANEL, lbessard@145: ID_PROJECTDIALOGPROJECTNAME, ID_PROJECTDIALOGPROJECTVERSION, lbessard@64: ID_PROJECTDIALOGPRODUCTNAME, ID_PROJECTDIALOGPRODUCTVERSION, lbessard@145: ID_PROJECTDIALOGPRODUCTRELEASE, ID_PROJECTDIALOGCOMPANYNAME, lbessard@145: ID_PROJECTDIALOGCOMPANYURL, ID_PROJECTDIALOGAUTHORNAME, lbessard@145: ID_PROJECTDIALOGORGANIZATION, ID_PROJECTDIALOGLANGUAGE, lbessard@145: ID_PROJECTDIALOGCONTENTDESCRIPTION, ID_PROJECTDIALOGSCALINGNOTEBOOK, lbessard@145: ID_PROJECTDIALOGPAGEWIDTH, ID_PROJECTDIALOGPAGEHEIGHT, lbessard@64: ID_PROJECTDIALOGSTATICTEXT1, ID_PROJECTDIALOGSTATICTEXT2, lbessard@64: ID_PROJECTDIALOGSTATICTEXT3, ID_PROJECTDIALOGSTATICTEXT4, lbessard@64: ID_PROJECTDIALOGSTATICTEXT5, ID_PROJECTDIALOGSTATICTEXT6, lbessard@145: ID_PROJECTDIALOGSTATICTEXT7, ID_PROJECTDIALOGSTATICTEXT8, lbessard@145: ID_PROJECTDIALOGSTATICTEXT9, ID_PROJECTDIALOGSTATICTEXT10, lbessard@145: ID_PROJECTDIALOGSTATICTEXT11, ID_PROJECTDIALOGSTATICTEXT12, lbessard@145: ID_PROJECTDIALOGSTATICTEXT13, ID_PROJECTDIALOGSTATICTEXT14, lbessard@145: ID_PROJECTDIALOGSTATICTEXT15, lbessard@145: ] = [wx.NewId() for _init_ctrls in range(35)] lbessard@145: etisserant@0: class ProjectDialog(wx.Dialog): lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: etisserant@0: def _init_coll_flexGridSizer1_Items(self, parent): lbessard@145: parent.AddSizer(self.MainNotebook, 0, border=0, flag=wx.GROW) lbessard@64: parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@64: lbessard@64: def _init_coll_flexGridSizer1_Growables(self, parent): lbessard@64: parent.AddGrowableCol(0) lbessard@64: parent.AddGrowableRow(0) lbessard@64: lbessard@145: def _init_coll_ProjectPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText1, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) lbessard@145: parent.AddWindow(self.ProjectName, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText2, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.ProjectVersion, 0, border=10, flag=wx.GROW|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText3, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.ProductName, 0, border=10, flag=wx.GROW|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText4, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.ProductVersion, 0, border=10, flag=wx.GROW|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText5, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT) lbessard@145: parent.AddWindow(self.ProductRelease, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) lbessard@145: lbessard@145: def _init_coll_ProjectPanelSizer_Growables(self, parent): lbessard@64: parent.AddGrowableCol(1) lbessard@145: lbessard@145: def _init_coll_AuthorPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText6, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) lbessard@145: parent.AddWindow(self.CompanyName, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText7, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.CompanyURL, 0, border=10, flag=wx.GROW|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText8, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.AuthorName, 0, border=10, flag=wx.GROW|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText9, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT) lbessard@145: parent.AddWindow(self.Organization, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) lbessard@145: lbessard@145: def _init_coll_AuthorPanelSizer_Growables(self, parent): lbessard@145: parent.AddGrowableCol(1) lbessard@145: lbessard@145: def _init_coll_GraphicsPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText12, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT|wx.RIGHT) lbessard@145: parent.AddSizer(self.GraphicsPageSizeSizer, 0, border=10, flag=wx.GROW|wx.LEFT|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText15, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT) lbessard@145: parent.AddWindow(self.ScalingNotebook, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@145: lbessard@145: def _init_coll_GraphicsPanelSizer_Growables(self, parent): lbessard@145: parent.AddGrowableCol(0) lbessard@145: parent.AddGrowableRow(3) lbessard@145: lbessard@145: def _init_coll_GraphicsPageSizeSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText13, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.PageWidth, 0, border=0, flag=wx.GROW) laurent@391: parent.AddWindow(self.staticText14, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) lbessard@145: parent.AddWindow(self.PageHeight, 0, border=0, flag=wx.GROW) lbessard@145: lbessard@145: def _init_coll_GraphicsPageSizeSizer_Growables(self, parent): lbessard@145: parent.AddGrowableCol(1) lbessard@145: lbessard@145: def _init_coll_MiscellaneousPanelSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText10, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) lbessard@145: parent.AddWindow(self.Language, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) laurent@391: parent.AddWindow(self.staticText11, 0, border=10, flag=wx.BOTTOM|wx.LEFT) lbessard@145: parent.AddWindow(self.ContentDescription, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) lbessard@145: lbessard@145: def _init_coll_MiscellaneousPanelSizer_Growables(self, parent): lbessard@145: parent.AddGrowableCol(1) lbessard@145: parent.AddGrowableRow(1) lbessard@64: etisserant@0: def _init_sizers(self): lbessard@64: self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) laurent@391: self.ProjectPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15) laurent@391: self.AuthorPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15) laurent@391: self.GraphicsPanelSizer = wx.FlexGridSizer(cols=1, hgap=5, rows=4, vgap=5) laurent@391: self.GraphicsPageSizeSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5) laurent@391: self.MiscellaneousPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15) etisserant@0: etisserant@0: self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) lbessard@64: self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) lbessard@145: self._init_coll_ProjectPanelSizer_Items(self.ProjectPanelSizer) lbessard@145: self._init_coll_ProjectPanelSizer_Growables(self.ProjectPanelSizer) lbessard@145: self._init_coll_AuthorPanelSizer_Items(self.AuthorPanelSizer) lbessard@145: self._init_coll_AuthorPanelSizer_Growables(self.AuthorPanelSizer) lbessard@145: self._init_coll_GraphicsPanelSizer_Items(self.GraphicsPanelSizer) lbessard@145: self._init_coll_GraphicsPanelSizer_Growables(self.GraphicsPanelSizer) lbessard@145: self._init_coll_GraphicsPageSizeSizer_Items(self.GraphicsPageSizeSizer) lbessard@145: self._init_coll_GraphicsPageSizeSizer_Growables(self.GraphicsPageSizeSizer) lbessard@145: self._init_coll_MiscellaneousPanelSizer_Items(self.MiscellaneousPanelSizer) lbessard@145: self._init_coll_MiscellaneousPanelSizer_Growables(self.MiscellaneousPanelSizer) etisserant@0: etisserant@0: self.SetSizer(self.flexGridSizer1) lbessard@145: self.ProjectPanel.SetSizer(self.ProjectPanelSizer) lbessard@145: self.AuthorPanel.SetSizer(self.AuthorPanelSizer) lbessard@145: self.GraphicsPanel.SetSizer(self.GraphicsPanelSizer) lbessard@145: self.MiscellaneousPanel.SetSizer(self.MiscellaneousPanelSizer) etisserant@0: etisserant@0: def _init_ctrls(self, prnt): lbessard@64: wx.Dialog.__init__(self, id=ID_PROJECTDIALOG, laurent@534: name='ProjectDialog', parent=prnt, lbessard@145: size=wx.Size(500, 350), style=wx.DEFAULT_DIALOG_STYLE, laurent@391: title=_('Project properties')) lbessard@145: self.SetClientSize(wx.Size(500, 350)) lbessard@145: lbessard@145: self.MainNotebook = wx.Notebook(id=ID_PROJECTDIALOGMAINNOTEBOOK, lbessard@145: name='MainNotebook', parent=self, pos=wx.Point(0, lbessard@145: 0), size=wx.Size(0, 0), style=0) lbessard@145: lbessard@145: # Project Panel elements lbessard@145: lbessard@145: self.ProjectPanel = wx.Panel(id=ID_PROJECTDIALOGPROJECTPANEL, lbessard@145: name='ProjectPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) etisserant@0: lbessard@64: self.staticText1 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT1, laurent@391: label=_('Project Name (required):'), name='staticText1', parent=self.ProjectPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@64: self.ProjectName = wx.TextCtrl(id=ID_PROJECTDIALOGPROJECTNAME, lbessard@145: name='ProjectName', parent=self.ProjectPanel, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@64: self.staticText2 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT2, laurent@391: label=_('Project Version (optional):'), name='staticText2', parent=self.ProjectPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@145: self.ProjectVersion = wx.TextCtrl(id=ID_PROJECTDIALOGPROJECTVERSION, lbessard@145: name='ProjectVersion', parent=self.ProjectPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0) lbessard@145: lbessard@145: self.staticText3 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT3, laurent@391: label=_('Product Name (required):'), name='staticText3', parent=self.ProjectPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.ProductName = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTNAME, lbessard@145: name='ProductName', parent=self.ProjectPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0) lbessard@145: lbessard@145: self.staticText4 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT4, laurent@391: label=_('Product Version (required):'), name='staticText4', parent=self.ProjectPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.ProductVersion = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTVERSION, lbessard@145: name='ProductVersion', parent=self.ProjectPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0) lbessard@145: lbessard@145: self.staticText5 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT5, laurent@391: label=_('Product Release (optional):'), name='staticText5', parent=self.ProjectPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.ProductRelease = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTRELEASE, lbessard@145: name='ProductRelease', parent=self.ProjectPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0) lbessard@145: laurent@391: self.MainNotebook.AddPage(self.ProjectPanel, _("Project")) lbessard@145: lbessard@145: # Author Panel elements lbessard@145: lbessard@145: self.AuthorPanel = wx.Panel(id=ID_PROJECTDIALOGAUTHORPANEL, lbessard@145: name='AuthorPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@145: lbessard@145: self.staticText6 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT6, laurent@391: label=_('Company Name (required):'), name='staticText6', parent=self.AuthorPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@64: self.CompanyName = wx.TextCtrl(id=ID_PROJECTDIALOGCOMPANYNAME, lbessard@145: name='CompanyName', parent=self.AuthorPanel, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@145: self.staticText7 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT7, laurent@391: label=_('Company URL (optional):'), name='staticText7', parent=self.AuthorPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@64: self.CompanyURL = wx.TextCtrl(id=ID_PROJECTDIALOGCOMPANYURL, lbessard@145: name='CompanyURL', parent=self.AuthorPanel, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@145: self.staticText8 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT8, laurent@391: label=_('Author Name (optional):'), name='staticText8', parent=self.AuthorPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@145: self.AuthorName = wx.TextCtrl(id=ID_PROJECTDIALOGAUTHORNAME, lbessard@145: name='AuthorName', parent=self.AuthorPanel, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@145: self.staticText9 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT9, laurent@391: label=_('Organization (optional):'), name='staticText9', parent=self.AuthorPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@145: self.Organization = wx.TextCtrl(id=ID_PROJECTDIALOGORGANIZATION, lbessard@145: name='Organization', parent=self.AuthorPanel, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: laurent@391: self.MainNotebook.AddPage(self.AuthorPanel, _("Author")) lbessard@145: lbessard@145: # Graphics Panel elements lbessard@145: lbessard@145: self.GraphicsPanel = wx.Panel(id=ID_PROJECTDIALOGGRAPHICSPANEL, lbessard@145: name='GraphicsPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@145: lbessard@145: self.staticText12 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT12, laurent@391: label=_('Page Size (optional):'), name='staticText12', parent=self.GraphicsPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@145: self.staticText13 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT13, laurent@391: label=_('Width:'), name='staticText13', parent=self.GraphicsPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.PageWidth = wx.SpinCtrl(id=ID_PROJECTDIALOGPAGEWIDTH, lbessard@145: name='PageWidth', parent=self.GraphicsPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0, min=0, max=2**16) lbessard@145: lbessard@145: self.staticText14 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT14, laurent@391: label=_('Height:'), name='staticText14', parent=self.GraphicsPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.PageHeight = wx.SpinCtrl(id=ID_PROJECTDIALOGPAGEHEIGHT, lbessard@145: name='PageHeight', parent=self.GraphicsPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=0, min=0, max=2**16) lbessard@145: lbessard@145: self.staticText15 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT15, laurent@555: label=_('Grid Resolution:'), name='staticText15', parent=self.GraphicsPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@145: self.ScalingNotebook = wx.Notebook(id=ID_PROJECTDIALOGSCALINGNOTEBOOK, lbessard@145: name='ScalingNotebook', parent=self.GraphicsPanel, pos=wx.Point(0, lbessard@145: 0), size=wx.Size(0, 0), style=0) lbessard@145: lbessard@145: self.Scalings = {} laurent@391: for language, translation in [("FBD",_("FBD")), ("LD",_("LD")), ("SFC",_("SFC"))]: lbessard@145: window = ScalingPanel(self.ScalingNotebook) lbessard@145: self.Scalings[language] = window laurent@391: self.ScalingNotebook.AddPage(window, translation) laurent@391: laurent@391: self.MainNotebook.AddPage(self.GraphicsPanel, _("Graphics")) lbessard@145: lbessard@145: # Miscellaneous Panel elements lbessard@145: lbessard@145: self.MiscellaneousPanel = wx.Panel(id=ID_PROJECTDIALOGMISCELLANEOUSPANEL, lbessard@145: name='MiscellaneousPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@145: lbessard@145: self.staticText10 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT10, laurent@391: label=_('Language (optional):'), name='staticText10', parent=self.MiscellaneousPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@145: lbessard@304: self.Language = wx.ComboBox(id=ID_PROJECTDIALOGLANGUAGE, lbessard@145: name='Language', parent=self.MiscellaneousPanel, pos=wx.Point(0, 0), lbessard@346: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@64: lbessard@145: self.staticText11 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT11, laurent@391: label=_('Content Description (optional):'), name='staticText11', parent=self.MiscellaneousPanel, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@64: self.ContentDescription = wx.TextCtrl(id=ID_PROJECTDIALOGCONTENTDESCRIPTION, lbessard@145: name='ContentDescription', parent=self.MiscellaneousPanel, pos=wx.Point(0, 0), lbessard@145: size=wx.Size(0, 24), style=wx.TE_MULTILINE) lbessard@145: laurent@391: self.MainNotebook.AddPage(self.MiscellaneousPanel, _("Miscellaneous")) lbessard@64: lbessard@64: self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) lbessard@64: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) lbessard@64: etisserant@0: self._init_sizers() etisserant@0: laurent@482: def __init__(self, parent, enable_required=True): etisserant@0: self._init_ctrls(parent) lbessard@64: laurent@482: self.ProjectName.Enable(enable_required) laurent@482: self.ProductName.Enable(enable_required) laurent@482: self.ProductVersion.Enable(enable_required) laurent@482: self.CompanyName.Enable(enable_required) laurent@482: laurent@391: languages = ["", "en-US", "fr-FR", "zh-CN"] lbessard@145: lbessard@145: for language in languages: lbessard@145: self.Language.Append(language) lbessard@145: etisserant@0: def OnOK(self, event): etisserant@0: error = [] etisserant@0: if self.ProjectName.GetValue() == "": etisserant@0: error.append("Project Name") etisserant@0: if self.CompanyName.GetValue() == "": etisserant@0: error.append("Company Name") etisserant@0: if self.ProductName.GetValue() == "": etisserant@0: error.append("Product Name") etisserant@0: if self.ProductVersion.GetValue() == "": etisserant@0: error.append("Product Version") etisserant@0: if len(error) > 0: etisserant@0: text = "" etisserant@0: for i, item in enumerate(error): etisserant@0: if i == 0: etisserant@0: text += item etisserant@0: elif i == len(error) - 1: etisserant@0: text += " and %s"%item etisserant@0: else: lbessard@145: text += ", %s"%item laurent@391: message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() etisserant@0: else: lbessard@64: self.EndModal(wx.ID_OK) etisserant@0: etisserant@0: def SetValues(self, values): etisserant@0: for item, value in values.items(): etisserant@0: if item == "projectName": etisserant@0: self.ProjectName.SetValue(value) lbessard@145: elif item == "projectVersion": lbessard@145: self.ProjectVersion.SetValue(value) etisserant@0: elif item == "productName": etisserant@0: self.ProductName.SetValue(value) etisserant@0: elif item == "productVersion": etisserant@0: self.ProductVersion.SetValue(value) etisserant@0: elif item == "productRelease": etisserant@0: self.ProductRelease.SetValue(value) lbessard@145: elif item == "companyName": lbessard@145: self.CompanyName.SetValue(value) lbessard@145: elif item == "companyURL": lbessard@145: self.CompanyURL.SetValue(value) lbessard@145: elif item == "authorName": lbessard@145: self.AuthorName.SetValue(value) lbessard@145: elif item == "organization": lbessard@145: self.Organization.SetValue(value) lbessard@145: elif item == "language": lbessard@145: self.Language.SetStringSelection(value) etisserant@0: elif item == "contentDescription": etisserant@0: self.ContentDescription.SetValue(value) lbessard@145: elif item == "pageSize": lbessard@145: self.PageWidth.SetValue(value[0]) lbessard@145: self.PageHeight.SetValue(value[1]) lbessard@145: elif item == "scaling": lbessard@145: for language, (x, y) in value.items(): lbessard@145: if language in self.Scalings: lbessard@145: self.Scalings[language].SetScaling(x, y) lbessard@145: etisserant@0: def GetValues(self): etisserant@0: values = {} etisserant@0: values["projectName"] = self.ProjectName.GetValue() lbessard@145: if self.ProjectVersion.GetValue() != "": lbessard@145: values["projectVersion"] = self.ProjectVersion.GetValue() etisserant@0: values["productName"] = self.ProductName.GetValue() etisserant@0: values["productVersion"] = self.ProductVersion.GetValue() lbessard@145: if self.ProductRelease.GetValue() != "": etisserant@0: values["productRelease"] = self.ProductRelease.GetValue() lbessard@145: values["companyName"] = self.CompanyName.GetValue() lbessard@145: if self.CompanyURL.GetValue() != "": lbessard@145: values["companyURL"] = self.CompanyURL.GetValue() lbessard@145: if self.AuthorName.GetValue() != "": lbessard@145: values["authorName"] = self.AuthorName.GetValue() lbessard@145: if self.Organization.GetValue() != "": lbessard@145: values["organization"] = self.Organization.GetValue() lbessard@145: if self.Language.GetStringSelection() != "": lbessard@145: values["language"] = self.Language.GetStringSelection() lbessard@145: if self.ProductRelease.GetValue() != "": etisserant@0: values["contentDescription"] = self.ContentDescription.GetValue() lbessard@145: values["pageSize"] = (self.PageWidth.GetValue(), self.PageHeight.GetValue()) lbessard@145: values["scaling"] = {} lbessard@145: for language in ["FBD", "LD", "SFC"]: lbessard@145: values["scaling"][language] = self.Scalings[language].GetScaling() etisserant@0: return values etisserant@0: etisserant@0: #------------------------------------------------------------------------------- lbessard@125: # Edit Step Name Dialog lbessard@125: #------------------------------------------------------------------------------- lbessard@125: lbessard@125: class DataTypeDialog(wx.TextEntryDialog): lbessard@125: lbessard@125: if wx.VERSION < (2, 6, 0): lbessard@125: def Bind(self, event, function, id = None): lbessard@125: if id is not None: lbessard@125: event(self, id, function) lbessard@125: else: lbessard@125: event(self, function) lbessard@125: laurent@391: def __init__(self, parent, message, caption = _("Please enter text"), defaultValue = "", lbessard@125: style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition): lbessard@125: wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) lbessard@125: lbessard@125: self.DataTypeNames = [] lbessard@125: if wx.VERSION >= (2, 8, 0): lbessard@125: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId()) lbessard@125: elif wx.VERSION >= (2, 6, 0): lbessard@125: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId()) lbessard@125: else: lbessard@125: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) lbessard@125: lbessard@125: def OnOK(self, event): lbessard@125: datatype_name = self.GetSizer().GetItem(1).GetWindow().GetValue() lbessard@125: if datatype_name == "": laurent@391: message = wx.MessageDialog(self, _("You must type a name!"), _("Error"), wx.OK|wx.ICON_ERROR) lbessard@125: message.ShowModal() lbessard@125: message.Destroy() lbessard@125: elif not TestIdentifier(datatype_name): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%datatype_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@125: message.ShowModal() lbessard@125: message.Destroy() lbessard@125: elif datatype_name.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%datatype_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@125: message.ShowModal() lbessard@125: message.Destroy() lbessard@125: elif datatype_name.upper() in self.DataTypeNames: laurent@391: message = wx.MessageDialog(self, _("\"%s\" data type already exists!")%datatype_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@125: message.ShowModal() lbessard@125: message.Destroy() lbessard@125: else: lbessard@125: self.EndModal(wx.ID_OK) lbessard@125: lbessard@125: def SetDataTypeNames(self, datatype_names): lbessard@125: self.DataTypeNames = [datatype_name.upper() for datatype_name in datatype_names] lbessard@125: lbessard@125: def GetValue(self): lbessard@125: return self.GetSizer().GetItem(1).GetWindow().GetValue() lbessard@125: lbessard@125: #------------------------------------------------------------------------------- etisserant@0: # Create Pou Dialog etisserant@0: #------------------------------------------------------------------------------- etisserant@0: lbessard@64: [ID_POUDIALOG, ID_POUDIALOGPOUNAME, lbessard@64: ID_POUDIALOGPOUTYPE, ID_POUDIALOGLANGUAGE, ID_POUDIALOGSTATICTEXT1, lbessard@64: ID_POUDIALOGSTATICTEXT2, ID_POUDIALOGSTATICTEXT3, lbessard@64: ] = [wx.NewId() for _init_ctrls in range(7)] etisserant@0: laurent@391: def GetTransitionLanguages(): laurent@391: _ = lambda x : x laurent@391: return [_("IL"), _("ST"), _("LD"), _("FBD")] laurent@391: TRANSITION_LANGUAGES_DICT = dict([(_(language), language) for language in GetTransitionLanguages()]) laurent@391: laurent@391: def GetPouTypes(): laurent@391: _ = lambda x : x laurent@391: return [_("function"), _("functionBlock"), _("program")] laurent@391: POU_TYPES_DICT = dict([(_(pou_type), pou_type) for pou_type in GetPouTypes()]) laurent@391: laurent@391: def GetPouLanguages(): laurent@391: _ = lambda x : x laurent@391: return [_("IL"), _("ST"), _("LD"), _("FBD"), _("SFC")] laurent@391: POU_LANGUAGES_DICT = dict([(_(language), language) for language in GetPouLanguages()]) laurent@391: etisserant@0: class PouDialog(wx.Dialog): lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: etisserant@0: def _init_coll_flexGridSizer1_Items(self, parent): lbessard@64: parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) lbessard@64: parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@64: lbessard@64: def _init_coll_flexGridSizer1_Growables(self, parent): lbessard@64: parent.AddGrowableCol(0) lbessard@64: parent.AddGrowableRow(0) lbessard@64: lbessard@64: def _init_coll_MainSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText1, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.PouName, 0, border=0, flag=wx.GROW) laurent@391: parent.AddWindow(self.staticText2, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.PouType, 0, border=0, flag=wx.GROW) laurent@391: parent.AddWindow(self.staticText3, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.Language, 0, border=0, flag=wx.GROW) lbessard@64: lbessard@64: def _init_coll_MainSizer_Growables(self, parent): lbessard@64: parent.AddGrowableCol(1) lbessard@64: etisserant@0: def _init_sizers(self): lbessard@64: self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) laurent@391: self.MainSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=3, vgap=15) etisserant@0: etisserant@0: self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) lbessard@64: self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) lbessard@64: self._init_coll_MainSizer_Items(self.MainSizer) lbessard@64: self._init_coll_MainSizer_Growables(self.MainSizer) etisserant@0: etisserant@0: self.SetSizer(self.flexGridSizer1) lbessard@64: etisserant@0: def _init_ctrls(self, prnt): lbessard@64: wx.Dialog.__init__(self, id=ID_POUDIALOG, laurent@534: name='PouDialog', parent=prnt, etisserant@0: size=wx.Size(300, 200), style=wx.DEFAULT_DIALOG_STYLE, laurent@391: title=_('Create a new POU')) etisserant@0: self.SetClientSize(wx.Size(300, 200)) etisserant@0: lbessard@64: self.staticText1 = wx.StaticText(id=ID_POUDIALOGSTATICTEXT1, laurent@391: label=_('POU Name:'), name='staticText1', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@64: self.PouName = wx.TextCtrl(id=ID_POUDIALOGPOUNAME, lbessard@64: name='POUName', parent=self, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@64: self.staticText2 = wx.StaticText(id=ID_POUDIALOGSTATICTEXT2, laurent@391: label=_('POU Type:'), name='staticText2', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@304: self.PouType = wx.ComboBox(id=ID_POUDIALOGPOUTYPE, lbessard@64: name='POUType', parent=self, pos=wx.Point(0, 0), lbessard@346: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@304: self.Bind(wx.EVT_COMBOBOX, self.OnTypeChanged, id=ID_POUDIALOGPOUTYPE) lbessard@64: lbessard@64: self.staticText3 = wx.StaticText(id=ID_POUDIALOGSTATICTEXT3, laurent@391: label=_('Language:'), name='staticText3', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@304: self.Language = wx.ComboBox(id=ID_POUDIALOGLANGUAGE, lbessard@64: name='Language', parent=self, pos=wx.Point(0, 0), lbessard@346: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@64: lbessard@64: self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) lbessard@64: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) lbessard@64: etisserant@0: self._init_sizers() etisserant@0: lbessard@163: def __init__(self, parent, pou_type = None): etisserant@0: self._init_ctrls(parent) etisserant@0: laurent@391: for option in GetPouTypes(): laurent@391: self.PouType.Append(_(option)) lbessard@163: if pou_type is not None: laurent@391: self.PouType.SetStringSelection(_(pou_type)) etisserant@0: self.RefreshLanguage() etisserant@0: lbessard@6: self.PouNames = [] lbessard@70: self.PouElementNames = [] lbessard@6: etisserant@0: def OnOK(self, event): etisserant@0: error = [] etisserant@0: pou_name = self.PouName.GetValue() etisserant@0: if pou_name == "": laurent@391: error.append(_("POU Name")) laurent@391: if self.PouType.GetSelection() == -1: laurent@391: error.append(_("POU Type")) laurent@391: if self.Language.GetSelection() == -1: laurent@391: error.append(_("Language")) etisserant@0: if len(error) > 0: etisserant@0: text = "" etisserant@0: for i, item in enumerate(error): etisserant@0: if i == 0: etisserant@0: text += item etisserant@0: elif i == len(error) - 1: laurent@391: text += _(" and %s")%item etisserant@0: else: laurent@391: text += _(", %s")%item laurent@391: message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() etisserant@0: elif not TestIdentifier(pou_name): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() etisserant@0: elif pou_name.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() etisserant@0: elif pou_name.upper() in self.PouNames: laurent@391: message = wx.MessageDialog(self, _("\"%s\" pou already exists!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() lbessard@70: elif pou_name.upper() in self.PouElementNames: b@427: message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%pou_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION) lbessard@70: result = message.ShowModal() lbessard@70: message.Destroy() lbessard@70: if result == wx.ID_YES: lbessard@70: self.EndModal(wx.ID_OK) etisserant@0: else: lbessard@64: self.EndModal(wx.ID_OK) etisserant@0: etisserant@0: def RefreshLanguage(self): laurent@391: selection = POU_LANGUAGES_DICT.get(self.Language.GetStringSelection(), "") etisserant@0: self.Language.Clear() laurent@391: for language in GetPouLanguages(): laurent@391: if language != "SFC" or POU_TYPES_DICT[self.PouType.GetStringSelection()] != "function": laurent@391: self.Language.Append(language) laurent@391: if self.Language.FindString(_(selection)) != wx.NOT_FOUND: laurent@391: self.Language.SetStringSelection(_(selection)) etisserant@0: etisserant@0: def OnTypeChanged(self, event): etisserant@0: self.RefreshLanguage() etisserant@0: event.Skip() etisserant@0: etisserant@0: def SetPouNames(self, pou_names): etisserant@0: self.PouNames = [pou_name.upper() for pou_name in pou_names] etisserant@0: lbessard@70: def SetPouElementNames(self, element_names): lbessard@70: self.PouElementNames = [element_name.upper() for element_name in element_names] lbessard@70: etisserant@0: def SetValues(self, values): etisserant@0: for item, value in values.items(): etisserant@0: if item == "pouName": etisserant@0: self.PouName.SetValue(value) etisserant@0: elif item == "pouType": laurent@391: self.PouType.SetStringSelection(_(value)) etisserant@0: elif item == "language": laurent@391: self.Language.SetStringSelection(_(POU_LANGUAGES_DICT)) etisserant@0: etisserant@0: def GetValues(self): etisserant@0: values = {} etisserant@0: values["pouName"] = self.PouName.GetValue() laurent@391: values["pouType"] = POU_TYPES_DICT[self.PouType.GetStringSelection()] laurent@391: values["language"] = POU_LANGUAGES_DICT[self.Language.GetStringSelection()] etisserant@0: return values etisserant@0: etisserant@0: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Create Pou Transition Dialog etisserant@0: #------------------------------------------------------------------------------- etisserant@0: lbessard@64: [ID_POUTRANSITIONDIALOG, ID_POUTRANSITIONDIALOGTRANSITIONNAME, lbessard@64: ID_POUTRANSITIONDIALOGLANGUAGE, ID_POUTRANSITIONDIALOGSTATICTEXT1, lbessard@64: ID_POUTRANSITIONDIALOGSTATICTEXT2, lbessard@64: ] = [wx.NewId() for _init_ctrls in range(5)] etisserant@0: laurent@391: def GetTransitionLanguages(): laurent@391: _ = lambda x : x laurent@391: return [_("IL"), _("ST"), _("LD"), _("FBD")] laurent@391: TRANSITION_LANGUAGES_DICT = dict([(_(language), language) for language in GetTransitionLanguages()]) laurent@391: etisserant@0: class PouTransitionDialog(wx.Dialog): lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: etisserant@0: def _init_coll_flexGridSizer1_Items(self, parent): lbessard@64: parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) lbessard@64: parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@64: lbessard@64: def _init_coll_flexGridSizer1_Growables(self, parent): lbessard@64: parent.AddGrowableCol(0) lbessard@64: parent.AddGrowableRow(0) lbessard@64: lbessard@64: def _init_coll_MainSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText1, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.TransitionName, 0, border=0, flag=wx.GROW) laurent@391: parent.AddWindow(self.staticText2, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.Language, 0, border=0, flag=wx.GROW) lbessard@64: lbessard@64: def _init_coll_MainSizer_Growables(self, parent): lbessard@64: parent.AddGrowableCol(1) lbessard@64: etisserant@0: def _init_sizers(self): lbessard@64: self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) laurent@391: self.MainSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15) etisserant@0: etisserant@0: self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) lbessard@64: self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) lbessard@64: self._init_coll_MainSizer_Items(self.MainSizer) lbessard@64: self._init_coll_MainSizer_Growables(self.MainSizer) etisserant@0: etisserant@0: self.SetSizer(self.flexGridSizer1) etisserant@0: etisserant@0: def _init_ctrls(self, prnt): lbessard@64: wx.Dialog.__init__(self, id=ID_POUTRANSITIONDIALOG, laurent@534: name='PouTransitionDialog', parent=prnt, etisserant@0: size=wx.Size(350, 200), style=wx.DEFAULT_DIALOG_STYLE, laurent@391: title=_('Create a new transition')) lbessard@45: self.SetClientSize(wx.Size(350, 160)) etisserant@0: lbessard@64: self.staticText1 = wx.StaticText(id=ID_POUTRANSITIONDIALOGSTATICTEXT1, laurent@391: label=_('Transition Name:'), name='staticText1', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@64: self.TransitionName = wx.TextCtrl(id=ID_POUTRANSITIONDIALOGTRANSITIONNAME, lbessard@64: name='TransitionName', parent=self, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@64: self.staticText2 = wx.StaticText(id=ID_POUTRANSITIONDIALOGSTATICTEXT2, laurent@391: label=_('Language:'), name='staticText2', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@304: self.Language = wx.ComboBox(id=ID_POUTRANSITIONDIALOGLANGUAGE, lbessard@64: name='Language', parent=self, pos=wx.Point(0, 0), lbessard@346: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@64: lbessard@64: self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) lbessard@64: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) lbessard@64: etisserant@0: self._init_sizers() etisserant@0: etisserant@0: def __init__(self, parent): etisserant@0: self._init_ctrls(parent) lbessard@45: laurent@391: for language in GetTransitionLanguages(): laurent@391: self.Language.Append(_(language)) lbessard@70: lbessard@70: self.PouNames = [] lbessard@70: self.PouElementNames = [] etisserant@0: etisserant@0: def OnOK(self, event): etisserant@0: error = [] lbessard@70: transition_name = self.TransitionName.GetValue() etisserant@0: if self.TransitionName.GetValue() == "": laurent@391: error.append(_("Transition Name")) laurent@391: if self.Language.GetSelection() == -1: laurent@391: error.append(_("Language")) etisserant@0: if len(error) > 0: etisserant@0: text = "" etisserant@0: for i, item in enumerate(error): etisserant@0: if i == 0: etisserant@0: text += item etisserant@0: elif i == len(error) - 1: laurent@391: text += _(" and %s")%item etisserant@0: else: laurent@391: text += _(", %s")%item laurent@391: message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() lbessard@70: elif not TestIdentifier(transition_name): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() lbessard@70: elif transition_name.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() lbessard@70: elif transition_name.upper() in self.PouNames: b@427: message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() lbessard@70: elif transition_name.upper() in self.PouElementNames: laurent@391: message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() etisserant@0: else: lbessard@64: self.EndModal(wx.ID_OK) lbessard@70: lbessard@70: def SetPouNames(self, pou_names): lbessard@70: self.PouNames = [pou_name.upper() for pou_name in pou_names] lbessard@70: lbessard@70: def SetPouElementNames(self, pou_names): lbessard@70: self.PouElementNames = [pou_name.upper() for pou_name in pou_names] lbessard@70: etisserant@0: def SetValues(self, values): etisserant@0: for item, value in values.items(): lbessard@45: if item == "transitionName": etisserant@0: self.TransitionName.SetValue(value) etisserant@0: elif item == "language": laurent@391: self.Language.SetSelection(_(value)) etisserant@0: etisserant@0: def GetValues(self): etisserant@0: values = {} etisserant@0: values["transitionName"] = self.TransitionName.GetValue() laurent@391: values["language"] = TRANSITION_LANGUAGES_DICT[self.Language.GetStringSelection()] etisserant@0: return values etisserant@0: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Create Pou Action Dialog etisserant@0: #------------------------------------------------------------------------------- etisserant@0: lbessard@64: [ID_POUACTIONDIALOG, ID_POUACTIONDIALOGACTIONNAME, lbessard@64: ID_POUACTIONDIALOGLANGUAGE, ID_POUACTIONDIALOGSTATICTEXT1, lbessard@64: ID_POUACTIONDIALOGSTATICTEXT2, lbessard@64: ] = [wx.NewId() for _init_ctrls in range(5)] etisserant@0: laurent@391: def GetActionLanguages(): laurent@391: _ = lambda x : x laurent@391: return [_("IL"), _("ST"), _("LD"), _("FBD")] laurent@391: ACTION_LANGUAGES_DICT = dict([(_(language), language) for language in GetActionLanguages()]) laurent@391: etisserant@0: class PouActionDialog(wx.Dialog): lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: etisserant@0: def _init_coll_flexGridSizer1_Items(self, parent): lbessard@64: parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) lbessard@64: parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@64: lbessard@64: def _init_coll_flexGridSizer1_Growables(self, parent): lbessard@64: parent.AddGrowableCol(0) lbessard@64: parent.AddGrowableRow(0) lbessard@64: lbessard@64: def _init_coll_MainSizer_Items(self, parent): laurent@391: parent.AddWindow(self.staticText1, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.ActionName, 0, border=0, flag=wx.GROW) laurent@391: parent.AddWindow(self.staticText2, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) lbessard@64: parent.AddWindow(self.Language, 0, border=0, flag=wx.GROW) lbessard@64: lbessard@64: def _init_coll_MainSizer_Growables(self, parent): lbessard@64: parent.AddGrowableCol(1) lbessard@64: etisserant@0: def _init_sizers(self): lbessard@64: self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) laurent@391: self.MainSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15) etisserant@0: etisserant@0: self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) lbessard@64: self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) lbessard@64: self._init_coll_MainSizer_Items(self.MainSizer) lbessard@64: self._init_coll_MainSizer_Growables(self.MainSizer) etisserant@0: etisserant@0: self.SetSizer(self.flexGridSizer1) etisserant@0: etisserant@0: def _init_ctrls(self, prnt): lbessard@64: wx.Dialog.__init__(self, id=ID_POUACTIONDIALOG, laurent@534: name='PouActionDialog', parent=prnt, lbessard@64: size=wx.Size(320, 200), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, laurent@391: title=_('Create a new action')) lbessard@45: self.SetClientSize(wx.Size(320, 160)) etisserant@0: lbessard@64: self.staticText1 = wx.StaticText(id=ID_POUACTIONDIALOGSTATICTEXT1, laurent@391: label=_('Action Name:'), name='staticText1', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@64: self.ActionName = wx.TextCtrl(id=ID_POUACTIONDIALOGACTIONNAME, lbessard@64: name='ActionName', parent=self, pos=wx.Point(0, 0), lbessard@64: size=wx.Size(0, 24), style=0) lbessard@64: lbessard@64: self.staticText2 = wx.StaticText(id=ID_POUACTIONDIALOGSTATICTEXT2, laurent@391: label=_('Language:'), name='staticText2', parent=self, laurent@391: pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) lbessard@64: lbessard@304: self.Language = wx.ComboBox(id=ID_POUACTIONDIALOGLANGUAGE, lbessard@64: name='Language', parent=self, pos=wx.Point(0, 0), lbessard@346: size=wx.Size(0, 28), style=wx.CB_READONLY) lbessard@64: lbessard@64: self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) lbessard@64: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) lbessard@64: etisserant@0: self._init_sizers() etisserant@0: etisserant@0: def __init__(self, parent): etisserant@0: self._init_ctrls(parent) lbessard@45: laurent@391: for option in GetActionLanguages(): laurent@391: self.Language.Append(_(option)) etisserant@0: lbessard@70: self.PouNames = [] lbessard@70: self.PouElementNames = [] lbessard@70: etisserant@0: def OnOK(self, event): etisserant@0: error = [] lbessard@70: action_name = self.ActionName.GetValue() lbessard@70: if action_name == "": laurent@391: error.append(_("Action Name")) laurent@391: if self.Language.GetSelection() == -1: laurent@391: error.append(_("Language")) etisserant@0: if len(error) > 0: etisserant@0: text = "" etisserant@0: for i, item in enumerate(error): etisserant@0: if i == 0: etisserant@0: text += item etisserant@0: elif i == len(error) - 1: laurent@391: text += _(" and %s")%item etisserant@0: else: laurent@391: text += _(", %s")%item laurent@391: message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() lbessard@70: elif not TestIdentifier(action_name): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() lbessard@70: elif action_name.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() lbessard@70: elif action_name.upper() in self.PouNames: b@427: message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() lbessard@70: elif action_name.upper() in self.PouElementNames: laurent@391: message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@70: message.ShowModal() lbessard@70: message.Destroy() etisserant@0: else: lbessard@64: self.EndModal(wx.ID_OK) lbessard@70: lbessard@70: def SetPouNames(self, pou_names): lbessard@70: self.PouNames = [pou_name.upper() for pou_name in pou_names] lbessard@70: lbessard@70: def SetPouElementNames(self, element_names): lbessard@70: self.PouElementNames = [element_name.upper() for element_name in element_names] lbessard@70: etisserant@0: def SetValues(self, values): etisserant@0: for item, value in values.items(): lbessard@45: if item == "actionName": etisserant@0: self.ActionName.SetValue(value) etisserant@0: elif item == "language": laurent@391: self.Language.SetStringSelection(_(value)) etisserant@0: etisserant@0: def GetValues(self): etisserant@0: values = {} etisserant@0: values["actionName"] = self.ActionName.GetValue() laurent@391: values["language"] = ACTION_LANGUAGES_DICT[self.Language.GetStringSelection()] etisserant@0: return values etisserant@0: etisserant@0: #------------------------------------------------------------------------------- lbessard@80: # Configuration Name Dialog lbessard@80: #------------------------------------------------------------------------------- lbessard@80: lbessard@80: class ConfigurationNameDialog(wx.TextEntryDialog): lbessard@80: lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: laurent@391: def __init__(self, parent, message, caption = _("Please enter configuration name"), defaultValue = "", lbessard@80: style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition): lbessard@80: wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) lbessard@80: lbessard@80: self.PouNames = [] lbessard@80: self.PouElementNames = [] lbessard@80: lbessard@144: if wx.VERSION >= (2, 8, 0): lbessard@144: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId()) lbessard@144: elif wx.VERSION >= (2, 6, 0): lbessard@144: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId()) lbessard@144: else: lbessard@144: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) lbessard@144: lbessard@80: def OnOK(self, event): lbessard@80: config_name = self.GetSizer().GetItem(1).GetWindow().GetValue() lbessard@80: if config_name == "": laurent@391: message = wx.MessageDialog(self, _("You must type a name!"), _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif not TestIdentifier(config_name): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif config_name.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif config_name.upper() in self.PouNames: b@427: message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif config_name.upper() in self.PouElementNames: b@427: message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%config_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION) lbessard@80: result = message.ShowModal() lbessard@80: message.Destroy() lbessard@80: if result == wx.ID_YES: lbessard@80: self.EndModal(wx.ID_OK) lbessard@80: else: lbessard@80: self.EndModal(wx.ID_OK) lbessard@80: lbessard@80: def SetPouNames(self, pou_names): lbessard@80: self.PouNames = [pou_name.upper() for pou_name in pou_names] lbessard@80: lbessard@80: def SetPouElementNames(self, pou_names): lbessard@80: self.PouElementNames = [pou_name.upper() for pou_name in pou_names] lbessard@80: lbessard@80: def GetValue(self): lbessard@80: return self.GetSizer().GetItem(1).GetWindow().GetValue() lbessard@80: lbessard@80: #------------------------------------------------------------------------------- lbessard@80: # Resource Name Dialog lbessard@80: #------------------------------------------------------------------------------- lbessard@80: lbessard@80: class ResourceNameDialog(wx.TextEntryDialog): lbessard@80: lbessard@114: if wx.VERSION < (2, 6, 0): lbessard@114: def Bind(self, event, function, id = None): lbessard@114: if id is not None: lbessard@114: event(self, id, function) lbessard@114: else: lbessard@114: event(self, function) lbessard@114: laurent@391: def __init__(self, parent, message, caption = _("Please enter resource name"), defaultValue = "", lbessard@80: style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition): lbessard@80: wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) lbessard@80: lbessard@80: self.PouNames = [] lbessard@80: self.PouElementNames = [] lbessard@80: lbessard@144: if wx.VERSION >= (2, 8, 0): lbessard@144: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId()) lbessard@144: elif wx.VERSION >= (2, 6, 0): lbessard@144: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId()) lbessard@144: else: lbessard@144: self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) lbessard@144: lbessard@80: def OnOK(self, event): lbessard@80: resource_name = self.GetSizer().GetItem(1).GetWindow().GetValue() lbessard@80: if resource_name == "": laurent@391: message = wx.MessageDialog(self, _("You must type a name!"), _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif not TestIdentifier(resource_name): laurent@391: message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif resource_name.upper() in IEC_KEYWORDS: laurent@391: message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif resource_name.upper() in self.PouNames: b@427: message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@80: message.ShowModal() lbessard@80: message.Destroy() lbessard@80: elif resource_name.upper() in self.PouElementNames: b@427: message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%resource_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION) lbessard@80: result = message.ShowModal() lbessard@80: message.Destroy() lbessard@80: if result == wx.ID_YES: lbessard@80: self.EndModal(wx.ID_OK) lbessard@80: else: lbessard@80: self.EndModal(wx.ID_OK) lbessard@80: lbessard@80: def SetPouNames(self, pou_names): lbessard@80: self.PouNames = [pou_name.upper() for pou_name in pou_names] lbessard@80: lbessard@80: def SetPouElementNames(self, pou_names): lbessard@80: self.PouElementNames = [pou_name.upper() for pou_name in pou_names] lbessard@80: lbessard@80: def GetValue(self): lbessard@80: return self.GetSizer().GetItem(1).GetWindow().GetValue() lbessard@80: lbessard@80: #------------------------------------------------------------------------------- lbessard@121: # Variables Editor Panel lbessard@121: #------------------------------------------------------------------------------- lbessard@121: laurent@566: def PouTagname(tagname): laurent@566: words = tagname.split("::") laurent@566: if words[0] in ["T", "A"]: laurent@566: return "P::%s" % words[1] laurent@566: return tagname laurent@566: lbessard@121: class VariablePanelIndexer(wx.Panel): lbessard@121: lbessard@121: def _init_sizers(self): lbessard@121: self.MainSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@121: lbessard@121: self.SetSizer(self.MainSizer) lbessard@121: lbessard@121: def _init_ctrls(self, prnt): lbessard@121: wx.Panel.__init__(self, id=wx.NewId(), lbessard@121: name='VariablePanelIndexer', parent=prnt, pos=wx.Point(0, 0), lbessard@121: size=wx.Size(0, 300), style=wx.TAB_TRAVERSAL) lbessard@121: lbessard@121: self._init_sizers() lbessard@121: laurent@407: def __init__(self, parent, window): lbessard@121: self._init_ctrls(parent) lbessard@121: lbessard@145: self.ParentWindow = window lbessard@121: lbessard@121: self.VariablePanelList = {} lbessard@121: self.CurrentPanel = None lbessard@121: lbessard@121: def AddVariablePanel(self, tagname, element_type): laurent@566: tagname = PouTagname(tagname) laurent@566: panel, users = self.VariablePanelList.get(tagname, (None, 0)) laurent@566: if panel is None: laurent@566: panel = VariablePanel(self, self.ParentWindow, self.ParentWindow.Controler, element_type) laurent@566: panel.SetTagName(tagname) laurent@566: panel.Hide() laurent@566: panel.RefreshView() laurent@566: self.MainSizer.AddWindow(panel, 1, border=0, flag=wx.GROW) laurent@566: self.VariablePanelList[tagname] = (panel, users + 1) lbessard@121: lbessard@121: def RemoveVariablePanel(self, tagname): laurent@566: tagname = PouTagname(tagname) laurent@566: panel, users = self.VariablePanelList.pop(tagname, (None, 0)) laurent@566: if panel is not None: laurent@566: if users > 1: laurent@566: self.VariablePanelList[tagname] = (panel, users - 1) laurent@566: else: laurent@566: self.MainSizer.Remove(panel) laurent@566: panel.Destroy() laurent@566: if self.CurrentPanel == tagname: laurent@566: self.CurrentPanel = None laurent@566: laurent@566: def RemoveAllPanels(self): laurent@566: for panel, users in self.VariablePanelList.itervalues(): lbessard@121: self.MainSizer.Remove(panel) lbessard@294: panel.Destroy() laurent@566: self.VariablePanelList = {} laurent@566: self.CurrentPanel = None lbessard@121: lbessard@121: def UpdateVariablePanelTagName(self, old_tagname, new_tagname): laurent@566: old_tagname = PouTagname(old_tagname) laurent@566: new_tagname = PouTagname(new_tagname) laurent@566: if old_tagname in self.VariablePanelList and old_tagname != new_tagname: lbessard@121: self.VariablePanelList[new_tagname] = self.VariablePanelList.pop(old_tagname) lbessard@121: if self.CurrentPanel == old_tagname: lbessard@121: self.CurrentPanel = new_tagname lbessard@121: lbessard@121: def ChangeVariablePanel(self, tagname): laurent@566: tagname = PouTagname(tagname) laurent@566: panel, users = self.VariablePanelList.get(tagname, (None, 0)) laurent@566: if panel is None: lbessard@121: if self.CurrentPanel is not None: laurent@566: self.VariablePanelList[self.CurrentPanel][0].Hide() lbessard@125: self.CurrentPanel = None lbessard@121: self.MainSizer.Layout() laurent@566: elif tagname != self.CurrentPanel: laurent@566: if self.CurrentPanel is not None: laurent@566: self.VariablePanelList[self.CurrentPanel][0].Hide() laurent@566: self.CurrentPanel = tagname laurent@566: panel.RefreshView() laurent@566: panel.Show() laurent@566: self.MainSizer.Layout() lbessard@121: lbessard@121: def RefreshVariablePanel(self, tagname): laurent@566: panel, users = self.VariablePanelList.get(PouTagname(tagname), (None, 0)) laurent@566: if panel is not None: laurent@566: panel.RefreshView() laurent@566: laurent@566: def AddVariableHighlight(self, infos, highlight_type): lbessard@231: self.ChangeVariablePanel(infos[0]) lbessard@231: if self.CurrentPanel is not None: laurent@566: self.VariablePanelList[self.CurrentPanel][0].AddVariableHighlight(infos[2:], highlight_type) laurent@566: laurent@566: def ClearHighlights(self, highlight_type=None): laurent@566: for panel, users in self.VariablePanelList.values(): laurent@566: panel.ClearHighlights(highlight_type) lbessard@231: lbessard@121: #------------------------------------------------------------------------------- laurent@390: # Debug Variables Panel lbessard@341: #------------------------------------------------------------------------------- lbessard@341: laurent@391: def GetDebugVariablesTableColnames(): laurent@391: _ = lambda x : x laurent@391: return [_("Variable"), _("Value")] lbessard@341: greg@361: class VariableTableItem(DebugDataConsumer): lbessard@341: lbessard@341: def __init__(self, parent, variable, value): greg@361: DebugDataConsumer.__init__(self) lbessard@341: self.Parent = parent lbessard@341: self.Variable = variable lbessard@341: self.Value = value lbessard@341: lbessard@341: def __del__(self): lbessard@341: self.Parent = None lbessard@341: lbessard@341: def SetVariable(self, variable): lbessard@341: if self.Parent and self.Variable != variable: lbessard@341: self.Variable = variable lbessard@341: self.Parent.RefreshGrid() lbessard@341: lbessard@341: def GetVariable(self): lbessard@341: return self.Variable lbessard@341: laurent@478: def SetForced(self, forced): laurent@478: if self.Forced != forced: laurent@478: self.Forced = forced laurent@478: self.Parent.HasNewData = True laurent@478: lbessard@341: def SetValue(self, value): greg@361: if self.Value != value: lbessard@341: self.Value = value greg@372: self.Parent.HasNewData = True greg@372: lbessard@341: def GetValue(self): greg@361: return self.Value lbessard@341: lbessard@341: class DebugVariableTable(wx.grid.PyGridTableBase): lbessard@341: lbessard@341: """ lbessard@341: A custom wx.grid.Grid Table using user supplied data lbessard@341: """ lbessard@341: def __init__(self, parent, data, colnames): lbessard@341: # The base class must be initialized *first* lbessard@341: wx.grid.PyGridTableBase.__init__(self) lbessard@341: self.data = data lbessard@341: self.colnames = colnames lbessard@341: self.Parent = parent lbessard@341: # XXX lbessard@341: # we need to store the row length and collength to lbessard@341: # see if the table has changed size lbessard@341: self._rows = self.GetNumberRows() lbessard@341: self._cols = self.GetNumberCols() lbessard@341: lbessard@341: def GetNumberCols(self): lbessard@341: return len(self.colnames) lbessard@341: lbessard@341: def GetNumberRows(self): lbessard@341: return len(self.data) lbessard@341: laurent@391: def GetColLabelValue(self, col, translate=True): lbessard@341: if col < len(self.colnames): laurent@391: if translate: laurent@391: return _(self.colnames[col]) lbessard@341: return self.colnames[col] lbessard@341: laurent@391: def GetRowLabelValues(self, row, translate=True): lbessard@341: return row lbessard@341: lbessard@341: def GetValue(self, row, col): lbessard@341: if row < self.GetNumberRows(): laurent@391: return self.GetValueByName(row, self.GetColLabelValue(col, False)) lbessard@341: return "" lbessard@341: lbessard@341: def SetValue(self, row, col, value): lbessard@341: if col < len(self.colnames): laurent@391: self.SetValueByName(row, self.GetColLabelValue(col, False), value) lbessard@341: lbessard@341: def GetValueByName(self, row, colname): lbessard@341: if row < self.GetNumberRows(): lbessard@341: if colname == "Variable": lbessard@341: return self.data[row].GetVariable() lbessard@341: elif colname == "Value": lbessard@341: return self.data[row].GetValue() lbessard@341: return "" lbessard@341: lbessard@341: def SetValueByName(self, row, colname, value): lbessard@341: if row < self.GetNumberRows(): lbessard@341: if colname == "Variable": lbessard@341: self.data[row].SetVariable(value) lbessard@341: elif colname == "Value": lbessard@341: self.data[row].SetValue(value) lbessard@341: laurent@472: def IsForced(self, row): laurent@472: if row < self.GetNumberRows(): laurent@472: return self.data[row].IsForced() laurent@472: return False laurent@472: lbessard@341: def ResetView(self, grid): lbessard@341: """ lbessard@341: (wx.grid.Grid) -> Reset the grid view. Call this to lbessard@341: update the grid if rows and columns have been added or deleted lbessard@341: """ lbessard@341: grid.BeginBatch() lbessard@341: for current, new, delmsg, addmsg in [ lbessard@341: (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED), lbessard@341: (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED), lbessard@341: ]: lbessard@341: if new < current: lbessard@341: msg = wx.grid.GridTableMessage(self,delmsg,new,current-new) lbessard@341: grid.ProcessTableMessage(msg) lbessard@341: elif new > current: lbessard@341: msg = wx.grid.GridTableMessage(self,addmsg,new-current) lbessard@341: grid.ProcessTableMessage(msg) lbessard@341: self.UpdateValues(grid) lbessard@341: grid.EndBatch() lbessard@341: lbessard@341: self._rows = self.GetNumberRows() lbessard@341: self._cols = self.GetNumberCols() lbessard@341: # update the column rendering scheme lbessard@341: self._updateColAttrs(grid) lbessard@341: lbessard@341: # update the scrollbars and the displayed part of the grid lbessard@341: grid.AdjustScrollbars() lbessard@341: grid.ForceRefresh() lbessard@341: lbessard@341: def UpdateValues(self, grid): lbessard@341: """Update all displayed values""" lbessard@341: # This sends an event to the grid table to update all of the values lbessard@341: msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES) lbessard@341: grid.ProcessTableMessage(msg) lbessard@341: lbessard@341: def _updateColAttrs(self, grid): lbessard@341: """ lbessard@341: wx.grid.Grid -> update the column attributes to add the lbessard@341: appropriate renderer given the column name. lbessard@341: lbessard@341: Otherwise default to the default renderer. lbessard@341: """ lbessard@341: lbessard@341: for row in range(self.GetNumberRows()): lbessard@341: for col in range(self.GetNumberCols()): laurent@473: if self.GetColLabelValue(col, False) == "Value": laurent@473: if self.IsForced(row): laurent@478: grid.SetCellTextColour(row, col, wx.BLUE) laurent@473: else: laurent@474: grid.SetCellTextColour(row, col, wx.BLACK) lbessard@341: grid.SetReadOnly(row, col, True) lbessard@341: lbessard@341: def SetData(self, data): lbessard@341: self.data = data lbessard@341: lbessard@341: def GetData(self): lbessard@341: return self.data lbessard@341: lbessard@341: def AppendItem(self, data): lbessard@341: self.data.append(data) lbessard@341: lbessard@341: def InsertItem(self, idx, data): lbessard@341: self.data.insert(idx, data) lbessard@341: lbessard@341: def RemoveItem(self, idx): lbessard@341: self.data.pop(idx) lbessard@341: lbessard@341: def MoveItem(self, idx, new_idx): lbessard@341: self.data.insert(new_idx, self.data.pop(idx)) lbessard@341: lbessard@341: def GetItem(self, idx): lbessard@341: return self.data[idx] lbessard@341: lbessard@341: def Empty(self): lbessard@341: self.data = [] lbessard@341: lbessard@341: class DebugVariableDropTarget(wx.TextDropTarget): lbessard@341: lbessard@341: def __init__(self, parent): lbessard@341: wx.TextDropTarget.__init__(self) lbessard@341: self.ParentWindow = parent lbessard@341: lbessard@341: def OnDropText(self, x, y, data): lbessard@341: x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y) lbessard@341: row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize()) lbessard@341: if row == wx.NOT_FOUND: lbessard@341: row = self.ParentWindow.Table.GetNumberRows() lbessard@341: message = None lbessard@341: try: lbessard@341: values = eval(data) lbessard@341: except: laurent@391: message = _("Invalid value \"%s\" for debug variable")%data lbessard@341: values = None lbessard@341: if not isinstance(values, TupleType): laurent@391: message = _("Invalid value \"%s\" for debug variable")%data lbessard@341: values = None lbessard@341: if values is not None and values[1] == "debug": laurent@479: self.ParentWindow.InsertValue(values[0], row) lbessard@341: if message is not None: lbessard@341: wx.CallAfter(self.ShowMessage, message) lbessard@341: lbessard@341: def ShowMessage(self, message): laurent@391: message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) lbessard@341: message.ShowModal() lbessard@341: message.Destroy() lbessard@341: lbessard@341: [ID_DEBUGVARIABLEPANEL, ID_DEBUGVARIABLEPANELVARIABLESGRID, lbessard@341: ID_DEBUGVARIABLEPANELUPBUTTON, ID_DEBUGVARIABLEPANELDOWNBUTTON, greg@361: ID_DEBUGVARIABLEPANELDELETEBUTTON, lbessard@341: ] = [wx.NewId() for _init_ctrls in range(5)] lbessard@341: greg@361: class DebugVariablePanel(wx.Panel, DebugViewer): lbessard@341: lbessard@341: if wx.VERSION < (2, 6, 0): lbessard@341: def Bind(self, event, function, id = None): lbessard@341: if id is not None: lbessard@341: event(self, id, function) lbessard@341: else: lbessard@341: event(self, function) lbessard@341: lbessard@341: def _init_coll_MainSizer_Items(self, parent): lbessard@341: parent.AddSizer(self.ButtonPanelSizer, 0, border=5, flag=wx.ALIGN_RIGHT|wx.ALL) lbessard@341: parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW) lbessard@341: lbessard@341: def _init_coll_MainSizer_Growables(self, parent): lbessard@341: parent.AddGrowableCol(0) lbessard@341: parent.AddGrowableRow(1) lbessard@341: lbessard@341: def _init_coll_ButtonPanelSizer_Items(self, parent): lbessard@341: parent.AddWindow(self.UpButton, 0, border=5, flag=wx.RIGHT) lbessard@341: parent.AddWindow(self.DownButton, 0, border=5, flag=wx.RIGHT) lbessard@341: parent.AddWindow(self.DeleteButton, 0, border=0, flag=0) lbessard@341: lbessard@341: def _init_sizers(self): lbessard@341: self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0) lbessard@341: self.ButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@341: lbessard@341: self._init_coll_MainSizer_Items(self.MainSizer) lbessard@341: self._init_coll_MainSizer_Growables(self.MainSizer) lbessard@341: self._init_coll_ButtonPanelSizer_Items(self.ButtonPanelSizer) lbessard@341: lbessard@341: self.SetSizer(self.MainSizer) lbessard@341: lbessard@341: def _init_ctrls(self, prnt): lbessard@341: wx.Panel.__init__(self, id=ID_DEBUGVARIABLEPANEL, lbessard@341: name='DebugVariablePanel', parent=prnt, pos=wx.Point(0, 0), lbessard@341: size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) lbessard@341: lbessard@341: self.VariablesGrid = wx.grid.Grid(id=ID_DEBUGVARIABLEPANELVARIABLESGRID, lbessard@341: name='VariablesGrid', parent=self, pos=wx.Point(0, 0), lbessard@341: size=wx.Size(0, 150), style=wx.VSCROLL) lbessard@341: self.VariablesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, lbessard@341: 'Sans')) lbessard@341: self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, lbessard@341: False, 'Sans')) lbessard@341: self.VariablesGrid.SetSelectionBackground(wx.WHITE) lbessard@341: self.VariablesGrid.SetSelectionForeground(wx.BLACK) lbessard@341: self.VariablesGrid.SetDropTarget(DebugVariableDropTarget(self)) laurent@497: if wx.VERSION >= (2, 6, 0): laurent@497: self.VariablesGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnVariablesGridCellSelect) laurent@497: self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.OnVariablesGridCellRightClick) laurent@497: else: laurent@497: wx.grid.EVT_GRID_SELECT_CELL(self.VariablesGrid, self.OnVariablesGridCellSelect) laurent@497: wx.grid.EVT_GRID_CELL_RIGHT_CLICK(self.VariablesGrid, self.OnVariablesGridCellRightClick) lbessard@341: lbessard@341: self.UpButton = wx.Button(id=ID_DEBUGVARIABLEPANELUPBUTTON, label='^', lbessard@341: name='UpButton', parent=self, pos=wx.Point(0, 0), lbessard@341: size=wx.Size(32, 32), style=0) lbessard@341: self.Bind(wx.EVT_BUTTON, self.OnUpButton, id=ID_DEBUGVARIABLEPANELUPBUTTON) lbessard@341: lbessard@341: self.DownButton = wx.Button(id=ID_DEBUGVARIABLEPANELDOWNBUTTON, label='v', lbessard@341: name='DownButton', parent=self, pos=wx.Point(0, 0), lbessard@341: size=wx.Size(32, 32), style=0) lbessard@341: self.Bind(wx.EVT_BUTTON, self.OnDownButton, id=ID_DEBUGVARIABLEPANELDOWNBUTTON) lbessard@341: laurent@391: self.DeleteButton = wx.Button(id=ID_DEBUGVARIABLEPANELDELETEBUTTON, label=_('Delete'), lbessard@341: name='DeleteButton', parent=self, pos=wx.Point(0, 0), laurent@407: size=wx.DefaultSize, style=0) lbessard@341: self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DEBUGVARIABLEPANELDELETEBUTTON) lbessard@341: lbessard@341: self._init_sizers() lbessard@341: b@415: def __init__(self, parent, producer): lbessard@341: self._init_ctrls(parent) b@415: DebugViewer.__init__(self, producer, True) greg@372: self.HasNewData = False lbessard@341: laurent@391: self.Table = DebugVariableTable(self, [], GetDebugVariablesTableColnames()) lbessard@341: self.VariablesGrid.SetTable(self.Table) lbessard@341: self.VariablesGrid.SetRowLabelSize(0) lbessard@341: lbessard@341: for col in range(self.Table.GetNumberCols()): lbessard@341: attr = wx.grid.GridCellAttr() lbessard@341: attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTER) lbessard@341: self.VariablesGrid.SetColAttr(col, attr) lbessard@341: self.VariablesGrid.SetColSize(col, 100) greg@361: lbessard@341: self.Table.ResetView(self.VariablesGrid) laurent@497: self.RefreshButtons() lbessard@341: greg@361: def RefreshNewData(self): greg@372: if self.HasNewData: greg@372: self.HasNewData = False greg@372: self.RefreshGrid() greg@372: DebugViewer.RefreshNewData(self) lbessard@341: lbessard@341: def RefreshGrid(self): greg@361: self.Freeze() lbessard@341: self.Table.ResetView(self.VariablesGrid) greg@361: self.Thaw() lbessard@341: laurent@407: def ResetGrid(self): laurent@407: self.DeleteDataConsumers() laurent@407: self.Table.Empty() laurent@407: self.Freeze() laurent@407: self.Table.ResetView(self.VariablesGrid) laurent@407: self.Thaw() laurent@407: laurent@479: def GetForceVariableMenuFunction(self, iec_path, item): laurent@472: iec_type = self.GetDataType(iec_path) laurent@472: def ForceVariableFunction(event): laurent@472: if iec_type is not None: laurent@479: dialog = ForceVariableDialog(self, iec_type, str(item.GetValue())) laurent@472: if dialog.ShowModal() == wx.ID_OK: laurent@472: self.ForceDataValue(iec_path, dialog.GetValue()) laurent@472: return ForceVariableFunction laurent@472: laurent@472: def GetReleaseVariableMenuFunction(self, iec_path): laurent@472: def ReleaseVariableFunction(event): laurent@472: self.ReleaseDataValue(iec_path) laurent@472: return ReleaseVariableFunction laurent@472: laurent@497: def OnVariablesGridCellSelect(self, event): laurent@497: wx.CallAfter(self.RefreshButtons) laurent@497: event.Skip() laurent@497: laurent@497: def OnVariablesGridCellRightClick(self, event): laurent@472: row, col = event.GetRow(), event.GetCol() laurent@472: if self.Table.GetColLabelValue(col, False) == "Value": laurent@472: iec_path = self.Table.GetValueByName(row, "Variable").upper() laurent@472: laurent@472: menu = wx.Menu(title='') laurent@472: new_id = wx.NewId() laurent@472: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Force value")) laurent@479: self.Bind(wx.EVT_MENU, self.GetForceVariableMenuFunction(iec_path.upper(), self.Table.GetItem(row)), id=new_id) laurent@472: new_id = wx.NewId() laurent@472: AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Release value")) laurent@472: self.Bind(wx.EVT_MENU, self.GetReleaseVariableMenuFunction(iec_path.upper()), id=new_id) laurent@472: if self.Table.IsForced(row): laurent@472: menu.Enable(new_id, True) laurent@472: else: laurent@472: menu.Enable(new_id, False) laurent@472: self.PopupMenu(menu) laurent@472: event.Skip() laurent@472: laurent@497: def RefreshButtons(self): laurent@497: if getattr(self, "Table", None): laurent@497: table_length = len(self.Table.data) laurent@497: row = 0 laurent@497: if table_length > 0: laurent@497: row = self.VariablesGrid.GetGridCursorRow() laurent@497: self.DeleteButton.Enable(table_length > 0) laurent@497: self.UpButton.Enable(table_length > 0 and row > 0) laurent@497: self.DownButton.Enable(table_length > 0 and row < table_length - 1) laurent@497: lbessard@341: def OnDeleteButton(self, event): lbessard@341: idx = self.VariablesGrid.GetGridCursorRow() laurent@481: if idx >= 0: laurent@481: item = self.Table.GetItem(idx) laurent@481: self.RemoveDataConsumer(item) laurent@481: self.Table.RemoveItem(idx) laurent@481: self.RefreshGrid() laurent@497: self.RefreshButtons() lbessard@341: event.Skip() lbessard@341: lbessard@341: def OnUpButton(self, event): lbessard@341: self.MoveValue(self.VariablesGrid.GetGridCursorRow(), -1) lbessard@341: event.Skip() lbessard@341: lbessard@341: def OnDownButton(self, event): lbessard@341: self.MoveValue(self.VariablesGrid.GetGridCursorRow(), 1) lbessard@341: event.Skip() lbessard@341: laurent@479: def InsertValue(self, iec_path, idx = None): laurent@479: if idx is None: laurent@479: idx = self.Table.GetNumberRows() lbessard@341: for item in self.Table.GetData(): lbessard@341: if iec_path == item.GetVariable(): lbessard@341: return lbessard@341: item = VariableTableItem(self, iec_path, "") greg@361: result = self.AddDataConsumer(iec_path.upper(), item) lbessard@341: if result is not None: lbessard@341: self.Table.InsertItem(idx, item) lbessard@341: self.RefreshGrid() laurent@497: self.RefreshButtons() lbessard@341: lbessard@341: def MoveValue(self, idx, move): lbessard@341: new_idx = max(0, min(idx + move, self.Table.GetNumberRows() - 1)) lbessard@341: if new_idx != idx: lbessard@341: self.Table.MoveItem(idx, new_idx) lbessard@341: self.RefreshGrid() lbessard@341: self.VariablesGrid.SetGridCursor(new_idx, self.VariablesGrid.GetGridCursorCol()) laurent@497: self.RefreshButtons() laurent@497: lbessard@341: #------------------------------------------------------------------------------- lbessard@341: # Viewer Printout lbessard@341: #------------------------------------------------------------------------------- lbessard@341: lbessard@213: UPPER_DIV = lambda x, y: (x / y) + {True : 0, False : 1}[(x % y) == 0] lbessard@213: lbessard@213: class GraphicPrintout(wx.Printout): lbessard@213: def __init__(self, viewer, page_size, margins, preview = False): lbessard@213: wx.Printout.__init__(self) lbessard@213: self.Viewer = viewer lbessard@213: self.PageSize = page_size lbessard@221: if self.PageSize[0] == 0 or self.PageSize[1] == 0: lbessard@221: self.PageSize = (1050, 1485) lbessard@213: self.Preview = preview lbessard@213: self.Margins = margins lbessard@221: self.FontSize = 5 lbessard@221: self.TextMargin = 3 lbessard@213: lbessard@213: maxx, maxy = viewer.GetMaxSize() lbessard@221: self.PageGrid = (UPPER_DIV(maxx, self.PageSize[0]), lbessard@221: UPPER_DIV(maxy, self.PageSize[1])) lbessard@213: lbessard@213: def GetPageNumber(self): lbessard@213: return self.PageGrid[0] * self.PageGrid[1] lbessard@213: lbessard@213: def HasPage(self, page): lbessard@213: return page <= self.GetPageNumber() lbessard@213: lbessard@213: def GetPageInfo(self): lbessard@213: page_number = self.GetPageNumber() lbessard@213: return (1, page_number, 1, page_number) lbessard@213: lbessard@213: def OnBeginDocument(self, startPage, endPage): lbessard@213: dc = self.GetDC() lbessard@213: if not self.Preview and isinstance(dc, wx.PostScriptDC): lbessard@213: dc.SetResolution(720) lbessard@213: super(GraphicPrintout, self).OnBeginDocument(startPage, endPage) lbessard@213: lbessard@213: def OnPrintPage(self, page): lbessard@213: dc = self.GetDC() lbessard@221: dc.SetUserScale(1.0, 1.0) lbessard@221: dc.SetDeviceOrigin(0, 0) lbessard@213: dc.printing = not self.Preview lbessard@213: lbessard@213: # Get the size of the DC in pixels lbessard@213: ppiPrinterX, ppiPrinterY = self.GetPPIPrinter() lbessard@213: ppiScreenX, ppiScreenY = self.GetPPIScreen() lbessard@213: pw, ph = self.GetPageSizePixels() lbessard@213: dw, dh = dc.GetSizeTuple() lbessard@213: Xscale = (float(dw) * float(ppiPrinterX)) / (float(pw) * 25.4) lbessard@213: Yscale = (float(dh) * float(ppiPrinterY)) / (float(ph) * 25.4) lbessard@213: lbessard@221: fontsize = self.FontSize * Yscale lbessard@221: text_margin = self.TextMargin * Yscale lbessard@221: lbessard@213: margin_left = self.Margins[0].x * Xscale lbessard@213: margin_top = self.Margins[0].y * Yscale lbessard@213: area_width = dw - self.Margins[1].x * Xscale - margin_left lbessard@213: area_height = dh - self.Margins[1].y * Yscale - margin_top lbessard@213: laurent@563: dc.SetPen(MiterPen(wx.BLACK)) lbessard@213: dc.SetBrush(wx.TRANSPARENT_BRUSH) lbessard@213: dc.DrawRectangle(margin_left, margin_top, area_width, area_height) lbessard@213: lbessard@221: dc.SetFont(wx.Font(fontsize, wx.DEFAULT, wx.NORMAL, wx.NORMAL)) lbessard@213: dc.SetTextForeground(wx.BLACK) lbessard@213: block_name = " - ".join(self.Viewer.GetTagName().split("::")[1:]) lbessard@213: text_width, text_height = dc.GetTextExtent(block_name) lbessard@213: dc.DrawText(block_name, margin_left, margin_top - text_height - self.TextMargin) laurent@391: dc.DrawText(_("Page: %d") % page, margin_left, margin_top + area_height + self.TextMargin) lbessard@213: lbessard@213: # Calculate the position on the DC for centering the graphic lbessard@213: posX = area_width * ((page - 1) % self.PageGrid[0]) lbessard@213: posY = area_height * ((page - 1) / self.PageGrid[0]) lbessard@213: lbessard@213: scaleX = float(area_width) / float(self.PageSize[0]) lbessard@213: scaleY = float(area_height) / float(self.PageSize[1]) lbessard@213: scale = min(scaleX, scaleY) lbessard@213: lbessard@213: # Set the scale and origin lbessard@213: dc.SetDeviceOrigin(-posX + margin_left, -posY + margin_top) lbessard@221: dc.SetClippingRegion(posX, posY, self.PageSize[0] * scale, self.PageSize[1] * scale) lbessard@213: dc.SetUserScale(scale, scale) lbessard@213: lbessard@213: #------------------------------------------- lbessard@213: lbessard@213: self.Viewer.DoDrawing(dc, True) lbessard@213: lbessard@213: return True lbessard@213: etisserant@0: #------------------------------------------------------------------------------- etisserant@0: # Exception Handler etisserant@0: #------------------------------------------------------------------------------- etisserant@0: etisserant@0: Max_Traceback_List_Size = 20 etisserant@0: etisserant@0: def Display_Exception_Dialog(e_type,e_value,e_tb): etisserant@0: trcbck_lst = [] etisserant@0: for i,line in enumerate(traceback.extract_tb(e_tb)): laurent@391: trcbck = " " + str(i+1) + _(". ") etisserant@0: if line[0].find(os.getcwd()) == -1: laurent@391: trcbck += _("file : ") + str(line[0]) + _(", ") laurent@391: else: laurent@391: trcbck += _("file : ") + str(line[0][len(os.getcwd()):]) + _(", ") laurent@391: trcbck += _("line : ") + str(line[1]) + _(", ") + _("function : ") + str(line[2]) etisserant@0: trcbck_lst.append(trcbck) etisserant@0: etisserant@0: # Allow clicking.... etisserant@0: cap = wx.Window_GetCapture() etisserant@0: if cap: etisserant@0: cap.ReleaseMouse() etisserant@0: etisserant@0: dlg = wx.SingleChoiceDialog(None, laurent@391: _(""" b@427: An error has occurred. b@427: b@427: Click OK to save an error report. etisserant@0: greg@454: Please be kind enough to send this file to: greg@454: edouard.tisserant@gmail.com etisserant@0: etisserant@0: Error: laurent@391: """) + laurent@391: str(e_type) + _(" : ") + str(e_value), laurent@391: _("Error"), etisserant@0: trcbck_lst) etisserant@0: try: etisserant@0: res = (dlg.ShowModal() == wx.ID_OK) etisserant@0: finally: etisserant@0: dlg.Destroy() etisserant@0: etisserant@0: return res etisserant@0: etisserant@0: def Display_Error_Dialog(e_value): laurent@391: message = wx.MessageDialog(None, str(e_value), _("Error"), wx.OK|wx.ICON_ERROR) etisserant@0: message.ShowModal() etisserant@0: message.Destroy() etisserant@0: etisserant@0: def get_last_traceback(tb): etisserant@0: while tb.tb_next: etisserant@0: tb = tb.tb_next etisserant@0: return tb etisserant@0: etisserant@0: etisserant@0: def format_namespace(d, indent=' '): etisserant@0: return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()]) etisserant@0: etisserant@0: etisserant@0: ignored_exceptions = [] # a problem with a line in a module is only reported once per session etisserant@0: lbessard@65: def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]): etisserant@0: etisserant@0: def handle_exception(e_type, e_value, e_traceback): etisserant@0: traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func etisserant@0: last_tb = get_last_traceback(e_traceback) etisserant@0: ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno) etisserant@0: if str(e_value).startswith("!!!"): etisserant@0: Display_Error_Dialog(e_value) etisserant@0: elif ex not in ignored_exceptions: etisserant@0: result = Display_Exception_Dialog(e_type,e_value,e_traceback) etisserant@0: if result: etisserant@0: ignored_exceptions.append(ex) etisserant@0: info = { etisserant@0: 'app-title' : wx.GetApp().GetAppName(), # app_title etisserant@0: 'app-version' : app_version, etisserant@0: 'wx-version' : wx.VERSION_STRING, etisserant@0: 'wx-platform' : wx.Platform, etisserant@0: 'python-version' : platform.python_version(), #sys.version.split()[0], etisserant@0: 'platform' : platform.platform(), etisserant@0: 'e-type' : e_type, etisserant@0: 'e-value' : e_value, etisserant@0: 'date' : time.ctime(), etisserant@0: 'cwd' : os.getcwd(), etisserant@0: } etisserant@0: if e_traceback: etisserant@0: info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value) etisserant@0: last_tb = get_last_traceback(e_traceback) etisserant@0: exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred etisserant@0: info['locals'] = format_namespace(exception_locals) etisserant@0: if 'self' in exception_locals: etisserant@0: info['self'] = format_namespace(exception_locals['self'].__dict__) etisserant@0: etisserant@0: output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w') etisserant@0: lst = info.keys() etisserant@0: lst.sort() etisserant@0: for a in lst: etisserant@0: output.write(a+":\n"+str(info[a])+"\n\n") etisserant@0: etisserant@0: #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args) etisserant@0: sys.excepthook = handle_exception etisserant@0: etisserant@0: if __name__ == '__main__': lbessard@64: wx.InitAllImageHandlers() etisserant@0: etisserant@0: # Install a exception handle for bug reports lbessard@65: AddExceptHook(os.getcwd(),__version__) etisserant@0: lbessard@92: frame = PLCOpenEditor(None, fileOpen=fileOpen) etisserant@0: etisserant@0: frame.Show() etisserant@0: app.MainLoop() etisserant@0: