PLCOpenEditor.py
changeset 125 394d9f168258
parent 122 e6faee0c271b
child 128 d16a8df4d322
--- a/PLCOpenEditor.py	Tue Nov 27 12:58:34 2007 +0100
+++ b/PLCOpenEditor.py	Thu Dec 06 18:05:29 2007 +0100
@@ -34,6 +34,7 @@
 from Viewer import *
 from TextViewer import *
 from RessourceEditor import *
+from DataTypeEditor import *
 from PLCControler import *
 from plcopen import OpenPDFDoc
 from plcopen.structures import LOCATIONDATATYPES
@@ -42,7 +43,7 @@
 
 __version__ = "$Revision$"
 
-CWD = os.path.split(__file__)[0]
+CWD = os.path.split(os.path.realpath(__file__))[0]
 
 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORPROJECTTREE, 
  ID_PLCOPENEDITORMAINSPLITTER, ID_PLCOPENEDITORSECONDSPLITTER, 
@@ -71,11 +72,12 @@
 ] = [wx.NewId() for _init_coll_HelpMenu_Items in range(2)]
 
 [ID_PLCOPENEDITOREDITMENUITEMS0, ID_PLCOPENEDITOREDITMENUITEMS1, 
- ID_PLCOPENEDITOREDITMENUITEMS11, ID_PLCOPENEDITOREDITMENUITEMS12, 
  ID_PLCOPENEDITOREDITMENUITEMS2, ID_PLCOPENEDITOREDITMENUITEMS4, 
  ID_PLCOPENEDITOREDITMENUITEMS5, ID_PLCOPENEDITOREDITMENUITEMS6, 
  ID_PLCOPENEDITOREDITMENUITEMS8, ID_PLCOPENEDITOREDITMENUITEMS9, 
-] = [wx.NewId() for _init_coll_EditMenu_Items in range(10)]
+ ID_PLCOPENEDITOREDITMENUITEMS11, ID_PLCOPENEDITOREDITMENUITEMS12, 
+ ID_PLCOPENEDITOREDITMENUITEMS14, ID_PLCOPENEDITOREDITMENUITEMS15, 
+] = [wx.NewId() for _init_coll_EditMenu_Items in range(12)]
 
 [ID_PLCOPENEDITORSFCMENUITEMS0, ID_PLCOPENEDITORSFCMENUITEMS1, 
  ID_PLCOPENEDITORSFCMENUITEMS2, ID_PLCOPENEDITORSFCMENUITEMS3, 
@@ -171,13 +173,18 @@
               kind=wx.ITEM_NORMAL, text=u'Paste\tCTRL+V')
         parent.AppendSeparator()
         AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS8,
+              kind=wx.ITEM_NORMAL, text=u'Add Data Type')
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS9,
+              kind=wx.ITEM_NORMAL, text=u'Remove Data Type')
+        parent.AppendSeparator()
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS11,
               kind=wx.ITEM_NORMAL, text=u'Add POU')
-        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS9,
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS12,
               kind=wx.ITEM_NORMAL, text=u'Remove POU')
         parent.AppendSeparator()
-        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS11,
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS14,
               kind=wx.ITEM_NORMAL, text=u'Add Configuration')
-        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS12,
+        AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUITEMS15,
               kind=wx.ITEM_NORMAL, text=u'Remove Configuration')
         self.Bind(wx.EVT_MENU, self.OnRefreshMenu,
               id=ID_PLCOPENEDITOREDITMENUITEMS0)
@@ -191,14 +198,18 @@
               id=ID_PLCOPENEDITOREDITMENUITEMS5)
         self.Bind(wx.EVT_MENU, self.OnPasteMenu,
               id=ID_PLCOPENEDITOREDITMENUITEMS6)
+        self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu,
+              id=ID_PLCOPENEDITOREDITMENUITEMS8)
+        self.Bind(wx.EVT_MENU, self.OnRemoveDataTypeMenu,
+              id=ID_PLCOPENEDITOREDITMENUITEMS9)
         self.Bind(wx.EVT_MENU, self.OnAddPouMenu,
-              id=ID_PLCOPENEDITOREDITMENUITEMS8)
+              id=ID_PLCOPENEDITOREDITMENUITEMS11)
         self.Bind(wx.EVT_MENU, self.OnRemovePouMenu,
-              id=ID_PLCOPENEDITOREDITMENUITEMS9)
+              id=ID_PLCOPENEDITOREDITMENUITEMS12)
         self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu,
-              id=ID_PLCOPENEDITOREDITMENUITEMS11)
+              id=ID_PLCOPENEDITOREDITMENUITEMS14)
         self.Bind(wx.EVT_MENU, self.OnRemoveConfigurationMenu,
-              id=ID_PLCOPENEDITOREDITMENUITEMS12)
+              id=ID_PLCOPENEDITOREDITMENUITEMS15)
 
     def _init_coll_menuBar1_Menus(self, parent):
         if self.ModeSolo:
@@ -416,7 +427,7 @@
             self.VariablePanelIndexer = VariablePanelIndexer(self, self.Controler)
             self.AUIManager.AddPane(self.VariablePanelIndexer, wx.aui.AuiPaneInfo().Caption("Variable Panel").Bottom().Layer(0).BestSize(wx.Size(800, 200)).CloseButton(False))
             
-            self.AUIManager.Update(); 
+            self.AUIManager.Update()
         
     def __init__(self, parent, controler = None, fileOpen = None):
         self.ModeSolo = controler == None
@@ -594,10 +605,18 @@
                     self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS0, False)
                 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS8, True)
                 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS9, True)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS11, True)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS12, True)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS14, True)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS15, True)
             else:
                 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS0, False)
                 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS8, False)
                 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS9, False)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS11, False)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS12, False)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS14, False)
+                self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS15, False)
             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS4, True)
             self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUITEMS5, True)
             if self.CopyBuffer is not None:
@@ -798,7 +817,7 @@
         tool.SetToggle(False)
 
     def OnSelectionTool(self, event):
-        self.GetPageSelection()
+        selected = self.GetPageSelection()
         if selected != -1:
             self.GetPage(selected).SetMode(MODE_SELECTION)
         event.Skip()
@@ -1018,6 +1037,14 @@
                 itemtype = self.ProjectTree.GetPyData(item)
                 if itemtype == ITEM_PROJECT:
                     self.Controler.SetProjectProperties(name = new_name)
+                elif itemtype == ITEM_DATATYPE:
+                    if new_name.upper() in [name.upper() for name in self.Controler.GetProjectDataTypeNames() if name != old_name]:
+                        message = "\"%s\" data type already exists!"%new_name
+                        abort = True
+                    if not abort:
+                        self.Controler.ChangeDataTypeName(old_name, new_name)
+                        self.RefreshEditorNames(itemtype, old_name, new_name)
+                        self.RefreshPageTitles()
                 elif itemtype == ITEM_POU:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
                         message = "\"%s\" pou already exists!"%new_name
@@ -1135,7 +1162,9 @@
         data = self.ProjectTree.GetPyData(selected)
         if name == "Properties":
             self.ShowProperties()
-        if data == ITEM_POU:
+        if data == ITEM_DATATYPE:
+            self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name))
+        elif data == ITEM_POU:
             self.EditProjectElement(data, self.Controler.ComputePouName(name))
         elif data == ITEM_CONFIGURATION:
             self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name))
@@ -1162,11 +1191,12 @@
     
     def OnProjectTreeLeftUp(self, event):
         if self.SelectedItem is not None:
-            print "LeftUp", self.ProjectTree.GetItemText(self.SelectedItem)
             self.ProjectTree.SelectItem(self.SelectedItem)
             name = self.ProjectTree.GetItemText(self.SelectedItem)
             data = self.ProjectTree.GetPyData(self.SelectedItem)
-            if data == ITEM_POU:
+            if data == ITEM_DATATYPE:
+                self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name), True)
+            elif data == ITEM_POU:
                 self.EditProjectElement(data, self.Controler.ComputePouName(name), True)
             elif data == ITEM_CONFIGURATION:
                 self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name), True)
@@ -1191,15 +1221,9 @@
                     tagname = self.Controler.ComputePouActionName(pou_name, name)
                 self.EditProjectElement(data, tagname, True)
             wx.CallAfter(self.ResetSelectedItem)
-        else:
-            print "LeftUp", None
         event.Skip()
     
     def OnProjectTreeItemChanging(self, event):
-        if self.SelectedItem is not None:
-            print "Changing", self.ProjectTree.GetItemText(event.GetItem()), self.ProjectTree.GetItemText(self.SelectedItem)
-        else:
-            print "Changing", None, self.ProjectTree.GetItemText(event.GetItem())
         if self.ProjectTree.GetPyData(event.GetItem()) != ITEM_UNEDITABLE and self.SelectedItem is None:
             self.SelectedItem = event.GetItem()
             event.Veto()
@@ -1230,10 +1254,8 @@
             if wx.VERSION >= (2, 8, 0):
                 if elementtype == ITEM_CONFIGURATION:
                     new_window = MDIConfigurationEditor(self, tagname, self, self.Controler)
-                    self.VariablePanelIndexer.AddVariablePanel(tagname, "config")
                 elif elementtype == ITEM_RESOURCE:
                     new_window = MDIResourceEditor(self, tagname, self, self.Controler)
-                    self.VariablePanelIndexer.AddVariablePanel(tagname, "resource")
                 elif elementtype in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
                     bodytype = self.Controler.GetEditedElementBodyType(tagname)
                     if bodytype == "FBD":
@@ -1250,17 +1272,18 @@
                             viewer.SetKeywords(IL_KEYWORDS)
                         else:
                             viewer.SetKeywords(ST_KEYWORDS)
+                elif elementtype == ITEM_DATATYPE:
+                    new_window = MDIDataTypeEditor(self, tagname, self, self.Controler)
                 new_window.Bind(wx.EVT_ACTIVATE, self.OnPouSelectedChanged)
                 new_window.Bind(wx.EVT_CLOSE, self.OnPageClose)
+                new_window.Layout()
             else:
                 if elementtype == ITEM_CONFIGURATION:
                     new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler)
                     self.TabsOpened.AddPage(new_window, "")
-                    self.VariablePanelIndexer.AddVariablePanel(tagname, "config")
                 elif elementtype == ITEM_RESOURCE:
                     new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler)
                     self.TabsOpened.AddPage(new_window, "")
-                    self.VariablePanelIndexer.AddVariablePanel(tagname, "resource")
                 elif elementtype in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
                     bodytype = self.Controler.GetEditedElementBodyType(tagname)
                     if bodytype == "FBD":
@@ -1277,13 +1300,16 @@
                         else:
                             new_window.SetKeywords(ST_KEYWORDS)
                     self.TabsOpened.AddPage(new_window, "")
-            if elementtype == ITEM_POU:
+                elif elementtype == ITEM_DATATYPE:
+                    new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler)
+                    self.TabsOpened.AddPage(new_window, "")
+            if elementtype == ITEM_CONFIGURATION:
+                self.VariablePanelIndexer.AddVariablePanel(tagname, "config")
+            elif elementtype == ITEM_RESOURCE:
+                self.VariablePanelIndexer.AddVariablePanel(tagname, "resource")
+            elif elementtype in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]:
                 words = tagname.split("::")
                 self.VariablePanelIndexer.AddVariablePanel(tagname, self.Controler.GetPouType(words[1]))
-            elif elementtype == ITEM_TRANSITION:
-                self.VariablePanelIndexer.AddVariablePanel(tagname, "transition")
-            elif elementtype == ITEM_TRANSITION:
-                self.VariablePanelIndexer.AddVariablePanel(tagname, "action")
             self.VariablePanelIndexer.ChangeVariablePanel(tagname)
             openedidx = self.IsOpened(tagname)
             old_selected = self.GetPageSelection()
@@ -1457,6 +1483,38 @@
                 pass
         event.Skip()
     
+    def OnAddDataTypeMenu(self, event):
+        dialog = DataTypeDialog(self, "Add a new data type", "Please enter data type name", "", wx.OK|wx.CANCEL)
+        dialog.SetDataTypeNames(self.Controler.GetProjectDataTypeNames())
+        if dialog.ShowModal() == wx.ID_OK:
+            self.Controler.ProjectAddDataType(dialog.GetValue())
+            self.RefreshTitle()
+            self.RefreshEditMenu()
+            self.RefreshProjectTree()
+        dialog.Destroy()
+        event.Skip()
+        
+    def OnRemoveDataTypeMenu(self, event):
+        datatypes = self.Controler.GetProjectDataTypeNames()
+        dialog = wx.SingleChoiceDialog(self, "Select Data Type to remove:", "Data Type Remove", datatypes, wx.OK|wx.CANCEL)
+        if dialog.ShowModal() == wx.ID_OK:
+            selected = dialog.GetStringSelection()
+            if not self.Controler.DataTypeIsUsed(selected):
+                self.Controler.ProjectRemoveDataType(selected)
+                tagname = self.Controler.ComputeDataTypeName(selected)
+                idx = self.IsOpened(tagname)
+                if idx is not None:
+                    self.DeletePage(idx)
+                self.RefreshTitle()
+                self.RefreshEditMenu()
+                self.RefreshProjectTree()
+                self.RefreshToolBar()
+            else:
+                message = wx.MessageDialog(self, "%s is used by one or more POUs. It can't be removed!"%selected, "Error", wx.OK|wx.ICON_ERROR)
+                message.ShowModal()
+                message.Destroy()
+        event.Skip()
+    
     def OnAddPouMenu(self, event):
         dialog = PouDialog(self)
         dialog.SetPouNames(self.Controler.GetProjectPouNames())
@@ -1840,6 +1898,59 @@
         return values
 
 #-------------------------------------------------------------------------------
+#                          Edit Step Name Dialog
+#-------------------------------------------------------------------------------
+
+class DataTypeDialog(wx.TextEntryDialog):
+
+    if wx.VERSION < (2, 6, 0):
+        def Bind(self, event, function, id = None):
+            if id is not None:
+                event(self, id, function)
+            else:
+                event(self, function)
+    
+
+    def __init__(self, parent, message, caption = "Please enter text", defaultValue = "", 
+                       style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition):
+        wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos)
+        
+        self.DataTypeNames = []
+        if wx.VERSION >= (2, 8, 0):
+            self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId())
+        elif wx.VERSION >= (2, 6, 0):
+            self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId())
+        else:
+            self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId())
+    
+    def OnOK(self, event):
+        datatype_name = self.GetSizer().GetItem(1).GetWindow().GetValue()
+        if datatype_name == "":
+            message = wx.MessageDialog(self, "You must type a name!", "Error", wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        elif not TestIdentifier(datatype_name):
+            message = wx.MessageDialog(self, "\"%s\" is not a valid identifier!"%datatype_name, "Error", wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        elif datatype_name.upper() in IEC_KEYWORDS:
+            message = wx.MessageDialog(self, "\"%s\" is a keyword. It can't be used!"%datatype_name, "Error", wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        elif datatype_name.upper() in self.DataTypeNames:
+            message = wx.MessageDialog(self, "\"%s\" data type already exists!"%datatype_name, "Error", wx.OK|wx.ICON_ERROR)
+            message.ShowModal()
+            message.Destroy()
+        else:
+            self.EndModal(wx.ID_OK)
+
+    def SetDataTypeNames(self, datatype_names):
+        self.DataTypeNames = [datatype_name.upper() for datatype_name in datatype_names]
+
+    def GetValue(self):
+        return self.GetSizer().GetItem(1).GetWindow().GetValue()
+
+#-------------------------------------------------------------------------------
 #                            Create Pou Dialog
 #-------------------------------------------------------------------------------
 
@@ -2462,12 +2573,18 @@
                 self.CurrentPanel = new_tagname
                 
     def ChangeVariablePanel(self, tagname):
-        if tagname in self.VariablePanelList and tagname != self.CurrentPanel:
+        if tagname in self.VariablePanelList:
+            if tagname != self.CurrentPanel:
+                if self.CurrentPanel is not None:
+                    self.VariablePanelList[self.CurrentPanel].Hide()
+                self.CurrentPanel = tagname
+                self.VariablePanelList[self.CurrentPanel].RefreshView()
+                self.VariablePanelList[self.CurrentPanel].Show()
+                self.MainSizer.Layout()
+        else:
             if self.CurrentPanel is not None:
                 self.VariablePanelList[self.CurrentPanel].Hide()
-            self.CurrentPanel = tagname
-            self.VariablePanelList[self.CurrentPanel].RefreshView()
-            self.VariablePanelList[self.CurrentPanel].Show()
+            self.CurrentPanel = None
             self.MainSizer.Layout()
 
     def RefreshVariablePanel(self, tagname):
@@ -2874,12 +2991,10 @@
         self.RefreshTypeList()
 
         self.OptionList = "Yes,No"
-        self.TypeList = [value for value, parent in TypeHierarchy_list if not value.startswith("ANY")]
         
         if element_type == "function":
-            for value, parent in TypeHierarchy_list:
-                if not value.startswith("ANY"):
-                    self.ReturnType.Append(value)
+            for base_type in self.Controler.GetBaseTypes():
+                self.ReturnType.Append(base_type)
             self.ReturnType.Enable(True)
         else:
             self.ReturnType.Enable(False)
@@ -3033,11 +3148,17 @@
         if self.Table.GetColLabelValue(col) == "Type":
             type_menu = wx.Menu(title='')
             base_menu = wx.Menu(title='')
-            for base_type in self.TypeList:
+            for base_type in self.Controler.GetBaseTypes():
                 new_id = wx.NewId()
                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
             type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
+            datatype_menu = wx.Menu(title='')
+            for datatype in self.Controler.GetDataTypes(basetypes = False):
+                new_id = wx.NewId()
+                AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
+                self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
+            type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
             functionblock_menu = wx.Menu(title='')
             for functionblock_type in self.Controler.GetFunctionBlockTypes():
                 new_id = wx.NewId()
@@ -3072,7 +3193,7 @@
             data = wx.TextDataObject(str((var_name, var_class, var_type, self.TagName)))
             dragSource = wx.DropSource(self.VariablesGrid)
             dragSource.SetData(data)
-            dragSource.DoDragDrop()
+            print dragSource.DoDragDrop()
         event.Skip()
     
     def OnVariablesGridSelectCell(self, event):