--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/PLCOpenEditor.py Wed Jan 31 16:31:39 2007 +0100
@@ -0,0 +1,2216 @@
+#Boa:Frame:PLCOpenEditor
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard.
+#
+#Copyright (C): Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from wxPython.wx import *
+from wxPython.grid import *
+from time import localtime
+from datetime import datetime
+import wx
+
+from SFCViewer import *
+from FBDViewer import *
+from LDViewer import *
+from Viewer import *
+from PLCControler import *
+from plcopen import OpenPDFDoc
+from plcopen.structures import *
+
+import os, re, platform, sys, time, traceback, getopt
+
+__version__ = "$Revision$"
+
+def create(parent):
+ return PLCOpenEditor(parent)
+
+def usage():
+ print "\nUsage of PLCOpenEditor.py :"
+ print "\n %s [Filepath]\n"%sys.argv[0]
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
+except getopt.GetoptError:
+ # print help information and exit:
+ usage()
+ sys.exit(2)
+
+for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+
+fileOpen = None
+if len(args) > 1:
+ usage()
+ sys.exit()
+elif len(args) == 1:
+ fileOpen = args[0]
+
+
+# Test if identifier is valid
+def TestIdentifier(identifier):
+ if identifier[0].isdigit():
+ return False
+ words = identifier.split('_')
+ for i, word in enumerate(words):
+ if len(word) == 0 and i != 0:
+ return False
+ if len(word) != 0 and not word.isalnum():
+ return False
+ return True
+
+[wxID_PLCOPENEDITOR, wxID_PLCOPENEDITORPROJECTTREE,
+ wxID_PLCOPENEDITORSPLITTERWINDOW1, wxID_PLCOPENEDITORTABSOPENED,
+ wxID_PLCOPENEDITORDEFAULTTOOLBAR, wxID_PLCOPENEDITORSFCTOOLBAR,
+ wxID_PLCOPENEDITORFBDTOOLBAR, wxID_PLCOPENEDITORLDTOOLBAR,
+] = [wx.NewId() for _init_ctrls in range(8)]
+
+[wxID_PLCOPENEDITORDEFAULTTOOLBARITEMS0,
+] = [wx.NewId() for _init_coll_DefaultToolBar_Items in range(1)]
+
+[wxID_PLCOPENEDITORSFCTOOLBARITEMS0, wxID_PLCOPENEDITORSFCTOOLBARITEMS1,
+ wxID_PLCOPENEDITORSFCTOOLBARITEMS2, wxID_PLCOPENEDITORSFCTOOLBARITEMS3,
+ wxID_PLCOPENEDITORSFCTOOLBARITEMS4, wxID_PLCOPENEDITORSFCTOOLBARITEMS5,
+ wxID_PLCOPENEDITORSFCTOOLBARITEMS6,
+] = [wx.NewId() for _init_coll_SFCToolBar_Items in range(7)]
+
+[wxID_PLCOPENEDITORFBDTOOLBARITEMS0, wxID_PLCOPENEDITORFBDTOOLBARITEMS1,
+ wxID_PLCOPENEDITORFBDTOOLBARITEMS2, wxID_PLCOPENEDITORFBDTOOLBARITEMS3,
+ wxID_PLCOPENEDITORFBDTOOLBARITEMS4, wxID_PLCOPENEDITORFBDTOOLBARITEMS5,
+] = [wx.NewId() for _init_coll_FBDToolBar_Items in range(6)]
+
+[wxID_PLCOPENEDITORLDTOOLBARITEMS0, wxID_PLCOPENEDITORLDTOOLBARITEMS1,
+ wxID_PLCOPENEDITORLDTOOLBARITEMS2, wxID_PLCOPENEDITORLDTOOLBARITEMS3,
+ wxID_PLCOPENEDITORLDTOOLBARITEMS4,
+] = [wx.NewId() for _init_coll_LDToolBar_Items in range(5)]
+
+[wxID_PLCOPENEDITORFILEMENUITEMS0, wxID_PLCOPENEDITORFILEMENUITEMS1,
+ wxID_PLCOPENEDITORFILEMENUITEMS2, wxID_PLCOPENEDITORFILEMENUITEMS3,
+ wxID_PLCOPENEDITORFILEMENUITEMS5, wxID_PLCOPENEDITORFILEMENUITEMS6,
+ wxID_PLCOPENEDITORFILEMENUITEMS7, wxID_PLCOPENEDITORFILEMENUITEMS9,
+ wxID_PLCOPENEDITORFILEMENUITEMS11,
+] = [wx.NewId() for _init_coll_FileMenu_Items in range(9)]
+
+[wxID_PLCOPENEDITORHELPMENUITEMS0, wxID_PLCOPENEDITORHELPMENUITEMS1,
+ wxID_PLCOPENEDITORHELPMENUITEMS2, wxID_PLCOPENEDITORHELPMENUITEMS3,
+] = [wx.NewId() for _init_coll_HelpMenu_Items in range(4)]
+
+[wxID_PLCOPENEDITORSFCMENUITEMS0, wxID_PLCOPENEDITORSFCMENUITEMS1,
+ wxID_PLCOPENEDITORSFCMENUITEMS2, wxID_PLCOPENEDITORSFCMENUITEMS3,
+] = [wx.NewId() for _init_coll_HelpMenu_Items in range(4)]
+
+[wxID_PLCOPENEDITORCONFIGMENUITEMS0, wxID_PLCOPENEDITORCONFIGMENUITEMS1,
+] = [wx.NewId() for _init_coll_HelpMenu_Items in range(2)]
+
+[wxID_PLCOPENEDITOREDITMENUITEMS0, wxID_PLCOPENEDITOREDITMENUITEMS1,
+ wxID_PLCOPENEDITOREDITMENUITEMS11, wxID_PLCOPENEDITOREDITMENUITEMS12,
+ wxID_PLCOPENEDITOREDITMENUITEMS2, wxID_PLCOPENEDITOREDITMENUITEMS4,
+ wxID_PLCOPENEDITOREDITMENUITEMS5, wxID_PLCOPENEDITOREDITMENUITEMS6,
+ wxID_PLCOPENEDITOREDITMENUITEMS8, wxID_PLCOPENEDITOREDITMENUITEMS9,
+] = [wx.NewId() for _init_coll_EditMenu_Items in range(10)]
+
+[wxID_PLCOPENEDITORSFCMENUITEMS0, wxID_PLCOPENEDITORSFCMENUITEMS1,
+ wxID_PLCOPENEDITORSFCMENUITEMS2, wxID_PLCOPENEDITORSFCMENUITEMS3,
+] = [wx.NewId() for _init_coll_SFCMenu_Items in range(4)]
+
+[wxID_PLCOPENEDITORCONFIGMENUITEMS0, wxID_PLCOPENEDITORCONFIGMENUITEMS1,
+] = [wx.NewId() for _init_coll_ConfigMenu_Items in range(2)]
+
+class PLCOpenEditor(wx.Frame):
+ _custom_classes = {'wx.SashWindow' : ['Viewer']}
+
+ def _init_coll_EditMenu_Items(self, parent):
+ # generated method, don't edit
+
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS0,
+ kind=wx.ITEM_NORMAL, text=u'Refresh\tCTRL+R')
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS1,
+ kind=wx.ITEM_NORMAL, text=u'Undo\tCTRL+Z')
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS2,
+ kind=wx.ITEM_NORMAL, text=u'Redo\tCTRL+Y')
+ parent.AppendSeparator()
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS4,
+ kind=wx.ITEM_NORMAL, text=u'Cut\tCTRL+X')
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS5,
+ kind=wx.ITEM_NORMAL, text=u'Copy\tCTRL+C')
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS6,
+ kind=wx.ITEM_NORMAL, text=u'Paste\tCTRL+V')
+ parent.AppendSeparator()
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS8,
+ kind=wx.ITEM_NORMAL, text=u'Add POU')
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS9,
+ kind=wx.ITEM_NORMAL, text=u'Remove POU')
+ parent.AppendSeparator()
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS11,
+ kind=wx.ITEM_NORMAL, text=u'Add Configuration')
+ parent.Append(help='', id=wxID_PLCOPENEDITOREDITMENUITEMS12,
+ kind=wx.ITEM_NORMAL, text=u'Remove Configuration')
+ self.Bind(wx.EVT_MENU, self.OnRefreshMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS0)
+ self.Bind(wx.EVT_MENU, self.OnCutMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS4)
+ self.Bind(wx.EVT_MENU, self.OnCopyMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS5)
+ self.Bind(wx.EVT_MENU, self.OnPasteMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS6)
+ self.Bind(wx.EVT_MENU, self.OnAddPouMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS8)
+ self.Bind(wx.EVT_MENU, self.OnRemovePouMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS9)
+ self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS11)
+ self.Bind(wx.EVT_MENU, self.OnRemoveConfigurationMenu,
+ id=wxID_PLCOPENEDITOREDITMENUITEMS12)
+
+ def _init_coll_menuBar1_Menus(self, parent):
+ # generated method, don't edit
+
+ parent.Append(menu=self.FileMenu, title=u'File')
+ parent.Append(menu=self.EditMenu, title=u'Edit')
+ parent.Append(menu=self.HelpMenu, title=u'Help')
+
+ def _init_coll_ConfigMenu_Items(self, parent):
+ # generated method, don't edit
+
+ parent.Append(help='', id=wxID_PLCOPENEDITORCONFIGMENUITEMS0,
+ kind=wx.ITEM_NORMAL, text=u'Add Resource')
+ parent.Append(help='', id=wxID_PLCOPENEDITORCONFIGMENUITEMS1,
+ kind=wx.ITEM_NORMAL, text=u'Remove Resource')
+ self.Bind(wx.EVT_MENU, self.OnAddResourceMenu,
+ id=wxID_PLCOPENEDITORCONFIGMENUITEMS0)
+ self.Bind(wx.EVT_MENU, self.OnRemoveResourceMenu,
+ id=wxID_PLCOPENEDITORCONFIGMENUITEMS1)
+
+ def _init_coll_HelpMenu_Items(self, parent):
+ # generated method, don't edit
+
+ parent.Append(help='', id=wxID_PLCOPENEDITORHELPMENUITEMS0,
+ kind=wx.ITEM_NORMAL, text=u'PLCOpenEditor\tF1')
+ parent.Append(help='', id=wxID_PLCOPENEDITORHELPMENUITEMS1,
+ kind=wx.ITEM_NORMAL, text=u'PLCOpen\tF2')
+ parent.Append(help='', id=wxID_PLCOPENEDITORHELPMENUITEMS2,
+ kind=wx.ITEM_NORMAL, text=u'IEC 61131-3\tF3')
+ parent.Append(help='', id=wxID_PLCOPENEDITORHELPMENUITEMS3,
+ kind=wx.ITEM_NORMAL, text=u'About')
+ self.Bind(wx.EVT_MENU, self.OnPLCOpenMenu,
+ id=wxID_PLCOPENEDITORHELPMENUITEMS1)
+
+ def _init_coll_FileMenu_Items(self, parent):
+ # generated method, don't edit
+
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS0,
+ kind=wx.ITEM_NORMAL, text=u'New\tCTRL+N')
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS1,
+ kind=wx.ITEM_NORMAL, text=u'Open\tCTRL+O')
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS2,
+ kind=wx.ITEM_NORMAL, text=u'Close Tab\tCTRL+W')
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS3,
+ kind=wx.ITEM_NORMAL, text=u'Close Project')
+ parent.AppendSeparator()
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS5,
+ kind=wx.ITEM_NORMAL, text=u'Save\tCTRL+S')
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS6,
+ kind=wx.ITEM_NORMAL, text=u'Save As...\tCTRL+SHIFT+S')
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS7,
+ kind=wx.ITEM_NORMAL, text=u'Generate Program\tCTRL+G')
+ parent.AppendSeparator()
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS9,
+ kind=wx.ITEM_NORMAL, text=u'Properties')
+ parent.AppendSeparator()
+ parent.Append(help='', id=wxID_PLCOPENEDITORFILEMENUITEMS11,
+ kind=wx.ITEM_NORMAL, text=u'Quit\tCTRL+Q')
+ self.Bind(wx.EVT_MENU, self.OnNewProjectMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS0)
+ self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS1)
+ self.Bind(wx.EVT_MENU, self.OnCloseTabMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS2)
+ self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS3)
+ self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS5)
+ self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS6)
+ self.Bind(wx.EVT_MENU, self.OnGenerateProgramMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS7)
+ self.Bind(wx.EVT_MENU, self.OnQuitMenu,
+ id=wxID_PLCOPENEDITORFILEMENUITEMS11)
+
+ def _init_coll_SFCMenu_Items(self, parent):
+ # generated method, don't edit
+
+ parent.Append(help='', id=wxID_PLCOPENEDITORSFCMENUITEMS0,
+ kind=wx.ITEM_NORMAL, text=u'Add Transition')
+ parent.Append(help='', id=wxID_PLCOPENEDITORSFCMENUITEMS1,
+ kind=wx.ITEM_NORMAL, text=u'Add Action')
+ parent.Append(help='', id=wxID_PLCOPENEDITORSFCMENUITEMS2,
+ kind=wx.ITEM_NORMAL, text=u'Remove Transition')
+ parent.Append(help='', id=wxID_PLCOPENEDITORSFCMENUITEMS3,
+ kind=wx.ITEM_NORMAL, text=u'Remove Action')
+ self.Bind(wx.EVT_MENU, self.OnAddPouTransitionMenu,
+ id=wxID_PLCOPENEDITORSFCMENUITEMS0)
+ self.Bind(wx.EVT_MENU, self.OnAddPouActionMenu,
+ id=wxID_PLCOPENEDITORSFCMENUITEMS1)
+ self.Bind(wx.EVT_MENU, self.OnRemovePouTransitionMenu,
+ id=wxID_PLCOPENEDITORSFCMENUITEMS2)
+ self.Bind(wx.EVT_MENU, self.OnRemovePouActionMenu,
+ id=wxID_PLCOPENEDITORSFCMENUITEMS3)
+
+ def _init_utils(self):
+ # generated method, don't edit
+ self.menuBar1 = wx.MenuBar()
+
+ self.FileMenu = wx.Menu(title=u'')
+
+ self.EditMenu = wx.Menu(title=u'')
+
+ self.HelpMenu = wx.Menu(title='')
+
+ self.SFCMenu = wx.Menu(title='')
+
+ self.ConfigMenu = wx.Menu(title='')
+
+ self._init_coll_menuBar1_Menus(self.menuBar1)
+ self._init_coll_FileMenu_Items(self.FileMenu)
+ self._init_coll_EditMenu_Items(self.EditMenu)
+ self._init_coll_HelpMenu_Items(self.HelpMenu)
+ self._init_coll_SFCMenu_Items(self.SFCMenu)
+ self._init_coll_ConfigMenu_Items(self.ConfigMenu)
+
+ def _init_coll_MainGridSizer_Items(self, parent):
+ # generated method, don't edit
+
+ parent.AddWindow(self.splitterWindow1, 0, border=0, flag=wxGROW)
+
+ def _init_coll_MainGridSizer_Growables(self, parent):
+ # generated method, don't edit
+
+ parent.AddGrowableCol(0)
+ parent.AddGrowableRow(0)
+
+ def _init_sizers(self):
+ # generated method, don't edit
+ self.MainGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
+
+ self._init_coll_MainGridSizer_Growables(self.MainGridSizer)
+ self._init_coll_MainGridSizer_Items(self.MainGridSizer)
+
+ self.SetSizer(self.MainGridSizer)
+
+ def _init_ctrls(self, prnt):
+ # generated method, don't edit
+ wx.Frame.__init__(self, id=wxID_PLCOPENEDITOR, name=u'PLCOpenEditor',
+ parent=prnt, pos=wx.Point(235, 287), size=wx.Size(1000, 600),
+ style=wx.DEFAULT_FRAME_STYLE, title=u'PLCOpenEditor')
+ self._init_utils()
+ self.SetClientSize(wx.Size(1000, 600))
+ self.SetMenuBar(self.menuBar1)
+ self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnProjectTreeItemBeginEdit,
+ id=wxID_PLCOPENEDITORPROJECTTREE)
+ self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnProjectTreeItemEndEdit,
+ id=wxID_PLCOPENEDITORPROJECTTREE)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnProjectTreeItemActivated,
+ id=wxID_PLCOPENEDITORPROJECTTREE)
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnProjectTreeItemSelected,
+ id=wxID_PLCOPENEDITORPROJECTTREE)
+
+ self.splitterWindow1 = wx.SplitterWindow(id=wxID_PLCOPENEDITORSPLITTERWINDOW1,
+ name='splitterWindow1', parent=self, point=wx.Point(0, 0),
+ size=wx.Size(-1, -1), style=wx.SP_3D)
+ self.splitterWindow1.SetNeedUpdating(True)
+ self.splitterWindow1.SetMinimumPaneSize(1)
+
+ self.TabsOpened = wx.Notebook(id=wxID_PLCOPENEDITORTABSOPENED,
+ name='TabsOpened', parent=self.splitterWindow1, pos=wx.Point(0,
+ 0), size=wx.Size(-1, -1), style=0)
+ self.TabsOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
+ self.OnPouSelectedChanged, id=wxID_PLCOPENEDITORTABSOPENED)
+
+ self.ProjectTree = wx.TreeCtrl(id=wxID_PLCOPENEDITORPROJECTTREE,
+ name='treeCtrl1', parent=self.splitterWindow1, pos=wx.Point(0, 0),
+ size=wx.Size(-1, -1),
+ style=wx.TR_HAS_BUTTONS|wx.TR_EDIT_LABELS|wx.TR_SINGLE|wx.SUNKEN_BORDER)
+ self.ProjectTree.Bind(wx.EVT_RIGHT_UP, self.OnProjectTreeRightUp)
+ self.splitterWindow1.SplitVertically(self.ProjectTree, self.TabsOpened,
+ 200)
+
+ self._init_sizers()
+
+ def init_coll_DefaultToolBar_Items(self, parent):
+ parent.AddRadioTool(wxID_PLCOPENEDITORDEFAULTTOOLBARITEMS0,
+ wxBitmap('Images/select.png'), wxNullBitmap, "Select an object")
+ self.Bind(wx.EVT_TOOL, self.OnSelectionTool,
+ id=wxID_PLCOPENEDITORDEFAULTTOOLBARITEMS0)
+
+ def init_coll_SFCToolBar_Items(self, parent):
+ parent.AddRadioTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS0,
+ wxBitmap('Images/select.png'), wxNullBitmap, "Select an object")
+ parent.AddRadioTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS1,
+ wxBitmap('Images/comment.png'), wxNullBitmap, "Create a new comment")
+ parent.AddRadioTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS2,
+ wxBitmap('Images/initial_step.png'), wxNullBitmap, "Create a new initial step")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS3,
+ wxBitmap('Images/step.png'), "Create a new step")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS4,
+ wxBitmap('Images/action.png'), "Add action block to step")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS5,
+ wxBitmap('Images/divergence.png'), "Create a new divergence")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS6,
+ wxBitmap('Images/jump.png'), "Create a new jump")
+ self.Bind(wx.EVT_TOOL, self.OnSelectionTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS0)
+ self.Bind(wx.EVT_TOOL, self.OnCommentTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS1)
+ self.Bind(wx.EVT_TOOL, self.OnSFCInitialStepTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS2)
+ self.Bind(wx.EVT_TOOL, self.OnSFCStepTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS3)
+ self.Bind(wx.EVT_TOOL, self.OnSFCActionBlockTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS4)
+ self.Bind(wx.EVT_TOOL, self.OnSFCDivergenceTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS5)
+ self.Bind(wx.EVT_TOOL, self.OnSFCJumpTool,
+ id=wxID_PLCOPENEDITORSFCTOOLBARITEMS6)
+
+ def init_coll_FBDToolBar_Items(self, parent):
+ parent.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS0,
+ wxBitmap('Images/select.png'), wxNullBitmap, "Select an object")
+ parent.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS1,
+ wxBitmap('Images/comment.png'), wxNullBitmap, "Create a new comment")
+ parent.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS2,
+ wxBitmap('Images/variable.png'), wxNullBitmap, "Create a new variable")
+ parent.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS3,
+ wxBitmap('Images/block.png'), wxNullBitmap, "Create a new block")
+ parent.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS4,
+ wxBitmap('Images/connection.png'), wxNullBitmap, "Create a new connection")
+ parent.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS5,
+ wxBitmap('Images/wire.png'), wxNullBitmap, "Create a new wire")
+ self.Bind(wx.EVT_TOOL, self.OnSelectionTool,
+ id=wxID_PLCOPENEDITORFBDTOOLBARITEMS0)
+ self.Bind(wx.EVT_TOOL, self.OnCommentTool,
+ id=wxID_PLCOPENEDITORFBDTOOLBARITEMS1)
+ self.Bind(wx.EVT_TOOL, self.OnFBDVariableTool,
+ id=wxID_PLCOPENEDITORFBDTOOLBARITEMS2)
+ self.Bind(wx.EVT_TOOL, self.OnFBDBlockTool,
+ id=wxID_PLCOPENEDITORFBDTOOLBARITEMS3)
+ self.Bind(wx.EVT_TOOL, self.OnFBDConnectionTool,
+ id=wxID_PLCOPENEDITORFBDTOOLBARITEMS4)
+ self.Bind(wx.EVT_TOOL, self.OnWireTool,
+ id=wxID_PLCOPENEDITORFBDTOOLBARITEMS5)
+
+ def init_coll_LDToolBar_Items(self, parent):
+ parent.AddRadioTool(wxID_PLCOPENEDITORLDTOOLBARITEMS0,
+ wxBitmap('Images/select.png'), wxNullBitmap, "Select an object")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS1,
+ wxBitmap('Images/coil.png'), "Create a new rung")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS2,
+ wxBitmap('Images/contact.png'), "Create a new contact")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS3,
+ wxBitmap('Images/block.png'), "Create a new block")
+ parent.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS4,
+ wxBitmap('Images/branch.png'), "Create a new branch")
+ self.Bind(wx.EVT_TOOL, self.OnSelectionTool,
+ id=wxID_PLCOPENEDITORLDTOOLBARITEMS0)
+ self.Bind(wx.EVT_TOOL, self.OnLDCoilTool,
+ id=wxID_PLCOPENEDITORLDTOOLBARITEMS1)
+ self.Bind(wx.EVT_TOOL, self.OnLDContactTool,
+ id=wxID_PLCOPENEDITORLDTOOLBARITEMS2)
+ self.Bind(wx.EVT_TOOL, self.OnLDBlockTool,
+ id=wxID_PLCOPENEDITORLDTOOLBARITEMS3)
+ self.Bind(wx.EVT_TOOL, self.OnLDBranchTool,
+ id=wxID_PLCOPENEDITORLDTOOLBARITEMS4)
+
+ def init_toolbars(self, parent):
+ self.DefaultToolBar = wxToolBar(id=wxID_PLCOPENEDITORDEFAULTTOOLBAR, name='DefaultToolBar',
+ parent=parent, pos=wx.Point(0, 27), size=wx.Size(0, 0),
+ style=wxTB_HORIZONTAL | wxNO_BORDER)
+
+ self.SFCToolBar = wxToolBar(id=wxID_PLCOPENEDITORSFCTOOLBAR, name='SFCToolBar',
+ parent=parent, pos=wx.Point(0, 27), size=wx.Size(0, 0),
+ style=wxTB_HORIZONTAL | wxNO_BORDER)
+
+ self.FBDToolBar = wxToolBar(id=wxID_PLCOPENEDITORFBDTOOLBAR, name='FBDToolBar',
+ parent=parent, pos=wx.Point(0, 27), size=wx.Size(0, 0),
+ style=wxTB_HORIZONTAL | wxNO_BORDER)
+
+ self.LDToolBar = wxToolBar(id=wxID_PLCOPENEDITORLDTOOLBAR, name='LDToolBar',
+ parent=parent, pos=wx.Point(0, 27), size=wx.Size(0, 0),
+ style=wxTB_HORIZONTAL | wxNO_BORDER)
+
+ self.init_coll_DefaultToolBar_Items(self.DefaultToolBar)
+ self.init_coll_SFCToolBar_Items(self.SFCToolBar)
+ self.init_coll_FBDToolBar_Items(self.FBDToolBar)
+ self.init_coll_LDToolBar_Items(self.LDToolBar)
+
+ def __init__(self, parent):
+ self._init_ctrls(parent)
+ self.init_toolbars(self)
+
+ self.Controler = PLCControler()
+
+ if fileOpen:
+ self.Controler.OpenXMLFile(fileOpen)
+ self.RefreshProjectTree()
+
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+
+ def RefreshFileMenu(self):
+ if self.Controler.HasOpenedProject():
+ if self.TabsOpened.GetPageCount() > 0:
+ self.FileMenu.FindItemByPosition(2).Enable(True)
+ else:
+ self.FileMenu.FindItemByPosition(2).Enable(False)
+ self.FileMenu.FindItemByPosition(3).Enable(True)
+ self.FileMenu.FindItemByPosition(5).Enable(True)
+ self.FileMenu.FindItemByPosition(6).Enable(True)
+ self.FileMenu.FindItemByPosition(7).Enable(True)
+ self.FileMenu.FindItemByPosition(9).Enable(True)
+ else:
+ self.FileMenu.FindItemByPosition(2).Enable(False)
+ self.FileMenu.FindItemByPosition(3).Enable(False)
+ self.FileMenu.FindItemByPosition(5).Enable(False)
+ self.FileMenu.FindItemByPosition(6).Enable(False)
+ self.FileMenu.FindItemByPosition(7).Enable(False)
+ self.FileMenu.FindItemByPosition(9).Enable(False)
+
+ def RefreshEditMenu(self):
+ self.EditMenu.FindItemByPosition(1).Enable(False)
+ self.EditMenu.FindItemByPosition(2).Enable(False)
+ if self.Controler.HasOpenedProject():
+ if self.TabsOpened.GetPageCount() > 0:
+ self.EditMenu.FindItemByPosition(0).Enable(True)
+ else:
+ self.EditMenu.FindItemByPosition(0).Enable(False)
+ self.EditMenu.FindItemByPosition(8).Enable(True)
+ self.EditMenu.FindItemByPosition(9).Enable(True)
+ else:
+ self.EditMenu.FindItemByPosition(0).Enable(False)
+ self.EditMenu.FindItemByPosition(8).Enable(False)
+ self.EditMenu.FindItemByPosition(9).Enable(False)
+ bodytype = self.Controler.GetCurrentElementEditingBodyType()
+ if bodytype in ["LD","ST"]:
+ self.EditMenu.FindItemByPosition(4).Enable(True)
+ self.EditMenu.FindItemByPosition(5).Enable(True)
+ self.EditMenu.FindItemByPosition(6).Enable(True)
+ else:
+ self.EditMenu.FindItemByPosition(4).Enable(False)
+ self.EditMenu.FindItemByPosition(5).Enable(False)
+ self.EditMenu.FindItemByPosition(6).Enable(False)
+
+ def OnNewProjectMenu(self, event):
+ dialog = ProjectDialog(self)
+ if dialog.ShowModal() == wxID_OK:
+ values = dialog.GetValues()
+ projectname = values.pop("projectName")
+ values["creationDateTime"] = datetime(*localtime()[:6])
+ self.Controler.CreateNewProject(projectname)
+ self.Controler.SetProjectProperties(values)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshProjectTree()
+ event.Skip()
+
+ def OnOpenProjectMenu(self, event):
+ filepath = self.Controler.GetFilePath()
+ if filepath != "":
+ directory = os.path.dirname(filepath)
+ else:
+ directory = os.getcwd()
+ dialog = wxFileDialog(self, "Choose a file", directory, "", "PLCOpen files (*.xml)|*.xml|All files|*.*", wxOPEN)
+ if dialog.ShowModal() == wxID_OK:
+ filepath = dialog.GetPath()
+ if os.path.isfile(filepath):
+ self.Controler.OpenXMLFile(filepath)
+ self.TabsOpened.DeleteAllPages()
+ self.RefreshProjectTree()
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnCloseTabMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected >= 0:
+ self.Controler.CloseElementEditing()
+ self.TabsOpened.DeletePage(selected)
+ if self.TabsOpened.GetPageCount() > 0:
+ self.TabsOpened.SetSelection(min(selected, self.TabsOpened.GetPageCount() - 1))
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ event.Skip()
+
+ def OnCloseProjectMenu(self, event):
+ self.Controler.Reset()
+ self.TabsOpened.DeleteAllPages()
+ self.ProjectTree.DeleteAllItems()
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ event.Skip()
+
+ def OnSaveProjectMenu(self, event):
+ self.SaveProject()
+ event.Skip()
+
+ def OnSaveProjectAsMenu(self, event):
+ self.SaveProjectAs()
+ event.Skip()
+
+ def OnGenerateProgramMenu(self, event):
+ self.Controler.GenerateProgram()
+ event.Skip()
+
+ def SaveProject(self):
+ result = self.Controler.SaveXMLFile()
+ if not result:
+ self.SaveProjectAs()
+
+ def SaveProjectAs(self):
+ filepath = self.Controler.GetFilePath()
+ if filepath != "":
+ directory, filename = os.path.split(filepath)
+ else:
+ directory, filename = os.getcwd(), "%s.od"%self.Controler.GetProjectName()
+ dialog = wxFileDialog(self, "Choose a file", directory, filename, "PLCOpen files (*.xml)|*.xml|All files|*.*", wxSAVE|wxOVERWRITE_PROMPT)
+ if dialog.ShowModal() == wxID_OK:
+ filepath = dialog.GetPath()
+ if os.path.isdir(os.path.dirname(filepath)):
+ result = self.Controler.SaveXMLFile(filepath)
+ if not result:
+ message = wxMessageDialog(self, "Can't save project to file %s!"%filepath, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ else:
+ message = wxMessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ dialog.Destroy()
+
+ def OnQuitMenu(self, event):
+ self.Close()
+ event.Skip()
+
+ def OnSelectionTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION)
+ event.Skip()
+
+ def OnCommentTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT)
+ event.Skip()
+
+ def OnWireTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_WIRE)
+ event.Skip()
+
+ def OnSFCInitialStepTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_INITIAL_STEP)
+ event.Skip()
+
+ def OnSFCStepTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddStep()
+ event.Skip()
+
+ def OnSFCActionBlockTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddStepAction()
+ event.Skip()
+
+ def OnSFCDivergenceTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddDivergence()
+ event.Skip()
+
+ def OnSFCJumpTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddJump()
+ event.Skip()
+
+ def OnFBDVariableTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE)
+ event.Skip()
+
+ def OnFBDBlockTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK)
+ event.Skip()
+
+ def OnFBDConnectionTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION)
+ event.Skip()
+
+ def OnLDCoilTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddRung()
+ event.Skip()
+
+ def OnLDContactTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddContact()
+ event.Skip()
+
+ def OnLDBlockTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ pass
+ event.Skip()
+
+ def OnLDBranchTool(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).AddBranch()
+ event.Skip()
+
+ def OnPouSelectedChanged(self, event):
+ selected = event.GetSelection()
+ if selected >= 0:
+ self.Controler.RefreshCurrentElementEditing(selected)
+ found = False
+ name = self.TabsOpened.GetPageText(selected)
+ root = self.ProjectTree.GetRootItem()
+ item, root_cookie = self.ProjectTree.GetFirstChild(root)
+ while item.IsOk() and not found:
+ if self.ProjectTree.GetItemText(item) == name:
+ self.ProjectTree.SelectItem(item)
+ item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ event.Skip()
+
+ def OnProjectTreeItemEndEdit(self, event):
+ new_name = event.GetLabel()
+ if new_name != "":
+ if TestIdentifier(new_name):
+ item = event.GetItem()
+ itemtype = self.ProjectTree.GetPyData(item)
+ if itemtype == ITEM_PROJECT:
+ self.Controler.SetProjectName(new_name)
+ elif itemtype == ITEM_POU:
+ old_name = self.ProjectTree.GetItemText(item)
+ self.Controler.ChangePouName(old_name, new_name)
+ self.RefreshTabsOpenedTitles()
+ elif itemtype == ITEM_TRANSITION:
+ old_name = self.ProjectTree.GetItemText(item)
+ parent = self.ProjectTree.GetItemParent(item)
+ grandparent = self.ProjectTree.GetItemParent(parent)
+ grandparent_name = self.ProjectTree.GetItemText(grandparent)
+ self.Controler.ChangePouTransitionName(grandparent_name, old_name, new_name)
+ self.RefreshTabsOpenedTitles()
+ elif itemtype == ITEM_ACTION:
+ old_name = self.ProjectTree.GetItemText(item)
+ parent = self.ProjectTree.GetItemParent(item)
+ grandparent = self.ProjectTree.GetItemParent(parent)
+ grandparent_name = self.ProjectTree.GetItemText(grandparent)
+ self.Controler.ChangePouActionName(grandparent_name, old_name, new_name)
+ self.RefreshTabsOpenedTitles()
+ wxCallAfter(self.RefreshProjectTree)
+ event.Skip()
+ else:
+ message = wxMessageDialog(self, "\"%s\" is not a valid identifier!"%new_name, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ item = event.GetItem()
+ wxCallAfter(self.ProjectTree.EditLabel, item)
+ event.Veto()
+
+ def OnProjectTreeItemBeginEdit(self, event):
+ selected = event.GetItem()
+ if self.ProjectTree.GetPyData(selected) == ITEM_UNEDITABLE:
+ event.Veto()
+ else:
+ event.Skip()
+
+ def OnProjectTreeItemActivated(self, event):
+ selected = event.GetItem()
+ if self.ProjectTree.IsExpanded(selected):
+ self.ProjectTree.Collapse(selected)
+ else:
+ self.ProjectTree.Expand(selected)
+ name = self.ProjectTree.GetItemText(selected)
+ data = self.ProjectTree.GetPyData(selected)
+ if name == "Properties":
+ old_values = self.Controler.GetProjectProperties()
+ old_values["projectName"] = self.Controler.GetProjectName()
+ dialog = ProjectDialog(self)
+ dialog.SetValues(old_values)
+ if dialog.ShowModal() == wxID_OK:
+ new_values = dialog.GetValues()
+ projectname = new_values.pop("projectName")
+ new_values["creationDateTime"] = old_values["creationDateTime"]
+ self.Controler.SetProjectName(projectname)
+ self.Controler.SetProjectProperties(new_values)
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ elif data == ITEM_CLASS:
+ item = self.ProjectTree.GetItemParent(selected)
+ item_type = self.ProjectTree.GetPyData(item)
+ while item_type != ITEM_POU:
+ item = self.ProjectTree.GetItemParent(item)
+ item_type = self.ProjectTree.GetPyData(item)
+ pou_name = self.ProjectTree.GetItemText(item)
+ dialog = EditVariableDialog(self, pou_name, self.Controler.GetPouType(pou_name), name)
+ values = {}
+ values["returnType"] = self.Controler.GetPouInterfaceReturnTypeByName(pou_name)
+ values["data"] = self.Controler.GetPouInterfaceVarsByName(pou_name)
+ dialog.SetValues(values)
+ if dialog.ShowModal() == wxID_OK:
+ if not self.Controler.PouIsUsed(pou_name):
+ new_values = dialog.GetValues()
+ if "returnType" in new_values:
+ self.Controler.SetPouInterfaceReturnType(pou_name, new_values["returnType"])
+ self.Controler.SetPouInterfaceVars(pou_name, new_values["data"])
+ pou_names = self.Controler.GetElementsOpenedNames()
+ if pou_name in pou_names:
+ window = self.TabsOpened.GetPage(pou_names.index(pou_name))
+ if isinstance(window, TextViewer):
+ varlist = []
+ if "returnType" in new_values:
+ varlist.append(name)
+ for var in new_values["data"]:
+ varlist.append(var["Name"])
+ window.SetVariables(varlist)
+ else:
+ message = wxMessageDialog(self, "\"%s\" is used by one or more POUs. Its interface can't be changed!"%pou_name, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ dialog.Destroy()
+ elif name == "Global Vars":
+ parent = self.ProjectTree.GetItemParent(selected)
+ parent_name = self.ProjectTree.GetItemText(parent)
+ dialog = EditVariableDialog(self, parent_name, None)
+ if self.ProjectTree.GetPyData(parent) == ITEM_CONFIGURATION:
+ values = {"data" : self.Controler.GetConfigurationGlobalVars(parent_name)}
+ dialog.SetValues(values)
+ if dialog.ShowModal() == wxID_OK:
+ new_values = dialog.GetValues()
+ self.Controler.SetConfigurationGlobalVars(parent_name, new_values["data"])
+ else:
+ config = self.ProjectTree.GetItemParent(parent)
+ config_name = self.ProjectTree.GetItemText(config)
+ values = {"data" : self.Controler.GetConfigurationResourceGlobalVars(config_name, parent_name)}
+ dialog.SetValues(values)
+ if dialog.ShowModal() == wxID_OK:
+ new_values = dialog.GetValues()
+ self.Controler.SetConfigurationResourceGlobalVars(config_name, parent_name, new_values["data"])
+ elif data in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
+ if data == ITEM_POU:
+ idx = self.Controler.OpenElementEditing(name)
+ language = self.Controler.GetPouBodyType(name)
+ varlist = []
+ returnType = self.Controler.GetPouInterfaceReturnTypeByName(name)
+ if returnType:
+ varlist.append(name)
+ vars = self.Controler.GetPouInterfaceVarsByName(name)
+ if vars:
+ for var in vars:
+ varlist.append(var["Name"])
+ else:
+ parent = self.ProjectTree.GetItemParent(selected)
+ parent_name = self.ProjectTree.GetItemText(parent)
+ grandparent = self.ProjectTree.GetItemParent(parent)
+ grandparent_name = self.ProjectTree.GetItemText(grandparent)
+ if data == ITEM_TRANSITION:
+ idx = self.Controler.OpenPouTransitionEditing(grandparent_name, name)
+ language = self.Controler.GetTransitionBodyType(grandparent_name, name)
+ elif data == ITEM_ACTION:
+ idx = self.Controler.OpenPouActionEditing(grandparent_name, name)
+ language = self.Controler.GetActionBodyType(grandparent_name, name)
+ varlist = [name]
+ vars = self.Controler.GetPouInterfaceVarsByName(grandparent_name)
+ if vars:
+ for var in vars:
+ varlist.append(var["Name"])
+ if idx != None:
+ if language == "FBD":
+ new_window = FBD_Viewer(self.TabsOpened, self, self.Controler)
+ elif language == "LD":
+ new_window = LD_Viewer(self.TabsOpened, self, self.Controler)
+ elif language == "SFC":
+ new_window = SFC_Viewer(self.TabsOpened, self, self.Controler)
+ elif language in ["IL", "ST"]:
+ new_window = TextViewer(self.TabsOpened, self, self.Controler)
+ if language == "IL":
+ new_window.SetKeywords(IL_KEYWORDS)
+ else:
+ new_window.SetKeywords(ST_KEYWORDS)
+ new_window.SetVariables(varlist)
+ new_window.SetFunctions(self.Controler.GetBlockTypes())
+ else:
+ return
+ new_window.RefreshView()
+ self.TabsOpened.AddPage(new_window, "")
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshTabsOpenedTitles()
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ else:
+ if data == ITEM_POU:
+ idx = self.Controler.ChangeElementEditing(name)
+ elif data == ITEM_TRANSITION:
+ idx = self.Controler.ChangePouTransitionEditing(grandparent_name, name)
+ elif data == ITEM_ACTION:
+ idx = self.Controler.ChangePouActionEditing(grandparent_name, name)
+ if idx != None:
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ elif data == ITEM_RESOURCE:
+ item = self.ProjectTree.GetItemParent(selected)
+ item_type = self.ProjectTree.GetPyData(item)
+ while item_type != ITEM_CONFIGURATION:
+ item = self.ProjectTree.GetItemParent(item)
+ item_type = self.ProjectTree.GetPyData(item)
+ config_name = self.ProjectTree.GetItemText(item)
+ idx = self.Controler.OpenConfigurationResourceEditing(config_name, name)
+ if idx != None:
+ new_window = ResourceEditor(self.TabsOpened, self, self.Controler)
+ new_window.RefreshView()
+ self.TabsOpened.AddPage(new_window, "")
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshTabsOpenedTitles()
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ else:
+ idx = self.Controler.ChangeConfigurationResourceEditing(parent_name, name)
+ if idx != None:
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+
+ def OnProjectTreeRightUp(self, event):
+ selected = self.ProjectTree.GetSelection()
+ if self.ProjectTree.GetPyData(selected) == ITEM_POU:
+ name = self.ProjectTree.GetItemText(selected)
+ if self.Controler.GetPouBodyType(name) == "SFC":
+ self.PopupMenu(self.SFCMenu)
+ elif self.ProjectTree.GetPyData(selected) == ITEM_CONFIGURATION:
+ self.PopupMenu(self.ConfigMenu)
+ event.Skip()
+
+ def OnProjectTreeItemSelected(self, event):
+ selected = event.GetItem()
+ name = self.ProjectTree.GetItemText(selected)
+ if self.ProjectTree.GetItemParent(selected) == self.ProjectTree.GetRootItem() and name != "Properties":
+ if self.Controler.IsElementEditing(name):
+ idx = self.Controler.ChangeElementEditing(name)
+ if idx != None:
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ else:
+ name = self.ProjectTree.GetItemText(selected)
+ parent = self.ProjectTree.GetItemParent(selected)
+ parent_name = self.ProjectTree.GetItemText(parent)
+ grandparent = self.ProjectTree.GetItemParent(parent)
+ grandparent_name = self.ProjectTree.GetItemText(grandparent)
+ if parent_name == "Transitions":
+ idx = self.Controler.ChangePouTransitionEditing(grandparent_name, name)
+ if idx != None:
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ elif parent_name == "Action":
+ idx = self.Controler.ChangePouActionEditing(grandparent_name, name)
+ if idx != None:
+ self.TabsOpened.SetSelection(idx)
+ self.RefreshFileMenu()
+ self.RefreshEditMenu()
+ self.RefreshToolBar()
+ event.Skip()
+
+ def RefreshProjectTree(self):
+ infos = self.Controler.GetProjectInfos()
+ root = self.ProjectTree.GetRootItem()
+ self.GenerateTreeBranch(root, infos)
+ self.ProjectTree.Expand(self.ProjectTree.GetRootItem())
+
+ def GenerateTreeBranch(self, root, infos):
+ to_delete = []
+ if root.IsOk():
+ self.ProjectTree.SetItemText(root, infos["name"])
+ else:
+ root = self.ProjectTree.AddRoot(infos["name"])
+ self.ProjectTree.SetPyData(root, infos["type"])
+ item, root_cookie = self.ProjectTree.GetFirstChild(root)
+ if len(infos["values"]) > 0:
+ for values in infos["values"]:
+ if not item.IsOk():
+ item = self.ProjectTree.AppendItem(root, "")
+ item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
+ self.GenerateTreeBranch(item, values)
+ item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie)
+ while item.IsOk():
+ to_delete.append(item)
+ item, root_cookie = self.ProjectTree.GetNextChild(item, root_cookie)
+ for item in to_delete:
+ self.ProjectTree.Delete(item)
+
+ def RefreshToolBar(self):
+ language = self.Controler.GetCurrentElementEditingBodyType()
+ if language == "SFC":
+ self.SFCToolBar.ToggleTool(0, True)
+ self.SFCToolBar.Show()
+ self.SetToolBar(self.SFCToolBar)
+ self.DefaultToolBar.Hide()
+ self.FBDToolBar.Hide()
+ self.LDToolBar.Hide()
+ elif language == "FBD":
+ self.FBDToolBar.ToggleTool(0, True)
+ self.FBDToolBar.Show()
+ self.SetToolBar(self.FBDToolBar)
+ self.DefaultToolBar.Hide()
+ self.SFCToolBar.Hide()
+ self.LDToolBar.Hide()
+ elif language == "LD":
+ self.LDToolBar.ToggleTool(0, True)
+ self.LDToolBar.Show()
+ self.SetToolBar(self.LDToolBar)
+ self.DefaultToolBar.Hide()
+ self.SFCToolBar.Hide()
+ self.FBDToolBar.Hide()
+ else:
+ self.DefaultToolBar.ToggleTool(0, True)
+ self.DefaultToolBar.Show()
+ self.SetToolBar(self.DefaultToolBar)
+ self.SFCToolBar.Hide()
+ self.FBDToolBar.Hide()
+ self.LDToolBar.Hide()
+
+ def RefreshTabsOpenedTitles(self):
+ pous = self.Controler.GetElementsOpenedNames()
+ for i, pou in enumerate(pous):
+ self.TabsOpened.SetPageText(i, pou)
+
+ def OnRefreshMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).Refresh()
+ event.Skip()
+
+ def OnCutMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).Cut()
+ event.Skip()
+
+ def OnCopyMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).Copy()
+ event.Skip()
+
+ def OnPasteMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ self.TabsOpened.GetPage(selected).Paste()
+ event.Skip()
+
+ def OnAddPouMenu(self, event):
+ dialog = PouDialog(self)
+ dialog.SetPouNames(self.Controler.GetProjectPouNames())
+ if dialog.ShowModal() == wxID_OK:
+ values = dialog.GetValues()
+ self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"])
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnRemovePouMenu(self, event):
+ pous = self.Controler.GetProjectPouNames()
+ dialog = wxSingleChoiceDialog(self, "Select POU to remove:", "POU Remove", pous, wxOK|wxCANCEL)
+ if dialog.ShowModal() == wxID_OK:
+ selected = dialog.GetStringSelection()
+ if not self.Controler.PouIsUsed(selected):
+ self.Controler.ProjectRemovePou(selected)
+ for i in xrange(self.TabsOpened.GetPageCount()):
+ if self.TabsOpened.GetPageText(i) == selected:
+ self.TabsOpened.DeletePage(i)
+ self.RefreshProjectTree()
+ self.RefreshToolBar()
+ else:
+ message = wxMessageDialog(self, "%s is used by one or more POUs. It can't be removed!"%selected, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ event.Skip()
+
+ def OnAddConfigurationMenu(self, event):
+ dialog = wxTextEntryDialog(self, "Enter configuration name:", "Create new configuration", "", wxOK|wxCANCEL)
+ if dialog.ShowModal() == wxID_OK:
+ value = dialog.GetValue()
+ self.Controler.ProjectAddConfiguration(value)
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnRemoveConfigurationMenu(self, event):
+ configs = self.Controler.GetProjectConfigNames()
+ dialog = wxSingleChoiceDialog(self, "Select Configuration to remove:", "Configuration Remove", configs, wxOK|wxCANCEL)
+ if dialog.ShowModal() == wxID_OK:
+ selected = dialog.GetStringSelection()
+ self.Controler.ProjectRemoveConfiguration(selected)
+ self.RefreshProjectTree()
+ event.Skip()
+
+ def OnAddPouTransitionMenu(self, event):
+ dialog = PouTransitionDialog(self)
+ dialog.SetPous(self.Controler.GetSFCPous())
+ if dialog.ShowModal() == wxID_OK:
+ values = dialog.GetValues()
+ self.Controler.ProjectAddPouTransition(values["pouName"], values["transitionName"], values["language"])
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnRemovePouTransitionMenu(self, event):
+ event.Skip()
+
+ def OnAddPouActionMenu(self, event):
+ dialog = PouActionDialog(self)
+ dialog.SetPous(self.Controler.GetSFCPous())
+ if dialog.ShowModal() == wxID_OK:
+ values = dialog.GetValues()
+ self.Controler.ProjectAddPouAction(values["pouName"], values["actionName"], values["language"])
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnRemovePouActionMenu(self, event):
+ event.Skip()
+
+ def OnAddResourceMenu(self, event):
+ selected = self.ProjectTree.GetSelection()
+ if self.ProjectTree.GetPyData(selected) == ITEM_CONFIGURATION:
+ config_name = self.ProjectTree.GetItemText(selected)
+ dialog = wxTextEntryDialog(self, "Enter Resource name:", "Create new Resource", "", wxOK|wxCANCEL)
+ if dialog.ShowModal() == wxID_OK:
+ value = dialog.GetValue()
+ self.Controler.ProjectAddConfigurationResource(config_name, value)
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnRemoveResourceMenu(self, event):
+ selected = self.ProjectTree.GetSelection()
+ if self.ProjectTree.GetPyData(selected) == ITEM_CONFIGURATION:
+ config_name = self.ProjectTree.GetItemText(selected)
+ infos = self.Controler.GetProjectInfos()
+ resources = []
+ for config in infos["configs"]:
+ if config["name"] == config_name:
+ resources = config["resources"]
+ dialog = wxSingleChoiceDialog(self, "Select Resource to remove:", "Resource Remove", resources, wxOK|wxCANCEL)
+ if dialog.ShowModal() == wxID_OK:
+ resource = dialog.GetStringSelection()
+ self.Controler.ProjectRemoveConfigurationResource(config_name, resource)
+ self.RefreshProjectTree()
+ dialog.Destroy()
+ event.Skip()
+
+ def OnPLCOpenMenu(self, event):
+ result = OpenPDFDoc()
+ if type(result) == StringType:
+ message = wxMessageDialog(self, result, "ERROR", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ event.Skip()
+
+current_num = 0
+def GetNewNum():
+ global current_num
+ current_num += 1
+ return current_num
+
+#-------------------------------------------------------------------------------
+# Create Project Dialog
+#-------------------------------------------------------------------------------
+
+[wxID_PROJECTDIALOG, wxID_PROJECTDIALOGMAINPANEL,
+ wxID_PROJECTDIALOGPROJECTNAME, wxID_PROJECTDIALOGCOMPANYNAME,
+ wxID_PROJECTDIALOGCOMPANYURL, wxID_PROJECTDIALOGPRODUCTNAME,
+ wxID_PROJECTDIALOGPRODUCTVERSION, wxID_PROJECTDIALOGPRODUCTRELEASE,
+ wxID_PROJECTDIALOGCONTENTDESCRIPTION, wxID_PROJECTDIALOGSTATICTEXT1,
+ wxID_PROJECTDIALOGSTATICTEXT2, wxID_PROJECTDIALOGSTATICTEXT3,
+ wxID_PROJECTDIALOGSTATICTEXT4, wxID_PROJECTDIALOGSTATICTEXT5,
+ wxID_PROJECTDIALOGSTATICTEXT6, wxID_PROJECTDIALOGSTATICTEXT7,
+] = [wx.NewId() for _init_ctrls in range(16)]
+
+class ProjectDialog(wx.Dialog):
+ def _init_coll_flexGridSizer1_Items(self, parent):
+ # generated method, don't edit
+
+ parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
+
+ def _init_sizers(self):
+ # generated method, don't edit
+ self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
+
+ self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
+
+ self.SetSizer(self.flexGridSizer1)
+
+ def _init_ctrls(self, prnt):
+ # generated method, don't edit
+ wx.Dialog.__init__(self, id=wxID_PROJECTDIALOG,
+ name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223),
+ size=wx.Size(550, 450), style=wx.DEFAULT_DIALOG_STYLE,
+ title='Create a new project')
+ self.SetClientSize(wx.Size(550, 450))
+
+ self.MainPanel = wx.Panel(id=wxID_PROJECTDIALOGMAINPANEL,
+ name='MainPanel', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(450, 400), style=wx.TAB_TRAVERSAL)
+ self.MainPanel.SetAutoLayout(True)
+
+ self.staticText1 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT1,
+ label='Project Name (required):', name='staticText1', parent=self.MainPanel,
+ pos=wx.Point(24, 24), size=wx.Size(215, 17), style=0)
+
+ self.ProjectName = wx.TextCtrl(id=wxID_PROJECTDIALOGPROJECTNAME,
+ name='ProjectName', parent=self.MainPanel, pos=wx.Point(224, 24),
+ size=wx.Size(295, 24), style=0)
+
+ self.staticText2 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT2,
+ label='Company Name (required):', name='staticText2', parent=self.MainPanel,
+ pos=wx.Point(24, 64), size=wx.Size(215, 17), style=0)
+
+ self.CompanyName = wx.TextCtrl(id=wxID_PROJECTDIALOGCOMPANYNAME,
+ name='CompanyName', parent=self.MainPanel, pos=wx.Point(224, 64),
+ size=wx.Size(295, 24), style=0)
+
+ self.staticText3 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT3,
+ label='Company URL (optional):', name='staticText3', parent=self.MainPanel,
+ pos=wx.Point(24, 104), size=wx.Size(215, 17), style=0)
+
+ self.CompanyURL = wx.TextCtrl(id=wxID_PROJECTDIALOGCOMPANYURL,
+ name='CompanyURL', parent=self.MainPanel, pos=wx.Point(224, 104),
+ size=wx.Size(295, 24), style=0)
+
+ self.staticText4 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT4,
+ label='Product Name (required):', name='staticText4', parent=self.MainPanel,
+ pos=wx.Point(24, 144), size=wx.Size(215, 17), style=0)
+
+ self.ProductName = wx.TextCtrl(id=wxID_PROJECTDIALOGPRODUCTNAME,
+ name='ProductName', parent=self.MainPanel, pos=wx.Point(224, 144),
+ size=wx.Size(295, 24), style=0)
+
+ self.staticText5 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT5,
+ label='Product Version (required):', name='staticText5', parent=self.MainPanel,
+ pos=wx.Point(24, 184), size=wx.Size(215, 17), style=0)
+
+ self.ProductVersion = wx.TextCtrl(id=wxID_PROJECTDIALOGPRODUCTVERSION,
+ name='ProductVersion', parent=self.MainPanel, pos=wx.Point(224, 184),
+ size=wx.Size(295, 24), style=0)
+
+ self.staticText6 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT6,
+ label='Product Release (optional):', name='staticText6', parent=self.MainPanel,
+ pos=wx.Point(24, 224), size=wx.Size(215, 17), style=0)
+
+ self.ProductRelease = wx.TextCtrl(id=wxID_PROJECTDIALOGPRODUCTRELEASE,
+ name='ProductRelease', parent=self.MainPanel, pos=wx.Point(224, 224),
+ size=wx.Size(295, 24), style=0)
+
+ self.staticText7 = wx.StaticText(id=wxID_PROJECTDIALOGSTATICTEXT7,
+ label='Content Description (optional):', name='staticText7', parent=self.MainPanel,
+ pos=wx.Point(24, 264), size=wx.Size(215, 17), style=0)
+
+ self.ContentDescription = wx.TextCtrl(id=wxID_PROJECTDIALOGCONTENTDESCRIPTION,
+ name='ProductRelease', parent=self.MainPanel, pos=wx.Point(224, 264),
+ size=wx.Size(295, 120), style=wxTE_MULTILINE)
+
+ self._init_sizers()
+
+ def __init__(self, parent):
+ self._init_ctrls(parent)
+ self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
+ self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
+
+ EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK)
+
+ def OnOK(self, event):
+ error = []
+ if self.ProjectName.GetValue() == "":
+ error.append("Project Name")
+ if self.CompanyName.GetValue() == "":
+ error.append("Company Name")
+ if self.ProductName.GetValue() == "":
+ error.append("Product Name")
+ if self.ProductVersion.GetValue() == "":
+ error.append("Product Version")
+ if len(error) > 0:
+ text = ""
+ for i, item in enumerate(error):
+ if i == 0:
+ text += item
+ elif i == len(error) - 1:
+ text += " and %s"%item
+ else:
+ text += ", %s"%item
+ message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ else:
+ self.EndModal(wxID_OK)
+
+ def SetValues(self, values):
+ for item, value in values.items():
+ if item == "projectName":
+ self.ProjectName.SetValue(value)
+ elif item == "companyName":
+ self.CompanyName.SetValue(value)
+ elif item == "companyURL":
+ self.CompanyURL.SetValue(value)
+ elif item == "productName":
+ self.ProductName.SetValue(value)
+ elif item == "productVersion":
+ self.ProductVersion.SetValue(value)
+ elif item == "productRelease":
+ self.ProductRelease.SetValue(value)
+ elif item == "contentDescription":
+ self.ContentDescription.SetValue(value)
+
+ def GetValues(self):
+ values = {}
+ values["projectName"] = self.ProjectName.GetValue()
+ values["companyName"] = self.CompanyName.GetValue()
+ if self.CompanyURL.GetValue() != None:
+ values["companyURL"] = self.CompanyURL.GetValue()
+ values["productName"] = self.ProductName.GetValue()
+ values["productVersion"] = self.ProductVersion.GetValue()
+ if self.ProductRelease.GetValue() != None:
+ values["productRelease"] = self.ProductRelease.GetValue()
+ if self.ProductRelease.GetValue() != None:
+ values["contentDescription"] = self.ContentDescription.GetValue()
+ return values
+
+#-------------------------------------------------------------------------------
+# Create Pou Dialog
+#-------------------------------------------------------------------------------
+
+[wxID_POUDIALOG, wxID_POUDIALOGMAINPANEL, wxID_POUDIALOGPOUNAME,
+ wxID_POUDIALOGPOUTYPE, wxID_POUDIALOGLANGUAGE, wxID_POUDIALOGSTATICTEXT1,
+ wxID_POUDIALOGSTATICTEXT2, wxID_POUDIALOGSTATICTEXT3,
+] = [wx.NewId() for _init_ctrls in range(8)]
+
+class PouDialog(wx.Dialog):
+ def _init_coll_flexGridSizer1_Items(self, parent):
+ # generated method, don't edit
+
+ parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
+
+ def _init_sizers(self):
+ # generated method, don't edit
+ self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
+
+ self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
+
+ self.SetSizer(self.flexGridSizer1)
+
+ def _init_ctrls(self, prnt):
+ # generated method, don't edit
+ wx.Dialog.__init__(self, id=wxID_POUDIALOG,
+ name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223),
+ size=wx.Size(300, 200), style=wx.DEFAULT_DIALOG_STYLE,
+ title='Create a new project')
+ self.SetClientSize(wx.Size(300, 200))
+
+ self.MainPanel = wx.Panel(id=wxID_POUDIALOGMAINPANEL,
+ name='MainPanel', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL)
+ self.MainPanel.SetAutoLayout(True)
+
+ self.staticText1 = wx.StaticText(id=wxID_POUDIALOGSTATICTEXT1,
+ label='POU Name:', name='staticText1', parent=self.MainPanel,
+ pos=wx.Point(24, 24), size=wx.Size(95, 17), style=0)
+
+ self.PouName = wx.TextCtrl(id=wxID_POUDIALOGPOUNAME,
+ name='POUName', parent=self.MainPanel, pos=wx.Point(104, 24),
+ size=wx.Size(150, 24), style=0)
+
+ self.staticText2 = wx.StaticText(id=wxID_POUDIALOGSTATICTEXT2,
+ label='POU Type:', name='staticText2', parent=self.MainPanel,
+ pos=wx.Point(24, 64), size=wx.Size(95, 17), style=0)
+
+ self.PouType = wx.Choice(id=wxID_POUDIALOGPOUTYPE,
+ name='POUType', parent=self.MainPanel, pos=wx.Point(104, 64),
+ size=wx.Size(150, 24), style=0)
+ EVT_CHOICE(self, wxID_POUDIALOGPOUTYPE, self.OnTypeChanged)
+
+ self.staticText3 = wx.StaticText(id=wxID_POUDIALOGSTATICTEXT3,
+ label='Language:', name='staticText3', parent=self.MainPanel,
+ pos=wx.Point(24, 104), size=wx.Size(95, 17), style=0)
+
+ self.Language = wx.Choice(id=wxID_POUDIALOGLANGUAGE,
+ name='Language', parent=self.MainPanel, pos=wx.Point(104, 104),
+ size=wx.Size(150, 24), style=0)
+
+ self._init_sizers()
+
+ def __init__(self, parent):
+ self._init_ctrls(parent)
+ self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
+ self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
+
+ for option in ["function","functionBlock","program"]:
+ self.PouType.Append(option)
+ self.RefreshLanguage()
+
+ EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK)
+
+ def OnOK(self, event):
+ error = []
+ pou_name = self.PouName.GetValue()
+ if pou_name == "":
+ error.append("POU Name")
+ if self.PouType.GetStringSelection() == "":
+ error.append("POU Type")
+ if self.Language.GetStringSelection() == "":
+ error.append("Language")
+ if len(error) > 0:
+ text = ""
+ for i, item in enumerate(error):
+ if i == 0:
+ text += item
+ elif i == len(error) - 1:
+ text += " and %s"%item
+ else:
+ text += ", %s"%item
+ message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ elif not TestIdentifier(pou_name):
+ message = wxMessageDialog(self, "\"%s\" is not a valid identifier!"%pou_name, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ elif pou_name.upper() in IEC_KEYWORDS:
+ message = wxMessageDialog(self, "\"%s\" is a keyword. It can't be used!"%pou_name, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ elif pou_name.upper() in self.PouNames:
+ message = wxMessageDialog(self, "\"%s\" pou already exists!"%pou_name, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ else:
+ self.EndModal(wxID_OK)
+
+ def RefreshLanguage(self):
+ selection = self.Language.GetStringSelection()
+ self.Language.Clear()
+ for option in ["IL","ST","LD","FBD","SFC"]:
+ if option != "SFC" or self.PouType.GetStringSelection() == "program":
+ self.Language.Append(option)
+ if self.Language.FindString(selection) != wxNOT_FOUND:
+ self.Language.SetStringSelection(selection)
+
+ def OnTypeChanged(self, event):
+ self.RefreshLanguage()
+ event.Skip()
+
+ def SetPouNames(self, pou_names):
+ self.PouNames = [pou_name.upper() for pou_name in pou_names]
+
+ def SetValues(self, values):
+ for item, value in values.items():
+ if item == "pouName":
+ self.PouName.SetValue(value)
+ elif item == "pouType":
+ self.PouType.SetStringSelection(value)
+ elif item == "language":
+ self.Language.SetStringSelection(value)
+
+ def GetValues(self):
+ values = {}
+ values["pouName"] = self.PouName.GetValue()
+ values["pouType"] = self.PouType.GetStringSelection()
+ values["language"] = self.Language.GetStringSelection()
+ return values
+
+
+#-------------------------------------------------------------------------------
+# Create Pou Transition Dialog
+#-------------------------------------------------------------------------------
+
+[wxID_POUTRANSITIONDIALOG, wxID_POUTRANSITIONDIALOGMAINPANEL,
+ wxID_POUTRANSITIONDIALOGPOUNAME, wxID_POUTRANSITIONDIALOGTRANSITIONNAME,
+ wxID_POUTRANSITIONDIALOGLANGUAGE, wxID_POUTRANSITIONDIALOGSTATICTEXT1,
+ wxID_POUTRANSITIONDIALOGSTATICTEXT2, wxID_POUTRANSITIONDIALOGSTATICTEXT3,
+] = [wx.NewId() for _init_ctrls in range(8)]
+
+class PouTransitionDialog(wx.Dialog):
+ def _init_coll_flexGridSizer1_Items(self, parent):
+ # generated method, don't edit
+
+ parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
+
+ def _init_sizers(self):
+ # generated method, don't edit
+ self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
+
+ self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
+
+ self.SetSizer(self.flexGridSizer1)
+
+ def _init_ctrls(self, prnt):
+ # generated method, don't edit
+ wx.Dialog.__init__(self, id=wxID_POUTRANSITIONDIALOG,
+ name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223),
+ size=wx.Size(350, 200), style=wx.DEFAULT_DIALOG_STYLE,
+ title='Create a new project')
+ self.SetClientSize(wx.Size(350, 200))
+
+ self.MainPanel = wx.Panel(id=wxID_POUTRANSITIONDIALOGMAINPANEL,
+ name='MainPanel', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(350, 200), style=wx.TAB_TRAVERSAL)
+ self.MainPanel.SetAutoLayout(True)
+
+ self.staticText1 = wx.StaticText(id=wxID_POUTRANSITIONDIALOGSTATICTEXT1,
+ label='POU Name:', name='staticText1', parent=self.MainPanel,
+ pos=wx.Point(24, 24), size=wx.Size(145, 17), style=0)
+
+ self.PouName = wx.Choice(id=wxID_POUTRANSITIONDIALOGPOUNAME,
+ name='POUName', parent=self.MainPanel, pos=wx.Point(154, 24),
+ size=wx.Size(150, 24), style=0)
+
+ self.staticText2 = wx.StaticText(id=wxID_POUTRANSITIONDIALOGSTATICTEXT2,
+ label='Transition Name:', name='staticText2', parent=self.MainPanel,
+ pos=wx.Point(24, 64), size=wx.Size(145, 17), style=0)
+
+ self.TransitionName = wx.TextCtrl(id=wxID_POUTRANSITIONDIALOGTRANSITIONNAME,
+ name='TransitionName', parent=self.MainPanel, pos=wx.Point(154, 64),
+ size=wx.Size(150, 24), style=0)
+
+ self.staticText3 = wx.StaticText(id=wxID_POUTRANSITIONDIALOGSTATICTEXT3,
+ label='Language:', name='staticText3', parent=self.MainPanel,
+ pos=wx.Point(24, 104), size=wx.Size(145, 17), style=0)
+
+ self.Language = wx.Choice(id=wxID_POUTRANSITIONDIALOGLANGUAGE,
+ name='Language', parent=self.MainPanel, pos=wx.Point(154, 104),
+ size=wx.Size(150, 24), style=0)
+
+ self._init_sizers()
+
+ def __init__(self, parent):
+ self._init_ctrls(parent)
+ self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
+ self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
+
+ for option in ["IL","ST","LD","FBD"]:
+ self.Language.Append(option)
+
+ EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK)
+
+ def OnOK(self, event):
+ error = []
+ if self.PouName.GetStringSelection() == "":
+ error.append("POU Name")
+ if self.TransitionName.GetValue() == "":
+ error.append("Transition Name")
+ if self.Language.GetStringSelection() == "":
+ error.append("Language")
+ if len(error) > 0:
+ text = ""
+ for i, item in enumerate(error):
+ if i == 0:
+ text += item
+ elif i == len(error) - 1:
+ text += " and %s"%item
+ else:
+ text += ", %s"%item
+ message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ else:
+ self.EndModal(wxID_OK)
+
+ def SetPous(self, pous):
+ for pou in pous:
+ self.PouName.Append(pou)
+
+ def SetValues(self, values):
+ for item, value in values.items():
+ if item == "pouName":
+ self.PouName.SetStringSelection(value)
+ elif item == "transitionName":
+ self.TransitionName.SetValue(value)
+ elif item == "language":
+ self.Language.SetStringSelection(value)
+
+ def GetValues(self):
+ values = {}
+ values["pouName"] = self.PouName.GetStringSelection()
+ values["transitionName"] = self.TransitionName.GetValue()
+ values["language"] = self.Language.GetStringSelection()
+ return values
+
+#-------------------------------------------------------------------------------
+# Create Pou Action Dialog
+#-------------------------------------------------------------------------------
+
+[wxID_POUACTIONDIALOG, wxID_POUACTIONDIALOGMAINPANEL,
+ wxID_POUACTIONDIALOGPOUNAME, wxID_POUACTIONDIALOGACTIONNAME,
+ wxID_POUACTIONDIALOGLANGUAGE, wxID_POUACTIONDIALOGSTATICTEXT1,
+ wxID_POUACTIONDIALOGSTATICTEXT2, wxID_POUACTIONDIALOGSTATICTEXT3,
+] = [wx.NewId() for _init_ctrls in range(8)]
+
+class PouActionDialog(wx.Dialog):
+ def _init_coll_flexGridSizer1_Items(self, parent):
+ # generated method, don't edit
+
+ parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
+
+ def _init_sizers(self):
+ # generated method, don't edit
+ self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
+
+ self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
+
+ self.SetSizer(self.flexGridSizer1)
+
+ def _init_ctrls(self, prnt):
+ # generated method, don't edit
+ wx.Dialog.__init__(self, id=wxID_POUACTIONDIALOG,
+ name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223),
+ size=wx.Size(320, 200), style=wx.DEFAULT_DIALOG_STYLE,
+ title='Create a new project')
+ self.SetClientSize(wx.Size(320, 200))
+
+ self.MainPanel = wx.Panel(id=wxID_POUACTIONDIALOGMAINPANEL,
+ name='MainPanel', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(350, 200), style=wx.TAB_TRAVERSAL)
+ self.MainPanel.SetAutoLayout(True)
+
+ self.staticText1 = wx.StaticText(id=wxID_POUACTIONDIALOGSTATICTEXT1,
+ label='POU Name:', name='staticText1', parent=self.MainPanel,
+ pos=wx.Point(24, 24), size=wx.Size(145, 17), style=0)
+
+ self.PouName = wx.Choice(id=wxID_POUACTIONDIALOGPOUNAME,
+ name='POUName', parent=self.MainPanel, pos=wx.Point(124, 24),
+ size=wx.Size(150, 24), style=0)
+
+ self.staticText2 = wx.StaticText(id=wxID_POUACTIONDIALOGSTATICTEXT2,
+ label='Action Name:', name='staticText2', parent=self.MainPanel,
+ pos=wx.Point(24, 64), size=wx.Size(145, 17), style=0)
+
+ self.ActionName = wx.TextCtrl(id=wxID_POUACTIONDIALOGACTIONNAME,
+ name='ActionName', parent=self.MainPanel, pos=wx.Point(124, 64),
+ size=wx.Size(150, 24), style=0)
+
+ self.staticText3 = wx.StaticText(id=wxID_POUACTIONDIALOGSTATICTEXT3,
+ label='Language:', name='staticText3', parent=self.MainPanel,
+ pos=wx.Point(24, 104), size=wx.Size(145, 17), style=0)
+
+ self.Language = wx.Choice(id=wxID_POUACTIONDIALOGLANGUAGE,
+ name='Language', parent=self.MainPanel, pos=wx.Point(124, 104),
+ size=wx.Size(150, 24), style=0)
+
+ self._init_sizers()
+
+ def __init__(self, parent):
+ self._init_ctrls(parent)
+ self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
+ self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
+
+ for option in ["IL","ST","LD","FBD"]:
+ self.Language.Append(option)
+
+ EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK)
+
+ def OnOK(self, event):
+ error = []
+ if self.PouName.GetStringSelection() == "":
+ error.append("POU Name")
+ if self.ActionName.GetValue() == "":
+ error.append("Action Name")
+ if self.Language.GetStringSelection() == "":
+ error.append("Language")
+ if len(error) > 0:
+ text = ""
+ for i, item in enumerate(error):
+ if i == 0:
+ text += item
+ elif i == len(error) - 1:
+ text += " and %s"%item
+ else:
+ text += ", %s"%item
+ message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ else:
+ self.EndModal(wxID_OK)
+
+ def SetPous(self, pous):
+ for pou in pous:
+ self.PouName.Append(pou)
+
+ def SetValues(self, values):
+ for item, value in values.items():
+ if item == "pouName":
+ self.PouName.SetStringSelection(value)
+ elif item == "actionName":
+ self.ActionName.SetValue(value)
+ elif item == "language":
+ self.Language.SetStringSelection(value)
+
+ def GetValues(self):
+ values = {}
+ values["pouName"] = self.PouName.GetStringSelection()
+ values["actionName"] = self.ActionName.GetValue()
+ values["language"] = self.Language.GetStringSelection()
+ return values
+
+#-------------------------------------------------------------------------------
+# Pou Interface Dialog
+#-------------------------------------------------------------------------------
+
+class VariableTable(wxPyGridTableBase):
+
+ """
+ A custom wxGrid Table using user supplied data
+ """
+ def __init__(self, parent, data, colnames):
+ # The base class must be initialized *first*
+ wxPyGridTableBase.__init__(self)
+ self.data = data
+ self.colnames = colnames
+ self.Parent = parent
+ # XXX
+ # we need to store the row length and collength to
+ # see if the table has changed size
+ self._rows = self.GetNumberRows()
+ self._cols = self.GetNumberCols()
+
+ def GetNumberCols(self):
+ return len(self.colnames)
+
+ def GetNumberRows(self):
+ return len(self.data)
+
+ def GetColLabelValue(self, col):
+ if col < len(self.colnames):
+ return self.colnames[col]
+
+ def GetRowLabelValues(self, row):
+ return row
+
+ def GetValue(self, row, col):
+ if row < self.GetNumberRows():
+ name = str(self.data[row].get(self.GetColLabelValue(col), ""))
+ return name
+
+ def GetValueByName(self, row, colname):
+ return self.data[row].get(colname)
+
+ def SetValue(self, row, col, value):
+ if col < len(self.colnames):
+ self.data[row][self.GetColLabelValue(col)] = value
+
+ def ResetView(self, grid):
+ """
+ (wxGrid) -> Reset the grid view. Call this to
+ update the grid if rows and columns have been added or deleted
+ """
+ grid.BeginBatch()
+ for current, new, delmsg, addmsg in [
+ (self._rows, self.GetNumberRows(), wxGRIDTABLE_NOTIFY_ROWS_DELETED, wxGRIDTABLE_NOTIFY_ROWS_APPENDED),
+ (self._cols, self.GetNumberCols(), wxGRIDTABLE_NOTIFY_COLS_DELETED, wxGRIDTABLE_NOTIFY_COLS_APPENDED),
+ ]:
+ if new < current:
+ msg = wxGridTableMessage(self,delmsg,new,current-new)
+ grid.ProcessTableMessage(msg)
+ elif new > current:
+ msg = wxGridTableMessage(self,addmsg,new-current)
+ grid.ProcessTableMessage(msg)
+ self.UpdateValues(grid)
+ grid.EndBatch()
+
+ self._rows = self.GetNumberRows()
+ self._cols = self.GetNumberCols()
+ # update the column rendering scheme
+ self._updateColAttrs(grid)
+
+ # update the scrollbars and the displayed part of the grid
+ grid.AdjustScrollbars()
+ grid.ForceRefresh()
+
+ def UpdateValues(self, grid):
+ """Update all displayed values"""
+ # This sends an event to the grid table to update all of the values
+ msg = wxGridTableMessage(self, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES)
+ grid.ProcessTableMessage(msg)
+
+ def _updateColAttrs(self, grid):
+ """
+ wxGrid -> update the column attributes to add the
+ appropriate renderer given the column name.
+
+ Otherwise default to the default renderer.
+ """
+
+ for col in range(self.GetNumberCols()):
+ attr = wxGridCellAttr()
+ attr.SetAlignment(self.Parent.ColAlignements[col], wxALIGN_CENTRE)
+ grid.SetColAttr(col, attr)
+ grid.SetColSize(col, self.Parent.ColSizes[col])
+
+ typelist = None
+ accesslist = None
+ for row in range(self.GetNumberRows()):
+ for col in range(self.GetNumberCols()):
+ editor = None
+ renderer = None
+ colname = self.GetColLabelValue(col)
+ grid.SetReadOnly(row, col, False)
+ if colname in ["Name","Initial Value","Location"]:
+ editor = wxGridCellTextEditor()
+ renderer = wxGridCellStringRenderer()
+ elif colname == "Class":
+ if len(self.Parent.ClassList) == 1:
+ grid.SetReadOnly(row, col, True)
+ else:
+ editor = wxGridCellChoiceEditor()
+ editor.SetParameters(",".join(self.Parent.ClassList))
+ elif colname == "Type":
+ editor = wxGridCellChoiceEditor()
+ editor.SetParameters(self.Parent.TypeList)
+ elif colname in ["Retain", "Constant"]:
+ editor = wxGridCellChoiceEditor()
+ editor.SetParameters(self.Parent.OptionList)
+
+ grid.SetCellEditor(row, col, editor)
+ grid.SetCellRenderer(row, col, renderer)
+
+ grid.SetCellBackgroundColour(row, col, wxWHITE)
+
+ def SetData(self, data):
+ self.data = data
+
+ def GetData(self):
+ return self.data
+
+ def GetCurrentIndex(self):
+ return self.CurrentIndex
+
+ def SetCurrentIndex(self, index):
+ self.CurrentIndex = index
+
+ def AppendRow(self, row_content):
+ self.data.append(row_content)
+
+ def RemoveRow(self, row_index):
+ self.data.pop(row_index)
+
+ def MoveRow(self, row_index, move, grid):
+ new_index = max(0, min(row_index + move, len(self.data) - 1))
+ if new_index != row_index:
+ self.data.insert(new_index, self.data.pop(row_index))
+ grid.SetGridCursor(new_index, grid.GetGridCursorCol())
+
+ def Empty(self):
+ self.data = []
+ self.editors = []
+
+[wxID_EDITVARIABLEDIALOG, wxID_EDITVARIABLEDIALOGMAINPANEL,
+ wxID_EDITVARIABLEDIALOGVARIABLESGRID, wxID_EDITVARIABLEDIALOGRETURNTYPE,
+ wxID_EDITVARIABLEDIALOGCLASSFILTER, wxID_EDITVARIABLEDIALOGADDBUTTON,
+ wxID_EDITVARIABLEDIALOGDELETEBUTTON, wxID_EDITVARIABLEDIALOGUPBUTTON,
+ wxID_EDITVARIABLEDIALOGDOWNBUTTON, wxID_EDITVARIABLEDIALOGSTATICTEXT1,
+ wxID_EDITVARIABLEDIALOGSTATICTEXT2, wxID_EDITVARIABLEDIALOGSTATICTEXT3,
+] = [wx.NewId() for _init_ctrls in range(12)]
+
+class EditVariableDialog(wx.Dialog):
+ def _init_coll_flexGridSizer1_Items(self, parent):
+ # generated method, don't edit
+
+ parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
+
+ def _init_sizers(self):
+ # generated method, don't edit
+ self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
+
+ self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
+
+ self.SetSizer(self.flexGridSizer1)
+
+ def _init_ctrls(self, prnt, name):
+ # generated method, don't edit
+ wx.Dialog.__init__(self, id=wxID_EDITVARIABLEDIALOG,
+ name='EditVariableDialog', parent=prnt, pos=wx.Point(376, 223),
+ size=wx.Size(600, 440), style=wx.DEFAULT_DIALOG_STYLE,
+ title='Edit variables of %s'%name)
+ self.SetClientSize(wx.Size(600, 440))
+
+ self.MainPanel = wx.Panel(id=wxID_EDITVARIABLEDIALOGMAINPANEL,
+ name='MainPanel', parent=self, pos=wx.Point(0, 0),
+ size=wx.Size(600, 440), style=wx.TAB_TRAVERSAL)
+ self.MainPanel.SetAutoLayout(True)
+
+ self.staticText1 = wx.StaticText(id=wxID_EDITVARIABLEDIALOGSTATICTEXT1,
+ label='Return Type:', name='staticText1', parent=self.MainPanel,
+ pos=wx.Point(24, 29), size=wx.Size(95, 17), style=0)
+
+ self.ReturnType = wx.Choice(id=wxID_EDITVARIABLEDIALOGRETURNTYPE,
+ name='ReturnType', parent=self.MainPanel, pos=wx.Point(124, 24),
+ size=wx.Size(145, 24), style=0)
+
+ self.staticText2 = wx.StaticText(id=wxID_EDITVARIABLEDIALOGSTATICTEXT2,
+ label='Class Filter:', name='staticText2', parent=self.MainPanel,
+ pos=wx.Point(324, 29), size=wx.Size(95, 17), style=0)
+
+ self.ClassFilter = wx.Choice(id=wxID_EDITVARIABLEDIALOGCLASSFILTER,
+ name='ClassFilter', parent=self.MainPanel, pos=wx.Point(424, 24),
+ size=wx.Size(145, 24), style=0)
+ EVT_CHOICE(self, wxID_EDITVARIABLEDIALOGCLASSFILTER, self.OnClassFilter)
+
+ self.staticText3 = wx.StaticText(id=wxID_EDITVARIABLEDIALOGSTATICTEXT3,
+ label='Variables:', name='staticText3', parent=self.MainPanel,
+ pos=wx.Point(24, 60), size=wx.Size(95, 17), style=0)
+
+ self.VariablesGrid = wx.grid.Grid(id=wxID_EDITVARIABLEDIALOGVARIABLESGRID,
+ name='VariablesGrid', parent=self.MainPanel, pos=wx.Point(24, 80),
+ size=wx.Size(550, 250), style=wxVSCROLL)
+ self.VariablesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
+ 'Sans'))
+ self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
+ False, 'Sans'))
+ self.VariablesGrid.DisableDragGridSize()
+ self.VariablesGrid.EnableScrolling(False, True)
+
+ self.AddButton = wx.Button(id=wxID_EDITVARIABLEDIALOGADDBUTTON, label='Add',
+ name='AddButton', parent=self.MainPanel, pos=wx.Point(345, 340),
+ size=wx.Size(72, 32), style=0)
+ EVT_BUTTON(self, wxID_EDITVARIABLEDIALOGADDBUTTON, self.OnAddButton)
+
+ self.DeleteButton = wx.Button(id=wxID_EDITVARIABLEDIALOGDELETEBUTTON, label='Delete',
+ name='DeleteButton', parent=self.MainPanel, pos=wx.Point(425, 340),
+ size=wx.Size(72, 32), style=0)
+ EVT_BUTTON(self, wxID_EDITVARIABLEDIALOGDELETEBUTTON, self.OnDeleteButton)
+
+ self.UpButton = wx.Button(id=wxID_EDITVARIABLEDIALOGUPBUTTON, label='^',
+ name='UpButton', parent=self.MainPanel, pos=wx.Point(505, 340),
+ size=wx.Size(32, 32), style=0)
+ EVT_BUTTON(self, wxID_EDITVARIABLEDIALOGUPBUTTON, self.OnUpButton)
+
+ self.DownButton = wx.Button(id=wxID_EDITVARIABLEDIALOGDOWNBUTTON, label='v',
+ name='DownButton', parent=self.MainPanel, pos=wx.Point(545, 340),
+ size=wx.Size(32, 32), style=0)
+ EVT_BUTTON(self, wxID_EDITVARIABLEDIALOGDOWNBUTTON, self.OnDownButton)
+
+ self._init_sizers()
+
+ def __init__(self, parent, name, pou_type, filter = "All"):
+ self._init_ctrls(parent, name)
+ self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
+ self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
+ self.Filter = filter
+ self.FilterChoices = []
+ self.FilterChoiceTransfer = {"All" : "All", "Interface" : "Interface",
+ "Input" : " Input", "Output" : " Output", "InOut" : " InOut",
+ "External" : " External", "Variables" : "Variables", "Local" : " Local",
+ "Temp" : " Temp", "Global" : "Global", "Access" : "Access"}
+
+ if pou_type:
+ self.DefaultValue = {"Name" : "", "Class" : "Input", "Type" : "INT", "Location" : "", "Initial Value" : "", "Retain" : "No", "Constant" : "No"}
+ else:
+ self.DefaultValue = {"Name" : "", "Class" : "Global", "Type" : "INT", "Location" : "", "Initial Value" : "", "Retain" : "No", "Constant" : "No"}
+ if not pou_type or pou_type == "program":
+ self.Table = VariableTable(self, [], ["Name", "Class", "Type", "Location", "Initial Value", "Retain", "Constant"])
+ if pou_type:
+ self.FilterChoices = ["All","Interface"," Input"," Output"," InOut"," External","Variables"," Local"," Temp","Global","Access"]
+ else:
+ self.FilterChoices = ["All","Global","Access"]
+ self.ColSizes = [80, 70, 80, 80, 80, 60, 70]
+ self.ColAlignements = [wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_CENTER, wxALIGN_CENTER]
+ else:
+ self.Table = VariableTable(self, [], ["Name", "Class", "Type", "Initial Value", "Retain", "Constant"])
+ self.FilterChoices = ["All","Interface"," Input"," Output"," InOut"," External","Variables"," Local"," Temp"]
+ self.ColSizes = [120, 70, 80, 120, 60, 70]
+ self.ColAlignements = [wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_CENTER, wxALIGN_CENTER]
+ for choice in self.FilterChoices:
+ self.ClassFilter.Append(choice)
+ self.ClassFilter.SetStringSelection(self.FilterChoiceTransfer[self.Filter])
+ self.RefreshTypeList()
+ self.RefreshUpDownButtons()
+
+ self.OptionList = "Yes,No"
+ self.TypeList = ""
+ for value in TypeHierarchy.keys():
+ if not value.startswith("ANY"):
+ self.TypeList += "%s,"%value
+ self.TypeList = self.TypeList[:-1]
+
+ if pou_type == "function":
+ for value in TypeHierarchy.keys():
+ if not value.startswith("ANY"):
+ self.ReturnType.Append(value)
+ self.ReturnType.Enable(True)
+ else:
+ self.ReturnType.Enable(False)
+ self.staticText2.Hide()
+ self.ReturnType.Hide()
+
+ self.VariablesGrid.SetTable(self.Table)
+ self.VariablesGrid.SetRowLabelSize(0)
+
+ self.Table.ResetView(self.VariablesGrid)
+
+ EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK)
+
+ def OnOK(self, event):
+ self.VariablesGrid.SetGridCursor(0, 0)
+ error = []
+ if self.ReturnType.IsEnabled() and self.ReturnType.GetStringSelection() == "":
+ error.append("Return Type")
+ if len(error) > 0:
+ text = ""
+ for i, item in enumerate(error):
+ if i == 0:
+ text += item
+ elif i == len(error) - 1:
+ text += " and %s"%item
+ else:
+ text += ", %s"%item
+ message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+ else:
+ self.EndModal(wxID_OK)
+
+ def OnClassFilter(self, event):
+ reverse_transfer = {}
+ for filter, choice in self.FilterChoiceTransfer.items():
+ reverse_transfer[choice] = filter
+ self.Filter = reverse_transfer[self.ClassFilter.GetStringSelection()]
+ self.RefreshTypeList()
+ self.RefreshValues()
+ self.RefreshUpDownButtons()
+ event.Skip()
+
+ def RefreshTypeList(self):
+ if self.Filter == "All":
+ self.ClassList = [choice for choice in self.FilterChoices if choice not in ["All","Interface","Variables"]]
+ elif self.Filter == "Interface":
+ self.ClassList = ["Input","Output","InOut","External"]
+ elif self.Filter == "Variables":
+ self.ClassList = ["Local","Temp"]
+ else:
+ self.ClassList = [self.Filter]
+
+ def RefreshUpDownButtons(self):
+ if self.Filter == "All":
+ self.UpButton.Enable(True)
+ self.DownButton.Enable(True)
+ else:
+ self.UpButton.Enable(False)
+ self.DownButton.Enable(False)
+
+ def OnAddButton(self, event):
+ self.Table.AppendRow(self.DefaultValue.copy())
+ self.Table.ResetView(self.VariablesGrid)
+ event.Skip()
+
+ def OnDeleteButton(self, event):
+ row = self.VariablesGrid.GetGridCursorRow()
+ self.Table.RemoveRow(row)
+ self.Table.ResetView(self.VariablesGrid)
+ event.Skip()
+
+ def OnUpButton(self, event):
+ row = self.VariablesGrid.GetGridCursorRow()
+ self.Table.MoveRow(row, -1, self.VariablesGrid)
+ self.Table.ResetView(self.VariablesGrid)
+ event.Skip()
+
+ def OnDownButton(self, event):
+ row = self.VariablesGrid.GetGridCursorRow()
+ self.Table.MoveRow(row, 1, self.VariablesGrid)
+ self.Table.ResetView(self.VariablesGrid)
+ event.Skip()
+
+ def SetValues(self, values):
+ for item, value in values.items():
+ if item == "returnType" and value and self.ReturnType.IsEnabled():
+ self.ReturnType.SetStringSelection(value)
+ if item == "data":
+ self.Values = value
+ self.RefreshValues()
+
+ def RefreshValues(self):
+ data = []
+ for variable in self.Values:
+ if variable["Class"] in self.ClassList:
+ data.append(variable)
+ self.Table.SetData(data)
+ self.Table.ResetView(self.VariablesGrid)
+
+ def GetValues(self):
+ values = {}
+ if self.ReturnType.IsEnabled():
+ values["returnType"] = self.ReturnType.GetStringSelection()
+ values["data"] = self.Table.GetData()
+ return values
+
+#-------------------------------------------------------------------------------
+# Exception Handler
+#-------------------------------------------------------------------------------
+
+Max_Traceback_List_Size = 20
+
+def Display_Exception_Dialog(e_type,e_value,e_tb):
+ trcbck_lst = []
+ for i,line in enumerate(traceback.extract_tb(e_tb)):
+ trcbck = " " + str(i+1) + ". "
+ if line[0].find(os.getcwd()) == -1:
+ trcbck += "file : " + str(line[0]) + ", "
+ else:
+ trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", "
+ trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2])
+ trcbck_lst.append(trcbck)
+
+ # Allow clicking....
+ cap = wx.Window_GetCapture()
+ if cap:
+ cap.ReleaseMouse()
+
+ dlg = wx.SingleChoiceDialog(None,
+ """
+An error happens.
+
+Click on OK for saving an error report.
+
+Please contact LOLITech at:
++33 (0)3 29 52 95 67
+bugs_PLCOpenEditor@lolitech.fr
+
+
+Error:
+""" +
+ str(e_type) + " : " + str(e_value),
+ "Error",
+ trcbck_lst)
+ try:
+ res = (dlg.ShowModal() == wx.ID_OK)
+ finally:
+ dlg.Destroy()
+
+ return res
+
+def Display_Error_Dialog(e_value):
+ message = wxMessageDialog(None, str(e_value), "Error", wxOK|wxICON_ERROR)
+ message.ShowModal()
+ message.Destroy()
+
+def get_last_traceback(tb):
+ while tb.tb_next:
+ tb = tb.tb_next
+ return tb
+
+
+def format_namespace(d, indent=' '):
+ return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()])
+
+
+ignored_exceptions = [] # a problem with a line in a module is only reported once per session
+
+def wxAddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]):
+
+ def handle_exception(e_type, e_value, e_traceback):
+ traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func
+ last_tb = get_last_traceback(e_traceback)
+ ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno)
+ if str(e_value).startswith("!!!"):
+ Display_Error_Dialog(e_value)
+ elif ex not in ignored_exceptions:
+ result = Display_Exception_Dialog(e_type,e_value,e_traceback)
+ if result:
+ ignored_exceptions.append(ex)
+ info = {
+ 'app-title' : wx.GetApp().GetAppName(), # app_title
+ 'app-version' : app_version,
+ 'wx-version' : wx.VERSION_STRING,
+ 'wx-platform' : wx.Platform,
+ 'python-version' : platform.python_version(), #sys.version.split()[0],
+ 'platform' : platform.platform(),
+ 'e-type' : e_type,
+ 'e-value' : e_value,
+ 'date' : time.ctime(),
+ 'cwd' : os.getcwd(),
+ }
+ if e_traceback:
+ info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value)
+ last_tb = get_last_traceback(e_traceback)
+ exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred
+ info['locals'] = format_namespace(exception_locals)
+ if 'self' in exception_locals:
+ info['self'] = format_namespace(exception_locals['self'].__dict__)
+
+ output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w')
+ lst = info.keys()
+ lst.sort()
+ for a in lst:
+ output.write(a+":\n"+str(info[a])+"\n\n")
+
+ #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args)
+ sys.excepthook = handle_exception
+
+if __name__ == '__main__':
+ app = wxPySimpleApp()
+ wxInitAllImageHandlers()
+
+ # Install a exception handle for bug reports
+ wxAddExceptHook(os.getcwd(),__version__)
+
+ frame = PLCOpenEditor(None)
+
+ frame.Show()
+ app.MainLoop()
+