--- a/PLCOpenEditor.py Fri Jul 24 12:29:48 2009 +0200
+++ b/PLCOpenEditor.py Fri Jul 24 12:49:57 2009 +0200
@@ -64,9 +64,11 @@
ID_PLCOPENEDITORLDTOOLBAR,
] = [wx.NewId() for _init_ctrls in range(17)]
+# Define PLCOpenEditor FileMenu extra items id
[ID_PLCOPENEDITORFILEMENUGENERATE,
] = [wx.NewId() for _init_coll_FileMenu_Items in range(1)]
+# Define PLCOpenEditor EditMenu extra items id
[ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, ID_PLCOPENEDITOREDITMENUADDDATATYPE,
ID_PLCOPENEDITOREDITMENUADDFUNCTION, ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK,
ID_PLCOPENEDITOREDITMENUADDPROGRAM, ID_PLCOPENEDITOREDITMENUADDCONFIGURATION,
@@ -77,7 +79,7 @@
# ToolBars definitions
#-------------------------------------------------------------------------------
-
+# Define PLCOpenEditor Toolbar items id
[ID_PLCOPENEDITORTOOLBARSELECTION, ID_PLCOPENEDITORTOOLBARCOMMENT,
ID_PLCOPENEDITORTOOLBARVARIABLE, ID_PLCOPENEDITORTOOLBARBLOCK,
ID_PLCOPENEDITORTOOLBARCONNECTION, ID_PLCOPENEDITORTOOLBARWIRE,
@@ -89,6 +91,14 @@
ID_PLCOPENEDITORTOOLBARJUMP,
] = [wx.NewId() for _init_coll_DefaultToolBar_Items in range(17)]
+# Define behaviour of each Toolbar item according to current POU body type
+# Informations meaning are in this order:
+# - Item is toggled
+# - PLCOpenEditor mode where item is displayed (could be more then one)
+# - Item id
+# - Item callback function name
+# - Item icon filename
+# - Item tooltip text
ToolBarItems = {
"FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE,
ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool",
@@ -169,12 +179,56 @@
"IL" : []
}
+#-------------------------------------------------------------------------------
+# Helper Functions
+#-------------------------------------------------------------------------------
+
+# Compatibility function for wx versions < 2.6
def AppendMenu(parent, help, id, kind, text):
if wx.VERSION >= (2, 6, 0):
parent.Append(help=help, id=id, kind=kind, text=text)
else:
parent.Append(helpString=help, id=id, kind=kind, item=text)
+[TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE,
+ INSTANCESTREE, LIBRARYTREE, SCALING
+] = [wx.NewId() for _refresh_elements in range(9)]
+
+def GetShortcutKeyCallbackFunction(viewer_function):
+ def ShortcutKeyFunction(self, event):
+ control = self.FindFocus()
+ if isinstance(control, (Viewer, TextViewer)):
+ getattr(control, viewer_function)()
+ elif isinstance(control, wx.TextCtrl):
+ control.ProcessEvent(event)
+ event.Skip()
+ return ShortcutKeyFunction
+
+def GetParentName(tree, item, parent_type):
+ parent_item = tree.GetItemParent(item)
+ parent_item_type = tree.GetPyData(parent_item)
+ while parent_item_type != parent_type:
+ parent_item = tree.GetItemParent(parent_item)
+ parent_item_type = tree.GetPyData(parent_item)
+ return tree.GetItemText(parent_item)
+
+def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None):
+ def DeleteElementFunction(self, selected):
+ name = self.TypesTree.GetItemText(selected)
+ if check_function is None or not check_function(self.Controler, name, self.Debug):
+ if parent_type is not None:
+ parent_name = GetParentName(self.TypesTree, selected, parent_type)
+ remove_function(self.Controler, parent_name, name)
+ else:
+ remove_function(self.Controler, name)
+ else:
+ self.ShowErrorMessage("\"%s\" is used by one or more POUs. It can't be removed!"%name)
+ return DeleteElementFunction
+
+#-------------------------------------------------------------------------------
+# PLCOpenEditor Main Class
+#-------------------------------------------------------------------------------
+
class PLCOpenEditor(wx.Frame):
# Compatibility function for wx versions < 2.6
@@ -430,6 +484,10 @@
name='InstancesTree', parent=self.TreeNoteBook,
pos=wx.Point(0, 0), size=wx.Size(0, 0),
style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER)
+
+ self.TabsImageList = wx.ImageList(16, 31)
+ self.TabsImageListIndexes = {}
+
if self.Debug:
if wx.VERSION >= (2, 6, 0):
self.InstancesTree.Bind(wx.EVT_RIGHT_UP, self.OnInstancesTreeRightUp)
@@ -540,9 +598,7 @@
self.TabsOpened = wx.Notebook(id=ID_PLCOPENEDITORTABSOPENED,
name='TabsOpened', parent=self.ThirdSplitter, pos=wx.Point(0,
0), size=wx.Size(0, 0), style=0)
- self.TabsImageList = wx.ImageList(16, 31)
self.TabsOpened.SetImageList(self.TabsImageList)
- self.TabsImageListIndexes = {}
if wx.VERSION >= (2, 6, 0):
self.TabsOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,
self.OnPouSelectedChanged, id=ID_PLCOPENEDITORTABSOPENED)
@@ -579,11 +635,19 @@
if USE_AUI:
self.AUIManager.Update()
+ ## Constructor of the PLCOpenEditor class.
+ # @param parent The parent window.
+ # @param controler The controler been used by PLCOpenEditor (default: None).
+ # @param fileOpen The filepath to open if no controler defined (default: None).
+ # @param debug The filepath to open if no controler defined (default: False).
def __init__(self, parent, controler = None, fileOpen = None, debug = False):
+ # Variable indicating that PLCOpenEditor was opened with a defined controler
self.ModeSolo = controler == None
self.Debug = debug
if self.ModeSolo:
+ # If no controler defined, create a new one
self.Controler = PLCControler()
+ # Open the filepath if defined
if fileOpen is not None:
self.Controler.OpenXMLFile(fileOpen)
else:
@@ -591,16 +655,18 @@
self._init_ctrls(parent)
- self.SetIcon(wx.Icon(os.path.join(CWD,"Images","poe.ico"),wx.BITMAP_TYPE_ICO))
-
- self.TypesTreeImageList = wx.ImageList(16, 16)
- self.InstancesTreeImageList = wx.ImageList(16, 16)
- self.TypesTreeImageDict = {}
- self.InstancesTreeImageDict = {}
+ # Define PLCOpenEditor icon
+ self.SetIcon(wx.Icon(os.path.join(CWD,"Images", "poe.ico"),wx.BITMAP_TYPE_ICO))
+
+ # Define Tree item icon list
+ self.TreeImageList = wx.ImageList(16, 16)
+ self.TreeImageDict = {}
+
+ # Icons for languages
for language in LANGUAGES:
- self.TypesTreeImageDict[language]=self.TypesTreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%language)))
- self.InstancesTreeImageDict[language]=self.InstancesTreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%language)))
-
+ self.TreeImageDict[language]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%language)))
+
+ # Icons for other items
for imgname, itemtype in [
#editables
("PROJECT", ITEM_PROJECT),
@@ -628,10 +694,11 @@
("CONFIGURATIONS", ITEM_CONFIGURATIONS),
("RESOURCES", ITEM_RESOURCES),
("PROPERTIES", ITEM_PROPERTIES)]:
- self.TypesTreeImageDict[itemtype]=self.TypesTreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname)))
- self.InstancesTreeImageDict[itemtype]=self.InstancesTreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname)))
- self.TypesTree.AssignImageList(self.TypesTreeImageList)
- self.InstancesTree.AssignImageList(self.InstancesTreeImageList)
+ self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname)))
+
+ # Assign icon list to TreeCtrls
+ self.TypesTree.SetImageList(self.TreeImageList)
+ self.InstancesTree.SetImageList(self.TreeImageList)
self.CurrentToolBar = []
self.CurrentLanguage = ""
@@ -642,6 +709,7 @@
if USE_AUI:
self.AuiTabCtrl = []
+ # Initialize Printing configuring elements
self.PrintData = wx.PrintData()
self.PrintData.SetPaperId(wx.PAPER_A4)
self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER)
@@ -649,41 +717,41 @@
self.PageSetupData.SetMarginTopLeft(wx.Point(10, 15))
self.PageSetupData.SetMarginBottomRight(wx.Point(10, 20))
+ # Refresh elements that need to
if not self.ModeSolo or fileOpen is not None:
- self.RefreshTypesTree()
- self.RefreshInstancesTree()
- self.RefreshLibraryTree()
-
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshDisplayMenu()
- self.RefreshTitle()
- self.RefreshToolBar()
-
- def ResetSelectedItem(self):
- self.SelectedItem = None
-
+ self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
+
+
+#-------------------------------------------------------------------------------
+# General Functions
+#-------------------------------------------------------------------------------
+
+ ## Call PLCOpenEditor refresh functions.
+ # @param elements List of elements to refresh.
+ def _Refresh(self, *elements):
+ for element in elements:
+ self.RefreshFunctions[element](self)
+
+ ## Callback function when AUINotebook Page closed with CloseButton
+ # @param event AUINotebook Event.
def OnPageClose(self, event):
+ # Get Selected Tab
selected = event.GetSelection()
if selected >= 0:
+ # Remove corresponding VariablePanel
if not self.Debug:
tagname = self.TabsOpened.GetPage(selected).GetTagName()
self.VariablePanelIndexer.RemoveVariablePanel(tagname)
+ # Refresh Tab selection
if self.TabsOpened.GetPageCount() > 0:
new_index = min(selected, self.TabsOpened.GetPageCount() - 1)
self.TabsOpened.SetSelection(new_index)
if not self.Debug:
tagname = self.TabsOpened.GetPage(new_index).GetTagName()
self.VariablePanelIndexer.ChangeVariablePanel(tagname)
- self.RefreshTitle()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshDisplayMenu()
- self.RefreshToolBar()
- wx.CallAfter(self.RefreshTabCtrlEvent)
- event.Skip()
-
- def OnPageDragged(self, event):
+ # Refresh all window elements that have changed
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
wx.CallAfter(self.RefreshTabCtrlEvent)
event.Skip()
@@ -731,12 +799,8 @@
new_values["creationDateTime"] = old_values["creationDateTime"]
if new_values != old_values:
self.Controler.SetProjectProperties(None, new_values)
- self.RefreshTitle()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshDisplayMenu()
- self.RefreshTypesTree()
- self.RefreshScaling()
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU,
+ TYPESTREE, INSTANCESTREE, SCALING)
dialog.Destroy()
def OnCloseFrame(self, event):
@@ -744,83 +808,106 @@
self.AUIManager.UnInit()
self._onclose()
event.Skip()
- elif not self.Controler.ProjectIsSaved():
- dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
- answer = dialog.ShowModal()
- dialog.Destroy()
- if answer == wx.ID_YES:
- self.SaveProject()
- event.Skip()
- elif answer == wx.ID_NO:
- self.Controler.Reset()
- self.AUIManager.UnInit()
- event.Skip()
+ elif self.CheckSaveBeforeClosing():
+ event.Skip()
+ else:
+ event.Veto()
+
+#-------------------------------------------------------------------------------
+# Notebook Unified Functions
+#-------------------------------------------------------------------------------
+
+ ## Function that generate bitmap for
+ # for wx.aui.AUINotebook.
+ # @param window Panel to display in tab.
+ # @param text title for the tab ctrl.
+ def GenerateBitmap(self, icon1_name, icon2_name = None):
+ # Find index of bitmap if already created
+ index = self.TabsImageListIndexes.get((icon1_name, icon2_name), None)
+ # Return index or bitmap if found
+ if index is not None:
+ if USE_AUI:
+ return self.TabsImageList.GetBitmap(index)
else:
- event.Veto()
- else:
- event.Skip()
-
-#-------------------------------------------------------------------------------
-# Notebook Unified Functions
-#-------------------------------------------------------------------------------
-
- def GenerateBitmap(self, icon1_name, icon2_name = None):
- if not USE_AUI:
- index = self.TabsImageListIndexes.get((icon1_name, icon2_name), None)
- if index is not None:
return index
if icon2_name is None:
+ # Bitmap with only one icon
tmp_bitmap = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon1_name))
else:
+ # Bitmap with two icon
icon1 = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon1_name))
icon2 = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon2_name))
+ # Calculate bitmap size
width = icon1.GetWidth() + icon2.GetWidth() - 1
height = max(icon1.GetHeight(), icon2.GetHeight())
+ # Create bitmap with both icons
tmp_bitmap = wx.EmptyBitmap(width, height)
dc = wx.MemoryDC()
dc.SelectObject(tmp_bitmap)
dc.Clear()
dc.DrawBitmap(icon1, 0, 0)
dc.DrawBitmap(icon2, icon1.GetWidth() - 1, 0)
+ # Store bitmap in ImageList
+ index = self.TabsImageList.Add(tmp_bitmap)
+ # Save bitmap index in ImageList in dictionary
+ self.TabsImageListIndexes[(icon1_name, icon2_name)] = index
if USE_AUI:
return tmp_bitmap
else:
- index = self.TabsImageList.Add(tmp_bitmap)
- self.TabsImageListIndexes[(icon1_name, icon2_name)] = index
return index
+ ## Function that add a tab in Notebook, calling refresh for tab DClick event
+ # for wx.aui.AUINotebook.
+ # @param window Panel to display in tab.
+ # @param text title for the tab ctrl.
def AddPage(self, window, text):
self.TabsOpened.AddPage(window, text)
self.RefreshTabCtrlEvent()
- def RefreshTabCtrlEvent(self):
- if USE_AUI:
- auitabctrl = []
- for child in self.TabsOpened.GetChildren():
- if isinstance(child, wx.aui.AuiTabCtrl):
- auitabctrl.append(child)
- if child not in self.AuiTabCtrl:
- child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child))
- self.AuiTabCtrl = auitabctrl
- if self.TabsOpened.GetPageCount() == 0:
- pane = self.AUIManager.GetPane(self.TabsOpened)
- if pane.IsMaximized():
- self.AUIManager.RestorePane(pane)
- self.AUIManager.Update()
-
+ ## Function that fix difference in deleting all tabs between
+ # wx.Notebook and wx.aui.AUINotebook.
def DeleteAllPages(self):
if USE_AUI:
for idx in xrange(self.TabsOpened.GetPageCount()):
self.TabsOpened.DeletePage(0)
else:
self.TabsOpened.DeleteAllPages()
-
+ self.RefreshTabCtrlEvent()
+
+ ## Function that fix difference in setting picture on tab between
+ # wx.Notebook and wx.aui.AUINotebook.
+ # @param idx Tab index.
+ # @param bitmap wx.Bitmap to define on tab.
+ # @return True if operation succeeded
def SetPageBitmap(self, idx, bitmap):
if USE_AUI:
return self.TabsOpened.SetPageBitmap(idx, bitmap)
else:
return self.TabsOpened.SetPageImage(idx, bitmap)
+#-------------------------------------------------------------------------------
+# Dialog Message Functions
+#-------------------------------------------------------------------------------
+
+ ## Function displaying an Error dialog in PLCOpenEditor.
+ # @param message The message to display.
+ def ShowErrorMessage(self, message):
+ dialog = wx.MessageDialog(self, message, "Error", wx.OK|wx.ICON_ERROR)
+ dialog.ShowModal()
+ dialog.Destroy()
+
+ ## Function displaying an Error dialog in PLCOpenEditor.
+ # @return False if closing cancelled.
+ def CheckSaveBeforeClosing(self):
+ if not self.Controler.ProjectIsSaved():
+ dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
+ answer = dialog.ShowModal()
+ dialog.Destroy()
+ if answer == wx.ID_YES:
+ self.SaveProject()
+ elif answer == wx.ID_CANCEL:
+ return False
+ return True
#-------------------------------------------------------------------------------
# File Menu Functions
@@ -871,23 +958,13 @@
if dialog.ShowModal() == wx.ID_OK:
properties = dialog.GetValues()
self.Controler.CreateNewProject(properties)
- self.RefreshTitle()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshTypesTree()
- self.RefreshInstancesTree()
- self.RefreshLibraryTree()
+ self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE,
+ LIBRARYTREE)
event.Skip()
def OnOpenProjectMenu(self, event):
- if not self.Controler.ProjectIsSaved():
- dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
- answer = dialog.ShowModal()
- dialog.Destroy()
- if answer == wx.ID_YES:
- self.SaveProject()
- elif answer == wx.ID_CANCEL:
- return
+ if not self.CheckSaveBeforeClosing():
+ return
filepath = self.Controler.GetFilePath()
if filepath != "":
directory = os.path.dirname(filepath)
@@ -900,13 +977,8 @@
self.DeleteAllPages()
self.VariablePanelIndexer.RemoveAllPanels()
self.Controler.OpenXMLFile(filepath)
- self.RefreshTypesTree()
- self.RefreshInstancesTree()
- self.RefreshLibraryTree()
- self.RefreshTitle()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshToolBar()
+ self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
dialog.Destroy()
event.Skip()
@@ -923,29 +995,18 @@
if not self.Debug:
tagname = self.TabsOpened.GetPage(new_index).GetTagName()
self.VariablePanelIndexer.ChangeVariablePanel(tagname)
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshToolBar()
+ self._Refresh(TOOLBAR, FILEMENU, EDITMENU)
event.Skip()
def OnCloseProjectMenu(self, event):
- if not self.Controler.ProjectIsSaved():
- dialog = wx.MessageDialog(self, "There are changes, do you want to save?", "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
- answer = dialog.ShowModal()
- dialog.Destroy()
- if answer == wx.ID_YES:
- self.SaveProject()
- elif answer == wx.ID_CANCEL:
- return
+ if not self.CheckSaveBeforeClosing():
+ return
self.DeleteAllPages()
self.VariablePanelIndexer.RemoveAllPanels()
self.TypesTree.DeleteAllItems()
self.InstancesTree.DeleteAllItems()
self.Controler.Reset()
- self.RefreshTitle()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshToolBar()
+ self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU)
event.Skip()
def OnSaveProjectMenu(self, event):
@@ -1002,13 +1063,9 @@
if os.path.isdir(os.path.dirname(filepath)):
result = self.Controler.SaveXMLFile(filepath)
if not result:
- message = wx.MessageDialog(self, "Can't save project to file %s!"%filepath, "Error", wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ self.ShowErrorMessage("Can't save project to file %s!"%filepath)
else:
- message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ self.ShowErrorMessage("\"%s\" is not a valid folder!"%os.path.dirname(filepath))
self.RefreshTitle()
dialog.Destroy()
@@ -1051,7 +1108,7 @@
printout = GraphicPrintout(self.TabsOpened.GetPage(selected), page_size, margins)
if not printer.Print(self, printout, True):
- wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK)
+ self.ShowErrorMessage("There was a problem printing.\nPerhaps your current printer is not set correctly?")
printout.Destroy()
event.Skip()
@@ -1101,8 +1158,7 @@
self.EditMenu.Enable(wx.ID_ADD, False)
self.EditMenu.Enable(wx.ID_DELETE, False)
- def OnUndoMenu(self, event):
- self.Controler.LoadPrevious()
+ def CloseTabsWithoutModel(self):
idxs = range(self.TabsOpened.GetPageCount())
idxs.reverse()
for idx in idxs:
@@ -1110,70 +1166,32 @@
if self.Controler.GetEditedElement(tagname, self.Debug) is None:
self.VariablePanelIndexer.RemoveVariablePanel(tagname)
self.TabsOpened.DeletePage(idx)
- selected = self.TabsOpened.GetSelection()
- if selected != -1:
- window = self.TabsOpened.GetPage(selected)
- window.RefreshView()
- self.VariablePanelIndexer.RefreshVariablePanel(window.GetTagName())
- self.RefreshTitle()
- self.RefreshEditMenu()
- self.RefreshTypesTree()
- self.RefreshInstancesTree()
- self.RefreshLibraryTree()
- self.RefreshScaling()
+
+ def OnUndoMenu(self, event):
+ self.Controler.LoadPrevious()
+ self.CloseTabsWithoutModel()
+ self.RefreshEditor()
+ self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE,
+ SCALING)
event.Skip()
def OnRedoMenu(self, event):
self.Controler.LoadNext()
- idxs = range(self.TabsOpened.GetPageCount())
- idxs.reverse()
- for idx in idxs:
- tagname = self.TabsOpened.GetPage(idx).GetTagName()
- if self.Controler.GetEditedElement(tagname, self.Debug) is None:
- self.VariablePanelIndexer.RemoveVariablePanel(tagname)
- self.TabsOpened.DeletePage(idx)
- selected = self.TabsOpened.GetSelection()
- if selected != -1:
- window = self.TabsOpened.GetPage(selected)
- window.RefreshView()
- self.VariablePanelIndexer.RefreshVariablePanel(window.GetTagName())
- self.RefreshTitle()
- self.RefreshEditMenu()
- self.RefreshTypesTree()
- self.RefreshInstancesTree()
- self.RefreshLibraryTree()
- self.RefreshScaling()
- event.Skip()
-
+ self.CloseTabsWithoutModel()
+ self.RefreshEditor()
+ self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE,
+ SCALING)
+ event.Skip()
+
def OnEnableUndoRedoMenu(self, event):
self.Controler.EnableProjectBuffer(event.IsChecked())
self.RefreshEditMenu()
event.Skip()
- def OnCutMenu(self, event):
- control = self.FindFocus()
- if isinstance(control, (Viewer, TextViewer)):
- control.Cut()
- elif isinstance(control, wx.TextCtrl):
- control.ProcessEvent(event)
- event.Skip()
-
- def OnCopyMenu(self, event):
- control = self.FindFocus()
- if isinstance(control, (Viewer, TextViewer)):
- control.Copy()
- elif isinstance(control, wx.TextCtrl):
- control.ProcessEvent(event)
- event.Skip()
-
- def OnPasteMenu(self, event):
- control = self.FindFocus()
- if isinstance(control, (Viewer, TextViewer)):
- control.Paste()
- elif isinstance(control, wx.TextCtrl):
- control.ProcessEvent(event)
- event.Skip()
-
+ OnCutMenu = GetShortcutKeyCallbackFunction("Cut")
+ OnCopyMenu = GetShortcutKeyCallbackFunction("Copy")
+ OnPasteMenu = GetShortcutKeyCallbackFunction("Paste")
+
def OnSelectAllMenu(self, event):
control = self.FindFocus()
if isinstance(control, (Viewer, TextViewer)):
@@ -1184,70 +1202,27 @@
control.SetMark(0, control.GetLastPosition() + 1)
event.Skip()
+ DeleteFunctions = {
+ ITEM_DATATYPE: GetDeleteElementFunction(PLCControler.ProjectRemoveDataType, check_function=PLCControler.DataTypeIsUsed),
+ ITEM_POU: GetDeleteElementFunction(PLCControler.ProjectRemovePou, check_function=PLCControler.PouIsUsed),
+ ITEM_TRANSITION: GetDeleteElementFunction(PLCControler.ProjectRemovePouTransition, ITEM_POU),
+ ITEM_ACTION: GetDeleteElementFunction(PLCControler.ProjectRemovePouAction, ITEM_POU),
+ ITEM_CONFIGURATION: GetDeleteElementFunction(PLCControler.ProjectRemoveConfiguration),
+ ITEM_RESOURCE: GetDeleteElementFunction(PLCControler.ProjectRemoveConfigurationResource, ITEM_CONFIGURATION)
+ }
+
def OnDeleteMenu(self, event):
window = self.FindFocus()
- if window == self.TypesTree:
+ if window == self.TypesTree or window is None:
selected = self.TypesTree.GetSelection()
if selected.IsOk():
type = self.TypesTree.GetPyData(selected)
- tagname = ""
- if type == ITEM_DATATYPE:
- name = self.TypesTree.GetItemText(selected)
- if not self.Controler.DataTypeIsUsed(name, self.Debug):
- self.Controler.ProjectRemoveDataType(name)
- tagname = self.Controler.ComputeDataTypeName(name)
- else:
- message = wx.MessageDialog(self, "\"%s\" is used by one or more POUs. It can't be removed!"%name, "Error", wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
- elif type == ITEM_POU:
- name = self.TypesTree.GetItemText(selected)
- if not self.Controler.PouIsUsed(name, self.Debug):
- self.Controler.ProjectRemovePou(name)
- tagname = self.Controler.ComputePouName(name)
- else:
- message = wx.MessageDialog(self, "\"%s\" is used by one or more POUs. It can't be removed!"%name, "Error", wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
- elif type in [ITEM_TRANSITION, ITEM_ACTION]:
- item = self.TypesTree.GetItemParent(selected)
- item_type = self.TypesTree.GetPyData(item)
- while item_type != ITEM_POU:
- item = self.TypesTree.GetItemParent(item)
- item_type = self.TypesTree.GetPyData(item)
- pou_name = self.TypesTree.GetItemText(item)
- if type == ITEM_TRANSITION:
- transition = self.TypesTree.GetItemText(selected)
- self.Controler.ProjectRemovePouTransition(pou_name, transition)
- tagname = self.Controler.ComputePouTransitionName(pou_name, transition)
- elif type == ITEM_ACTION:
- action = self.TypesTree.GetItemText(selected)
- self.Controler.ProjectRemovePouAction(pou_name, action)
- tagname = self.Controler.ComputePouActionName(pou_name, action)
- elif type == ITEM_CONFIGURATION:
- name = self.TypesTree.GetItemText(selected)
- self.Controler.ProjectRemoveConfiguration(name)
- tagname = self.Controler.ComputeConfigurationName(name)
- elif type == ITEM_RESOURCE:
- resource = self.TypesTree.GetItemText(selected)
- item = self.TypesTree.GetItemParent(selected)
- item_type = self.TypesTree.GetPyData(item)
- while item_type != ITEM_CONFIGURATION:
- item = self.TypesTree.GetItemParent(item)
- item_type = self.TypesTree.GetPyData(item)
- config_name = self.TypesTree.GetItemText(item)
- self.Controler.ProjectRemoveConfigurationResource(config_name, resource)
- tagname = self.Controler.ComputeConfigurationResourceName(config_name, selected)
- idx = self.IsOpened(tagname)
- if idx is not None:
- self.VariablePanelIndexer.RemoveVariablePanel(tagname)
- self.TabsOpened.DeletePage(idx)
- self.RefreshTitle()
- self.RefreshEditMenu()
- self.RefreshTypesTree()
- self.RefreshInstancesTree()
- self.RefreshLibraryTree()
- self.RefreshToolBar()
+ function = self.DeleteFunctions.get(type, None)
+ if function is not None:
+ function(self, selected)
+ self.CloseTabsWithoutModel()
+ self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE,
+ INSTANCESTREE, LIBRARYTREE)
elif isinstance(window, (Viewer, TextViewer)):
event = wx.KeyEvent(wx.EVT_CHAR._getEvtType())
event.m_keyCode = wx.WXK_DELETE
@@ -1287,12 +1262,7 @@
self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
def OnRefreshMenu(self, event):
- selected = self.TabsOpened.GetSelection()
- if selected != -1:
- window = self.TabsOpened.GetPage(selected)
- window.RefreshView()
- if not self.Debug:
- self.VariablePanelIndexer.RefreshVariablePanel(window.GetTagName())
+ self.RefreshEditor(not self.Debug)
event.Skip()
def OnClearErrorsMenu(self, event):
@@ -1315,6 +1285,25 @@
# Project Editor Panels Management Functions
#-------------------------------------------------------------------------------
+ def OnPageDragged(self, event):
+ wx.CallAfter(self.RefreshTabCtrlEvent)
+ event.Skip()
+
+ def RefreshTabCtrlEvent(self):
+ if USE_AUI:
+ auitabctrl = []
+ for child in self.TabsOpened.GetChildren():
+ if isinstance(child, wx.aui.AuiTabCtrl):
+ auitabctrl.append(child)
+ if child not in self.AuiTabCtrl:
+ child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child))
+ self.AuiTabCtrl = auitabctrl
+ if self.TabsOpened.GetPageCount() == 0:
+ pane = self.AUIManager.GetPane(self.TabsOpened)
+ if pane.IsMaximized():
+ self.AUIManager.RestorePane(pane)
+ self.AUIManager.Update()
+
def OnPouSelectedChanged(self, event):
old_selected = self.TabsOpened.GetSelection()
if old_selected >= 0:
@@ -1332,10 +1321,7 @@
window.RefreshView()
if not self.Debug:
self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName())
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshDisplayMenu()
- self.RefreshToolBar()
+ self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, TOOLBAR)
event.Skip()
def RefreshEditor(self, variablepanel = True):
@@ -1412,6 +1398,9 @@
self.GenerateTypesTreeBranch(root, infos)
self.TypesTree.Expand(root)
+ def ResetSelectedItem(self):
+ self.SelectedItem = None
+
def GenerateTypesTreeBranch(self, root, infos, topology=False):
to_delete = []
self.TypesTree.SetItemText(root, infos["name"])
@@ -1423,9 +1412,9 @@
self.TypesTree.SetItemBackgroundColour(root, wx.WHITE)
self.TypesTree.SetItemTextColour(root, wx.BLACK)
if infos["type"] == ITEM_POU:
- self.TypesTree.SetItemImage(root, self.TypesTreeImageDict[self.Controler.GetPouBodyType(infos["name"], self.Debug)])
- else:
- self.TypesTree.SetItemImage(root, self.TypesTreeImageDict[infos["type"]])
+ self.TypesTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"], self.Debug)])
+ else:
+ self.TypesTree.SetItemImage(root, self.TreeImageDict[infos["type"]])
if wx.VERSION >= (2, 6, 0):
item, root_cookie = self.TypesTree.GetFirstChild(root)
@@ -1543,12 +1532,7 @@
self.RefreshLibraryTree()
self.RefreshPageTitles()
elif itemtype == ITEM_TRANSITION:
- parent = self.TypesTree.GetItemParent(item)
- parent_type = self.TypesTree.GetPyData(parent)
- while parent_type != ITEM_POU:
- parent = self.TypesTree.GetItemParent(parent)
- parent_type = self.TypesTree.GetPyData(parent)
- pou_name = self.TypesTree.GetItemText(parent)
+ pou_name = GetParentName(self.TypesTree, item, ITEM_POU)
if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
message = "A pou with \"%s\" as name exists!"%new_name
elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name, self.Debug) if name != old_name]:
@@ -1559,12 +1543,7 @@
self.Controler.ComputePouTransitionName(pou_name, new_name))
self.RefreshPageTitles()
elif itemtype == ITEM_ACTION:
- parent = self.TypesTree.GetItemParent(item)
- parent_type = self.TypesTree.GetPyData(parent)
- while parent_type != ITEM_POU:
- parent = self.TypesTree.GetItemParent(parent)
- parent_type = self.TypesTree.GetPyData(parent)
- pou_name = self.TypesTree.GetItemText(parent)
+ pou_name = GetParentName(self.TypesTree, item, ITEM_POU)
if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
message = "A pou with \"%s\" as name exists!"%new_name
elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name, self.Debug) if name != old_name]:
@@ -1594,12 +1573,7 @@
self.Controler.ComputeConfigurationName(new_name))
self.RefreshPageTitles()
elif itemtype == ITEM_RESOURCE:
- parent = self.TypesTree.GetItemParent(item)
- parent_type = self.TypesTree.GetPyData(parent)
- while parent_type != ITEM_CONFIGURATION:
- parent = self.TypesTree.GetItemParent(parent)
- parent_type = self.TypesTree.GetPyData(parent)
- config_name = self.TypesTree.GetItemText(parent)
+ config_name = GetParentName(self.TypesTree, item, ITEM_CONFIGURATION)
if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames(self.Debug)]:
message = "\"%s\" config already exists!"%new_name
abort = True
@@ -1620,18 +1594,14 @@
self.RefreshPageTitles()
if message or abort:
if message:
- messageDialog = wx.MessageDialog(self, message, "Error", wx.OK|wx.ICON_ERROR)
- messageDialog.ShowModal()
- messageDialog.Destroy()
+ self.ShowErrorMessage(message)
item = event.GetItem()
wx.CallAfter(self.TypesTree.EditLabel, item)
event.Veto()
else:
wx.CallAfter(self.RefreshTypesTree)
self.RefreshEditor()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshTitle()
+ self._Refresh(TITLE, FILEMENU, EDITMENU)
event.Skip()
def OnTypesTreeItemActivated(self, event):
@@ -1647,20 +1617,10 @@
elif data == ITEM_CONFIGURATION:
self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name))
elif data == ITEM_RESOURCE:
- item = self.TypesTree.GetItemParent(selected)
- item_type = self.TypesTree.GetPyData(item)
- while item_type != ITEM_CONFIGURATION:
- item = self.TypesTree.GetItemParent(item)
- item_type = self.TypesTree.GetPyData(item)
- config_name = self.TypesTree.GetItemText(item)
+ config_name = GetParentName(self.TypesTree, selected, ITEM_CONFIGURATION)
self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name))
elif data in [ITEM_TRANSITION, ITEM_ACTION]:
- item = self.TypesTree.GetItemParent(selected)
- item_type = self.TypesTree.GetPyData(item)
- while item_type != ITEM_POU:
- item = self.TypesTree.GetItemParent(item)
- item_type = self.TypesTree.GetPyData(item)
- pou_name = self.TypesTree.GetItemText(item)
+ pou_name = GetParentName(self.TypesTree, selected, ITEM_POU)
if data == ITEM_TRANSITION:
tagname = self.Controler.ComputePouTransitionName(pou_name, name)
elif data == ITEM_ACTION:
@@ -1678,20 +1638,10 @@
elif data == ITEM_CONFIGURATION:
self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name), True)
elif data == ITEM_RESOURCE:
- item = self.TypesTree.GetItemParent(select_item)
- item_type = self.TypesTree.GetPyData(item)
- while item_type != ITEM_CONFIGURATION:
- item = self.TypesTree.GetItemParent(item)
- item_type = self.TypesTree.GetPyData(item)
- config_name = self.TypesTree.GetItemText(item)
+ config_name = GetParentName(self.TypesTree, select_item, ITEM_CONFIGURATION)
self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name), True)
elif data in [ITEM_TRANSITION, ITEM_ACTION]:
- item = self.TypesTree.GetItemParent(select_item)
- item_type = self.TypesTree.GetPyData(item)
- while item_type != ITEM_POU:
- item = self.TypesTree.GetItemParent(item)
- item_type = self.TypesTree.GetPyData(item)
- pou_name = self.TypesTree.GetItemText(item)
+ pou_name = GetParentName(self.TypesTree, select_item, ITEM_POU)
if data == ITEM_TRANSITION:
tagname = self.Controler.ComputePouTransitionName(pou_name, name)
elif data == ITEM_ACTION:
@@ -1724,12 +1674,9 @@
if old_selected >= 0:
self.TabsOpened.GetPage(old_selected).ResetBuffer()
self.TabsOpened.SetSelection(openedidx)
- self.TabsOpened.GetPage(openedidx).RefreshView()
self.VariablePanelIndexer.ChangeVariablePanel(tagname)
self.RefreshPageTitles()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshToolBar()
+ self._Refresh(FILEMENU, EDITMENU, TOOLBAR)
elif not onlyopened:
if elementtype == ITEM_CONFIGURATION:
new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
@@ -1775,9 +1722,7 @@
self.TabsOpened.SetSelection(i)
window.SetFocus()
self.RefreshPageTitles()
- self.RefreshFileMenu()
- self.RefreshEditMenu()
- self.RefreshToolBar()
+ self._Refresh(FILEMENU, EDITMENU, TOOLBAR)
def OnTypesTreeRightUp(self, event):
if wx.Platform == '__WXMSW__':
@@ -1815,7 +1760,7 @@
self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, id=new_id)
new_id = wx.NewId()
AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text="Delete")
- self.Bind(wx.EVT_MENU, self.OnRemovePouMenu, id=new_id)
+ self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id)
self.PopupMenu(menu)
elif type == ITEM_CONFIGURATION:
menu = wx.Menu(title='')
@@ -1824,20 +1769,13 @@
self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(name), id=new_id)
new_id = wx.NewId()
AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text="Delete")
- self.Bind(wx.EVT_MENU, self.OnRemoveConfigurationMenu, id=new_id)
+ self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id)
self.PopupMenu(menu)
elif type in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]:
menu = wx.Menu(title='')
new_id = wx.NewId()
AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text="Delete")
- if type == ITEM_DATATYPE:
- self.Bind(wx.EVT_MENU, self.OnRemoveDataTypeMenu, id=new_id)
- elif type == ITEM_TRANSITION:
- self.Bind(wx.EVT_MENU, self.OnRemoveTransitionMenu, id=new_id)
- elif type == ITEM_ACTION:
- self.Bind(wx.EVT_MENU, self.OnRemoveActionMenu, id=new_id)
- elif type == ITEM_RESOURCE:
- self.Bind(wx.EVT_MENU, self.OnRemoveResourceMenu, id=new_id)
+ self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id)
self.PopupMenu(menu)
elif type in ITEMS_UNEDITABLE:
if name == "Data Types":
@@ -1913,7 +1851,7 @@
else:
self.InstancesTree.SetItemText(root, infos["name"])
self.InstancesTree.SetPyData(root, (infos["type"], infos.get("tagname", None)))
- self.InstancesTree.SetItemImage(root, self.InstancesTreeImageDict[infos["type"]])
+ self.InstancesTree.SetItemImage(root, self.TreeImageDict[infos["type"]])
if wx.VERSION >= (2, 6, 0):
item, root_cookie = self.InstancesTree.GetFirstChild(root)
@@ -2642,7 +2580,18 @@
for i in xrange(self.TabsOpened.GetPageCount()):
viewer = self.TabsOpened.GetPage(i)
viewer.ClearErrors()
-
+
+ RefreshFunctions = {
+ TITLE : RefreshTitle,
+ TOOLBAR : RefreshToolBar,
+ FILEMENU : RefreshFileMenu,
+ EDITMENU : RefreshEditMenu,
+ DISPLAYMENU : RefreshDisplayMenu,
+ TYPESTREE : RefreshTypesTree,
+ INSTANCESTREE : RefreshInstancesTree,
+ LIBRARYTREE : RefreshLibraryTree,
+ SCALING : RefreshScaling}
+
current_num = 0
def GetNewNum():
global current_num
@@ -4543,7 +4492,7 @@
self.Table.ResetView(self.VariablesGrid)
#-------------------------------------------------------------------------------
-# Variables Editor Panel
+# Debug Variables Panel
#-------------------------------------------------------------------------------
class VariableTableItem(DebugDataConsumer):