PLCOpenEditor.py
changeset 431 c1c92d068ac5
parent 411 9ab97d517ae8
parent 430 8efd4c6874cd
child 434 8a0dfd22c408
equal deleted inserted replaced
411:9ab97d517ae8 431:c1c92d068ac5
   106 from TextViewer import *
   106 from TextViewer import *
   107 from GraphicViewer import *
   107 from GraphicViewer import *
   108 from RessourceEditor import *
   108 from RessourceEditor import *
   109 from DataTypeEditor import *
   109 from DataTypeEditor import *
   110 from PLCControler import *
   110 from PLCControler import *
   111 from plcopen.structures import LOCATIONDATATYPES
   111 from VariablePanel import VariablePanel
   112 
   112 
   113 # Define PLCOpenEditor controls id
   113 # Define PLCOpenEditor controls id
   114 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, 
   114 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, 
   115  ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, 
   115  ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, 
   116  ID_PLCOPENEDITORTYPESTREE, ID_PLCOPENEDITORINSTANCESTREE, 
   116  ID_PLCOPENEDITORTYPESTREE, ID_PLCOPENEDITORINSTANCESTREE, 
   249     else:
   249     else:
   250         parent.Append(helpString=help, id=id, kind=kind, item=text)
   250         parent.Append(helpString=help, id=id, kind=kind, item=text)
   251 
   251 
   252 [TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, 
   252 [TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, 
   253  INSTANCESTREE, LIBRARYTREE, SCALING
   253  INSTANCESTREE, LIBRARYTREE, SCALING
   254 ] = [wx.NewId() for _refresh_elements in range(9)]
   254 ] = range(9)
   255 
   255 
   256 def GetShortcutKeyCallbackFunction(viewer_function):
   256 def GetShortcutKeyCallbackFunction(viewer_function):
   257     def ShortcutKeyFunction(self, event):
   257     def ShortcutKeyFunction(self, event):
   258         control = self.FindFocus()
   258         control = self.FindFocus()
   259         if isinstance(control, (Viewer, TextViewer)):
   259         if isinstance(control, (Viewer, TextViewer)):
   260             getattr(control, viewer_function)()
   260             getattr(control, viewer_function)()
   261         elif isinstance(control, wx.TextCtrl):
   261         elif isinstance(control, wx.TextCtrl):
   262             control.ProcessEvent(event)
   262             control.ProcessEvent(event)
   263         event.Skip()
       
   264     return ShortcutKeyFunction
   263     return ShortcutKeyFunction
   265 
   264 
   266 def GetParentName(tree, item, parent_type):
   265 def GetParentName(tree, item, parent_type):
   267     parent_item = tree.GetItemParent(item)
   266     parent_item = tree.GetItemParent(item)
   268     parent_item_type = tree.GetPyData(parent_item)
   267     parent_item_type = tree.GetPyData(parent_item)
   959         self.ShowProperties()
   958         self.ShowProperties()
   960         event.Skip()
   959         event.Skip()
   961 
   960 
   962     def OnQuitMenu(self, event):
   961     def OnQuitMenu(self, event):
   963         self.Close()
   962         self.Close()
   964         event.Skip()
   963         # don't call event.Skip() here or it will attempt to close the
       
   964         # frame twice for some reason
   965 
   965 
   966 #-------------------------------------------------------------------------------
   966 #-------------------------------------------------------------------------------
   967 #                            Edit Menu Functions
   967 #                            Edit Menu Functions
   968 #-------------------------------------------------------------------------------
   968 #-------------------------------------------------------------------------------
   969 
   969 
  1379                 elif itemtype == ITEM_POU:
  1379                 elif itemtype == ITEM_POU:
  1380                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
  1380                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
  1381                         message = _("\"%s\" pou already exists!")%new_name
  1381                         message = _("\"%s\" pou already exists!")%new_name
  1382                         abort = True
  1382                         abort = True
  1383                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
  1383                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
  1384                         messageDialog = wx.MessageDialog(self, _("A pou has an element with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1384                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1385                         if messageDialog.ShowModal() == wx.ID_NO:
  1385                         if messageDialog.ShowModal() == wx.ID_NO:
  1386                             abort = True
  1386                             abort = True
  1387                         messageDialog.Destroy()
  1387                         messageDialog.Destroy()
  1388                     if not abort:
  1388                     if not abort:
  1389                         self.Controler.ChangePouName(old_name, new_name)
  1389                         self.Controler.ChangePouName(old_name, new_name)
  1392                         self.RefreshLibraryTree()
  1392                         self.RefreshLibraryTree()
  1393                         self.RefreshPageTitles()
  1393                         self.RefreshPageTitles()
  1394                 elif itemtype == ITEM_TRANSITION:
  1394                 elif itemtype == ITEM_TRANSITION:
  1395                     pou_name = GetParentName(self.TypesTree, item, ITEM_POU)
  1395                     pou_name = GetParentName(self.TypesTree, item, ITEM_POU)
  1396                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1396                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1397                         message = _("A pou with \"%s\" as name exists!")%new_name
  1397                         message = _("A POU named \"%s\" already exists!")%new_name
  1398                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
  1398                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
  1399                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
  1399                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
  1400                     else:
  1400                     else:
  1401                         self.Controler.ChangePouTransitionName(pou_name, old_name, new_name)
  1401                         self.Controler.ChangePouTransitionName(pou_name, old_name, new_name)
  1402                         self.RefreshEditorNames(self.Controler.ComputePouTransitionName(pou_name, old_name), 
  1402                         self.RefreshEditorNames(self.Controler.ComputePouTransitionName(pou_name, old_name), 
  1403                                                 self.Controler.ComputePouTransitionName(pou_name, new_name))
  1403                                                 self.Controler.ComputePouTransitionName(pou_name, new_name))
  1404                         self.RefreshPageTitles()
  1404                         self.RefreshPageTitles()
  1405                 elif itemtype == ITEM_ACTION:
  1405                 elif itemtype == ITEM_ACTION:
  1406                     pou_name = GetParentName(self.TypesTree, item, ITEM_POU)
  1406                     pou_name = GetParentName(self.TypesTree, item, ITEM_POU)
  1407                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1407                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1408                         message = _("A pou with \"%s\" as name exists!")%new_name
  1408                         message = _("A POU named \"%s\" already exists!")%new_name
  1409                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
  1409                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
  1410                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
  1410                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
  1411                     else:
  1411                     else:
  1412                         self.Controler.ChangePouActionName(pou_name, old_name, new_name)
  1412                         self.Controler.ChangePouActionName(pou_name, old_name, new_name)
  1413                         self.RefreshEditorNames(self.Controler.ComputePouActionName(pou_name, old_name), 
  1413                         self.RefreshEditorNames(self.Controler.ComputePouActionName(pou_name, old_name), 
  1416                 elif itemtype == ITEM_CONFIGURATION:
  1416                 elif itemtype == ITEM_CONFIGURATION:
  1417                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]:
  1417                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]:
  1418                         message = _("\"%s\" config already exists!")%new_name
  1418                         message = _("\"%s\" config already exists!")%new_name
  1419                         abort = True
  1419                         abort = True
  1420                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1420                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1421                         messageDialog = wx.MessageDialog(self, _("A pou is defined with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1421                         messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1422                         if messageDialog.ShowModal() == wx.ID_NO:
  1422                         if messageDialog.ShowModal() == wx.ID_NO:
  1423                             abort = True
  1423                             abort = True
  1424                         messageDialog.Destroy()
  1424                         messageDialog.Destroy()
  1425                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
  1425                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
  1426                         messageDialog = wx.MessageDialog(self, _("A pou has an element with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1426                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1427                         if messageDialog.ShowModal() == wx.ID_NO:
  1427                         if messageDialog.ShowModal() == wx.ID_NO:
  1428                             abort = True
  1428                             abort = True
  1429                         messageDialog.Destroy()
  1429                         messageDialog.Destroy()
  1430                     if not abort:
  1430                     if not abort:
  1431                         self.Controler.ChangeConfigurationName(old_name, new_name)
  1431                         self.Controler.ChangeConfigurationName(old_name, new_name)
  1436                     config_name = GetParentName(self.TypesTree, item, ITEM_CONFIGURATION)
  1436                     config_name = GetParentName(self.TypesTree, item, ITEM_CONFIGURATION)
  1437                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]:
  1437                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]:
  1438                         message = _("\"%s\" config already exists!")%new_name
  1438                         message = _("\"%s\" config already exists!")%new_name
  1439                         abort = True
  1439                         abort = True
  1440                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1440                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
  1441                         messageDialog = wx.MessageDialog(self, _("A pou is defined with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1441                         messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1442                         if messageDialog.ShowModal() == wx.ID_NO:
  1442                         if messageDialog.ShowModal() == wx.ID_NO:
  1443                             abort = True
  1443                             abort = True
  1444                         messageDialog.Destroy()
  1444                         messageDialog.Destroy()
  1445                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
  1445                     elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
  1446                         messageDialog = wx.MessageDialog(self, _("A pou has an element with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1446                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
  1447                         if messageDialog.ShowModal() == wx.ID_NO:
  1447                         if messageDialog.ShowModal() == wx.ID_NO:
  1448                             abort = True
  1448                             abort = True
  1449                         messageDialog.Destroy()
  1449                         messageDialog.Destroy()
  1450                     if not abort:
  1450                     if not abort:
  1451                         self.Controler.ChangeConfigurationResourceName(config_name, old_name, new_name)
  1451                         self.Controler.ChangeConfigurationResourceName(config_name, old_name, new_name)
  1585                     self._Refresh(FILEMENU, EDITMENU, TOOLBAR)
  1585                     self._Refresh(FILEMENU, EDITMENU, TOOLBAR)
  1586     
  1586     
  1587     def OnTypesTreeRightUp(self, event):
  1587     def OnTypesTreeRightUp(self, event):
  1588         if wx.Platform == '__WXMSW__':
  1588         if wx.Platform == '__WXMSW__':
  1589             item = event.GetItem()
  1589             item = event.GetItem()
       
  1590             self.TypesTree.SelectItem(item)
  1590         else:
  1591         else:
  1591             item = self.TypesTree.GetSelection()
  1592             item = self.TypesTree.GetSelection()
  1592         name = self.TypesTree.GetItemText(item)
  1593         name = self.TypesTree.GetItemText(item)
  1593         type = self.TypesTree.GetPyData(item)
  1594         type = self.TypesTree.GetPyData(item)
  1594         if type == ITEM_POU:
  1595         if type == ITEM_POU:
  1599                 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), id=new_id)
  1600                 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), id=new_id)
  1600                 new_id = wx.NewId()
  1601                 new_id = wx.NewId()
  1601                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action"))
  1602                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action"))
  1602                 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id)
  1603                 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id)
  1603                 menu.AppendSeparator()
  1604                 menu.AppendSeparator()
       
  1605 
  1604             new_id = wx.NewId()
  1606             new_id = wx.NewId()
  1605             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Create a new POU from"))
  1607             AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Create a new POU from"))
  1606             self.Bind(wx.EVT_MENU, self.OnCreatePouFromMenu, id=new_id)
  1608             self.Bind(wx.EVT_MENU, self.OnCreatePouFromMenu, id=new_id)
       
  1609 
       
  1610             AppendMenu(menu, help='', id=wx.ID_COPY, kind=wx.ITEM_NORMAL, text=_("Copy"))
       
  1611             self.Bind(wx.EVT_MENU, self.OnCopyPou, id=wx.ID_COPY)
       
  1612 
  1607             pou_type = self.Controler.GetPouType(name)
  1613             pou_type = self.Controler.GetPouType(name)
  1608             if pou_type in ["function", "functionBlock"]:
  1614             if pou_type in ["function", "functionBlock"]:
  1609                 change_menu = wx.Menu(title='')
  1615                 change_menu = wx.Menu(title='')
  1610                 if pou_type == "function":
  1616                 if pou_type == "function":
  1611                     new_id = wx.NewId()
  1617                     new_id = wx.NewId()
  1645                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add DataType"))
  1651                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add DataType"))
  1646                 self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, id=new_id)
  1652                 self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, id=new_id)
  1647                 self.PopupMenu(menu)
  1653                 self.PopupMenu(menu)
  1648             elif name in ["Functions", "Function Blocks", "Programs"]:
  1654             elif name in ["Functions", "Function Blocks", "Programs"]:
  1649                 menu = wx.Menu(title='')
  1655                 menu = wx.Menu(title='')
       
  1656 
  1650                 new_id = wx.NewId()
  1657                 new_id = wx.NewId()
  1651                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Pou"))
  1658                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Pou"))
  1652                 self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id)
  1659                 self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id)
       
  1660 
       
  1661                 AppendMenu(menu, help='', id=wx.ID_PASTE, kind=wx.ITEM_NORMAL, text=_("Paste"))
       
  1662                 self.Bind(wx.EVT_MENU, self.OnPastePou, id=wx.ID_PASTE)
       
  1663 
       
  1664                 if self.GetCopyBuffer() is None:
       
  1665                     menu.Enable(wx.ID_PASTE, False)
       
  1666 
  1653                 self.PopupMenu(menu)
  1667                 self.PopupMenu(menu)
  1654             elif name == "Configurations":
  1668             elif name == "Configurations":
  1655                 menu = wx.Menu(title='')
  1669                 menu = wx.Menu(title='')
  1656                 new_id = wx.NewId()
  1670                 new_id = wx.NewId()
  1657                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Configuration"))
  1671                 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Configuration"))
  2248             if dialog.ShowModal() == wx.ID_OK:
  2262             if dialog.ShowModal() == wx.ID_OK:
  2249                 self.Controler.ProjectCreatePouFrom(dialog.GetValue(), self.TypesTree.GetItemText(selected))
  2263                 self.Controler.ProjectCreatePouFrom(dialog.GetValue(), self.TypesTree.GetItemText(selected))
  2250                 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE, LIBRARYTREE)
  2264                 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE, LIBRARYTREE)
  2251         event.Skip()
  2265         event.Skip()
  2252 
  2266 
       
  2267     def OnCopyPou(self, event):
       
  2268         selected = self.TypesTree.GetSelection()
       
  2269 
       
  2270         pou_name = self.TypesTree.GetItemText(selected)
       
  2271         pou = self.Controler.Project.getpou(pou_name)
       
  2272 
       
  2273         pou_xml = pou.generateXMLText('pou', 0)
       
  2274         self.SetCopyBuffer(pou_xml)
       
  2275 
       
  2276     def OnPastePou(self, event):
       
  2277         selected = self.TypesTree.GetSelection()
       
  2278 
       
  2279         pou_type = self.TypesTree.GetItemText(selected)
       
  2280         pou_type = UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs'
       
  2281         pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type]
       
  2282 
       
  2283         pou_xml = self.GetCopyBuffer()
       
  2284 
       
  2285         result = self.Controler.PastePou(pou_type, pou_xml)
       
  2286 
       
  2287         if result is not None:
       
  2288             message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
       
  2289             message.ShowModal()
       
  2290             message.Destroy()
       
  2291         else:
       
  2292             self.RefreshTitle()
       
  2293             self.RefreshEditMenu()
       
  2294             self.RefreshTypesTree()
       
  2295             self.RefreshLibraryTree()
       
  2296             self.RefreshToolBar()
       
  2297 
  2253 #-------------------------------------------------------------------------------
  2298 #-------------------------------------------------------------------------------
  2254 #                        Remove Project Elements Functions
  2299 #                        Remove Project Elements Functions
  2255 #-------------------------------------------------------------------------------
  2300 #-------------------------------------------------------------------------------
  2256 
  2301 
  2257     def OnRemoveDataTypeMenu(self, event):
  2302     def OnRemoveDataTypeMenu(self, event):
  3286         elif pou_name.upper() in self.PouNames:
  3331         elif pou_name.upper() in self.PouNames:
  3287             message = wx.MessageDialog(self, _("\"%s\" pou already exists!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3332             message = wx.MessageDialog(self, _("\"%s\" pou already exists!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3288             message.ShowModal()
  3333             message.ShowModal()
  3289             message.Destroy()
  3334             message.Destroy()
  3290         elif pou_name.upper() in self.PouElementNames:
  3335         elif pou_name.upper() in self.PouElementNames:
  3291             message = wx.MessageDialog(self, _("A pou has an element with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%pou_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION)
  3336             message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%pou_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION)
  3292             result = message.ShowModal()
  3337             result = message.ShowModal()
  3293             message.Destroy()
  3338             message.Destroy()
  3294             if result == wx.ID_YES:
  3339             if result == wx.ID_YES:
  3295                 self.EndModal(wx.ID_OK)
  3340                 self.EndModal(wx.ID_OK)
  3296         else:
  3341         else:
  3445         elif transition_name.upper() in IEC_KEYWORDS:
  3490         elif transition_name.upper() in IEC_KEYWORDS:
  3446             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3491             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3447             message.ShowModal()
  3492             message.ShowModal()
  3448             message.Destroy()
  3493             message.Destroy()
  3449         elif transition_name.upper() in self.PouNames:
  3494         elif transition_name.upper() in self.PouNames:
  3450             message = wx.MessageDialog(self, _("A pou with \"%s\" as name exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3495             message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3451             message.ShowModal()
  3496             message.ShowModal()
  3452             message.Destroy()
  3497             message.Destroy()
  3453         elif transition_name.upper() in self.PouElementNames:
  3498         elif transition_name.upper() in self.PouElementNames:
  3454             message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3499             message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3455             message.ShowModal()
  3500             message.ShowModal()
  3589         elif action_name.upper() in IEC_KEYWORDS:
  3634         elif action_name.upper() in IEC_KEYWORDS:
  3590             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3635             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3591             message.ShowModal()
  3636             message.ShowModal()
  3592             message.Destroy()
  3637             message.Destroy()
  3593         elif action_name.upper() in self.PouNames:
  3638         elif action_name.upper() in self.PouNames:
  3594             message = wx.MessageDialog(self, _("A pou with \"%s\" as name exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3639             message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3595             message.ShowModal()
  3640             message.ShowModal()
  3596             message.Destroy()
  3641             message.Destroy()
  3597         elif action_name.upper() in self.PouElementNames:
  3642         elif action_name.upper() in self.PouElementNames:
  3598             message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3643             message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3599             message.ShowModal()
  3644             message.ShowModal()
  3660         elif config_name.upper() in IEC_KEYWORDS:
  3705         elif config_name.upper() in IEC_KEYWORDS:
  3661             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3706             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3662             message.ShowModal()
  3707             message.ShowModal()
  3663             message.Destroy()
  3708             message.Destroy()
  3664         elif config_name.upper() in self.PouNames:
  3709         elif config_name.upper() in self.PouNames:
  3665             message = wx.MessageDialog(self, _("A pou with \"%s\" as name exists!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3710             message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3666             message.ShowModal()
  3711             message.ShowModal()
  3667             message.Destroy()
  3712             message.Destroy()
  3668         elif config_name.upper() in self.PouElementNames:
  3713         elif config_name.upper() in self.PouElementNames:
  3669             message = wx.MessageDialog(self, _("A pou has an element with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%config_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION)
  3714             message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%config_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION)
  3670             result = message.ShowModal()
  3715             result = message.ShowModal()
  3671             message.Destroy()
  3716             message.Destroy()
  3672             if result == wx.ID_YES:
  3717             if result == wx.ID_YES:
  3673                 self.EndModal(wx.ID_OK)
  3718                 self.EndModal(wx.ID_OK)
  3674         else:
  3719         else:
  3723         elif resource_name.upper() in IEC_KEYWORDS:
  3768         elif resource_name.upper() in IEC_KEYWORDS:
  3724             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3769             message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3725             message.ShowModal()
  3770             message.ShowModal()
  3726             message.Destroy()
  3771             message.Destroy()
  3727         elif resource_name.upper() in self.PouNames:
  3772         elif resource_name.upper() in self.PouNames:
  3728             message = wx.MessageDialog(self, _("A pou with \"%s\" as name exists!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3773             message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR)
  3729             message.ShowModal()
  3774             message.ShowModal()
  3730             message.Destroy()
  3775             message.Destroy()
  3731         elif resource_name.upper() in self.PouElementNames:
  3776         elif resource_name.upper() in self.PouElementNames:
  3732             message = wx.MessageDialog(self, _("A pou has an element with \"%s\" as name. It can generate a conflict. Do you wish to continue?")%resource_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION)
  3777             message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%resource_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION)
  3733             result = message.ShowModal()
  3778             result = message.ShowModal()
  3734             message.Destroy()
  3779             message.Destroy()
  3735             if result == wx.ID_YES:
  3780             if result == wx.ID_YES:
  3736                 self.EndModal(wx.ID_OK)
  3781                 self.EndModal(wx.ID_OK)
  3737         else:
  3782         else:
  3825     def ClearErrors(self):
  3870     def ClearErrors(self):
  3826         for panel in self.VariablePanelList.values():
  3871         for panel in self.VariablePanelList.values():
  3827             panel.ClearErrors()
  3872             panel.ClearErrors()
  3828 
  3873 
  3829 #-------------------------------------------------------------------------------
  3874 #-------------------------------------------------------------------------------
  3830 #                            Variables Editor Panel
       
  3831 #-------------------------------------------------------------------------------
       
  3832 
       
  3833 def GetVariableTableColnames(location):
       
  3834     _ = lambda x : x
       
  3835     if location:
       
  3836     	return ["#", _("Name"), _("Class"), _("Type"), _("Location"), _("Initial Value"), _("Retain"), _("Constant")]
       
  3837     return ["#", _("Name"), _("Class"), _("Type"), _("Initial Value"), _("Retain"), _("Constant")]
       
  3838 
       
  3839 def GetAlternativeOptions():
       
  3840     _ = lambda x : x
       
  3841     return [_("Yes"), _("No")]
       
  3842 ALTERNATIVE_OPTIONS_DICT = dict([(_(option), option) for option in GetAlternativeOptions()])
       
  3843 
       
  3844 def GetFilterChoiceTransfer():
       
  3845     _ = lambda x : x
       
  3846     return {_("All"): _("All"), _("Interface"): _("Interface"), 
       
  3847             _("   Input"): _("Input"), _("   Output"): _("Output"), _("   InOut"): _("InOut"), 
       
  3848             _("   External"): _("External"), _("Variables"): _("Variables"), _("   Local"): _("Local"),
       
  3849             _("   Temp"): _("Temp"), _("Global"): _("Global")}#, _("Access") : _("Access")}
       
  3850 VARIABLE_CLASSES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().itervalues()])
       
  3851 
       
  3852 class VariableTable(wx.grid.PyGridTableBase):
       
  3853     
       
  3854     """
       
  3855     A custom wx.grid.Grid Table using user supplied data
       
  3856     """
       
  3857     def __init__(self, parent, data, colnames):
       
  3858         # The base class must be initialized *first*
       
  3859         wx.grid.PyGridTableBase.__init__(self)
       
  3860         self.data = data
       
  3861         self.old_value = None
       
  3862         self.colnames = colnames
       
  3863         self.Errors = {}
       
  3864         self.Parent = parent
       
  3865         # XXX
       
  3866         # we need to store the row length and collength to
       
  3867         # see if the table has changed size
       
  3868         self._rows = self.GetNumberRows()
       
  3869         self._cols = self.GetNumberCols()
       
  3870     
       
  3871     def GetNumberCols(self):
       
  3872         return len(self.colnames)
       
  3873         
       
  3874     def GetNumberRows(self):
       
  3875         return len(self.data)
       
  3876 
       
  3877     def GetColLabelValue(self, col, translate=True):
       
  3878         if col < len(self.colnames):
       
  3879             if translate:
       
  3880                 return _(self.colnames[col])
       
  3881             return self.colnames[col]
       
  3882 
       
  3883     def GetRowLabelValues(self, row, translate=True):
       
  3884         return row
       
  3885 
       
  3886     def GetValue(self, row, col):
       
  3887         if row < self.GetNumberRows():
       
  3888             if col == 0:
       
  3889                 return self.data[row]["Number"]
       
  3890             colname = self.GetColLabelValue(col, False)
       
  3891             value = str(self.data[row].get(colname, ""))
       
  3892             if colname in ["Class", "Retain", "Constant"]:
       
  3893                 return _(value)
       
  3894             return value
       
  3895     
       
  3896     def SetValue(self, row, col, value):
       
  3897         if col < len(self.colnames):
       
  3898             colname = self.GetColLabelValue(col, False)
       
  3899             if colname == "Name":
       
  3900                 self.old_value = self.data[row][colname]
       
  3901             elif colname == "Class":
       
  3902                 value = VARIABLE_CLASSES_DICT[value]
       
  3903             elif colname in ["Retain", "Constant"]:
       
  3904                 value = ALTERNATIVE_OPTIONS_DICT[value]
       
  3905             self.data[row][colname] = value
       
  3906     
       
  3907     def GetValueByName(self, row, colname):
       
  3908         if row < self.GetNumberRows():
       
  3909             return self.data[row].get(colname)
       
  3910 
       
  3911     def SetValueByName(self, row, colname, value):
       
  3912         if row < self.GetNumberRows():
       
  3913             self.data[row][colname] = value
       
  3914 
       
  3915     def GetOldValue(self):
       
  3916         return self.old_value
       
  3917     
       
  3918     def ResetView(self, grid):
       
  3919         """
       
  3920         (wx.grid.Grid) -> Reset the grid view.   Call this to
       
  3921         update the grid if rows and columns have been added or deleted
       
  3922         """
       
  3923         grid.BeginBatch()
       
  3924         for current, new, delmsg, addmsg in [
       
  3925             (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
       
  3926             (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
       
  3927         ]:
       
  3928             if new < current:
       
  3929                 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
       
  3930                 grid.ProcessTableMessage(msg)
       
  3931             elif new > current:
       
  3932                 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
       
  3933                 grid.ProcessTableMessage(msg)
       
  3934                 self.UpdateValues(grid)
       
  3935         grid.EndBatch()
       
  3936 
       
  3937         self._rows = self.GetNumberRows()
       
  3938         self._cols = self.GetNumberCols()
       
  3939         # update the column rendering scheme
       
  3940         self._updateColAttrs(grid)
       
  3941 
       
  3942         # update the scrollbars and the displayed part of the grid
       
  3943         grid.AdjustScrollbars()
       
  3944         grid.ForceRefresh()
       
  3945 
       
  3946     def UpdateValues(self, grid):
       
  3947         """Update all displayed values"""
       
  3948         # This sends an event to the grid table to update all of the values
       
  3949         msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
       
  3950         grid.ProcessTableMessage(msg)
       
  3951 
       
  3952     def _updateColAttrs(self, grid):
       
  3953         """
       
  3954         wx.grid.Grid -> update the column attributes to add the
       
  3955         appropriate renderer given the column name.
       
  3956 
       
  3957         Otherwise default to the default renderer.
       
  3958         """
       
  3959         
       
  3960         for row in range(self.GetNumberRows()):
       
  3961             grid.SetRowMinimalHeight(row, 28)
  3875             grid.SetRowMinimalHeight(row, 28)
  3962             grid.AutoSizeRow(row, False)
  3876             grid.AutoSizeRow(row, False)
  3963             for col in range(self.GetNumberCols()):
       
  3964                 editor = None
       
  3965                 renderer = None
       
  3966                 colname = self.GetColLabelValue(col, False)
       
  3967                 if col != 0 and self.GetValueByName(row, "Edit"):
       
  3968                     grid.SetReadOnly(row, col, False)
       
  3969                     if colname == "Name":
       
  3970                         if self.Parent.PouIsUsed and self.GetValueByName(row, "Class") in ["Input", "Output", "InOut"]:
       
  3971                             grid.SetReadOnly(row, col, True)
       
  3972                         else:
       
  3973                             editor = wx.grid.GridCellTextEditor()
       
  3974                             renderer = wx.grid.GridCellStringRenderer()
       
  3975                     elif colname == "Initial Value":
       
  3976                         editor = wx.grid.GridCellTextEditor()
       
  3977                         renderer = wx.grid.GridCellStringRenderer()
       
  3978                     elif colname == "Location":
       
  3979                         if self.GetValueByName(row, "Class") in ["Local", "Global"]:
       
  3980                             editor = wx.grid.GridCellTextEditor()
       
  3981                             renderer = wx.grid.GridCellStringRenderer()
       
  3982                         else:
       
  3983                             grid.SetReadOnly(row, col, True)
       
  3984                     elif colname == "Class":
       
  3985                         if len(self.Parent.ClassList) == 1 or self.Parent.PouIsUsed and self.GetValueByName(row, "Class") in ["Input", "Output", "InOut"]:
       
  3986                             grid.SetReadOnly(row, col, True)
       
  3987                         else:
       
  3988                             editor = wx.grid.GridCellChoiceEditor()
       
  3989                             excluded = []
       
  3990                             if self.Parent.PouIsUsed:
       
  3991                                 excluded.extend(["Input","Output","InOut"])
       
  3992                             if self.Parent.IsFunctionBlockType(self.data[row]["Type"]):
       
  3993                                 excluded.extend(["Local","Temp"])
       
  3994                             editor.SetParameters(",".join([_(choice) for choice in self.Parent.ClassList if choice not in excluded]))
       
  3995                     elif colname in ["Retain", "Constant"]:
       
  3996                         editor = wx.grid.GridCellChoiceEditor()
       
  3997                         editor.SetParameters(",".join(map(_, self.Parent.OptionList)))
       
  3998                     elif colname == "Type":
       
  3999                         editor = wx.grid.GridCellTextEditor()
       
  4000                 else:
       
  4001                     grid.SetReadOnly(row, col, True)
       
  4002                 
       
  4003                 grid.SetCellEditor(row, col, editor)
       
  4004                 grid.SetCellRenderer(row, col, renderer)
       
  4005                 
       
  4006                 if row in self.Errors and self.Errors[row][0] == colname.lower():
       
  4007                     grid.SetCellBackgroundColour(row, col, wx.Colour(255, 255, 0))
       
  4008                     grid.SetCellTextColour(row, col, wx.RED)
       
  4009                     grid.MakeCellVisible(row, col)
       
  4010                 else:
       
  4011                     grid.SetCellTextColour(row, col, wx.BLACK)
       
  4012                     grid.SetCellBackgroundColour(row, col, wx.WHITE)
       
  4013     
       
  4014     def SetData(self, data):
       
  4015         self.data = data
       
  4016     
       
  4017     def GetData(self):
       
  4018         return self.data
       
  4019     
       
  4020     def GetCurrentIndex(self):
       
  4021         return self.CurrentIndex
       
  4022     
       
  4023     def SetCurrentIndex(self, index):
       
  4024         self.CurrentIndex = index
       
  4025     
       
  4026     def AppendRow(self, row_content):
       
  4027         self.data.append(row_content)
       
  4028 
       
  4029     def RemoveRow(self, row_index):
       
  4030         self.data.pop(row_index)
       
  4031 
       
  4032     def GetRow(self, row_index):
       
  4033         return self.data[row_index]
       
  4034 
       
  4035     def Empty(self):
       
  4036         self.data = []
       
  4037         self.editors = []
       
  4038 
       
  4039     def AddError(self, infos):
       
  4040         self.Errors[infos[0]] = infos[1:]
       
  4041 
       
  4042     def ClearErrors(self):
       
  4043         self.Errors = {}
       
  4044 
       
  4045 class VariableDropTarget(wx.TextDropTarget):
       
  4046     
       
  4047     def __init__(self, parent):
       
  4048         wx.TextDropTarget.__init__(self)
       
  4049         self.ParentWindow = parent
       
  4050     
       
  4051     def OnDropText(self, x, y, data):
       
  4052         x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y)
       
  4053         col = self.ParentWindow.VariablesGrid.XToCol(x)
       
  4054         row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize())
       
  4055         if col != wx.NOT_FOUND and row != wx.NOT_FOUND:
       
  4056             if self.ParentWindow.Table.GetColLabelValue(col, False) != "Location":
       
  4057                 return
       
  4058             message = None
       
  4059             if not self.ParentWindow.Table.GetValueByName(row, "Edit"):
       
  4060                 message = _("Can't affect a location to a function block instance")
       
  4061             elif self.ParentWindow.Table.GetValueByName(row, "Class") not in ["Local", "Global"]:
       
  4062                 message = _("Can affect a location only to local or global variables")
       
  4063             else:
       
  4064                 try:
       
  4065                     values = eval(data)    
       
  4066                 except:
       
  4067                     message = _("Invalid value \"%s\" for location")%data
       
  4068                     values = None
       
  4069                 if not isinstance(values, TupleType):
       
  4070                     message = _("Invalid value \"%s\" for location")%data
       
  4071                     values = None
       
  4072                 if values is not None and values[1] == "location":
       
  4073                     location = values[0]
       
  4074                     variable_type = self.ParentWindow.Table.GetValueByName(row, "Type")
       
  4075                     base_type = self.ParentWindow.Controler.GetBaseType(variable_type)
       
  4076                     message = None
       
  4077                     if location.startswith("%"):
       
  4078                         if base_type != values[2]:
       
  4079                             message = _("Incompatible data types between \"%s\" and \"%s\"")%(values[2], variable_type)
       
  4080                         else:
       
  4081                             self.ParentWindow.Table.SetValue(row, col, location)
       
  4082                             self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
       
  4083                             self.ParentWindow.SaveValues()
       
  4084                     else:
       
  4085                         if location[0].isdigit() and base_type != "BOOL":
       
  4086                             message = _("Incompatible size of data between \"%s\" and \"BOOL\"")%location
       
  4087                         elif location[0] not in LOCATIONDATATYPES:
       
  4088                             message = _("Unrecognized data size \"%s\"")%location[0]
       
  4089                         elif base_type not in LOCATIONDATATYPES[location[0]]:
       
  4090                             message = _("Incompatible size of data between \"%s\" and \"%s\"")%(location, variable_type)
       
  4091                         else:
       
  4092                             dialog = wx.SingleChoiceDialog(self.ParentWindow, _("Select a variable class:"), _("Variable class"), ["Input", "Output", "Memory"], wx.OK|wx.CANCEL)
       
  4093                             if dialog.ShowModal() == wx.ID_OK:
       
  4094                                 selected = dialog.GetSelection()
       
  4095                                 if selected == 0:
       
  4096                                     location = "%I" + location
       
  4097                                 elif selected == 1:
       
  4098                                     location = "%Q" + location
       
  4099                                 else:
       
  4100                                     location = "%M" + location
       
  4101                                 self.ParentWindow.Table.SetValue(row, col, location)
       
  4102                                 self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
       
  4103                                 self.ParentWindow.SaveValues()
       
  4104                             dialog.Destroy()
       
  4105             if message is not None:
       
  4106                 wx.CallAfter(self.ShowMessage, message)
       
  4107             
       
  4108     def ShowMessage(self, message):
       
  4109         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
       
  4110         message.ShowModal()
       
  4111         message.Destroy()
       
  4112 
       
  4113 [ID_VARIABLEEDITORPANEL, ID_VARIABLEEDITORPANELVARIABLESGRID, 
       
  4114  ID_VARIABLEEDITORCONTROLPANEL, ID_VARIABLEEDITORPANELRETURNTYPE, 
       
  4115  ID_VARIABLEEDITORPANELCLASSFILTER, ID_VARIABLEEDITORPANELADDBUTTON, 
       
  4116  ID_VARIABLEEDITORPANELDELETEBUTTON, ID_VARIABLEEDITORPANELUPBUTTON, 
       
  4117  ID_VARIABLEEDITORPANELDOWNBUTTON, ID_VARIABLEEDITORPANELSTATICTEXT1, 
       
  4118  ID_VARIABLEEDITORPANELSTATICTEXT2, ID_VARIABLEEDITORPANELSTATICTEXT3,
       
  4119 ] = [wx.NewId() for _init_ctrls in range(12)]
       
  4120 
       
  4121 class VariablePanel(wx.Panel):
       
  4122     
       
  4123     if wx.VERSION < (2, 6, 0):
       
  4124         def Bind(self, event, function, id = None):
       
  4125             if id is not None:
       
  4126                 event(self, id, function)
       
  4127             else:
       
  4128                 event(self, function)
       
  4129     
       
  4130     def _init_coll_MainSizer_Items(self, parent):
       
  4131         parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
       
  4132         parent.AddWindow(self.ControlPanel, 0, border=5, flag=wx.GROW|wx.ALL)
       
  4133     
       
  4134     def _init_coll_MainSizer_Growables(self, parent):
       
  4135         parent.AddGrowableCol(0)
       
  4136         parent.AddGrowableRow(0)
       
  4137     
       
  4138     def _init_coll_ControlPanelSizer_Items(self, parent):
       
  4139         parent.AddSizer(self.ChoicePanelSizer, 0, border=0, flag=wx.GROW)
       
  4140         parent.AddSizer(self.ButtonPanelSizer, 0, border=0, flag=wx.ALIGN_CENTER)
       
  4141 
       
  4142     def _init_coll_ControlPanelSizer_Growables(self, parent):
       
  4143         parent.AddGrowableCol(0)
       
  4144         parent.AddGrowableRow(0)
       
  4145         parent.AddGrowableRow(1)
       
  4146 
       
  4147     def _init_coll_ChoicePanelSizer_Items(self, parent):
       
  4148         parent.AddWindow(self.staticText1, 0, border=0, flag=wx.ALIGN_BOTTOM)
       
  4149         parent.AddWindow(self.ReturnType, 0, border=0, flag=0)
       
  4150         parent.AddWindow(self.staticText2, 0, border=0, flag=wx.ALIGN_BOTTOM)
       
  4151         parent.AddWindow(self.ClassFilter, 0, border=0, flag=0)
       
  4152 
       
  4153     def _init_coll_ButtonPanelSizer_Items(self, parent):
       
  4154         parent.AddWindow(self.UpButton, 0, border=0, flag=0)
       
  4155         parent.AddWindow(self.AddButton, 0, border=0, flag=0)
       
  4156         parent.AddWindow(self.DownButton, 0, border=0, flag=0)
       
  4157         parent.AddWindow(self.DeleteButton, 0, border=0, flag=0)
       
  4158         
       
  4159     def _init_coll_ButtonPanelSizer_Growables(self, parent):
       
  4160         parent.AddGrowableCol(0)
       
  4161         parent.AddGrowableCol(1)
       
  4162         parent.AddGrowableCol(2)
       
  4163         parent.AddGrowableCol(3)
       
  4164         parent.AddGrowableRow(0)
       
  4165 
       
  4166     def _init_sizers(self):
       
  4167         self.MainSizer = wx.FlexGridSizer(cols=2, hgap=10, rows=1, vgap=0)
       
  4168         self.ControlPanelSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
  4169         self.ChoicePanelSizer = wx.GridSizer(cols=1, hgap=5, rows=4, vgap=5)
       
  4170         self.ButtonPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5)
       
  4171         
       
  4172         self._init_coll_MainSizer_Items(self.MainSizer)
       
  4173         self._init_coll_MainSizer_Growables(self.MainSizer)
       
  4174         self._init_coll_ControlPanelSizer_Items(self.ControlPanelSizer)
       
  4175         self._init_coll_ControlPanelSizer_Growables(self.ControlPanelSizer)
       
  4176         self._init_coll_ChoicePanelSizer_Items(self.ChoicePanelSizer)
       
  4177         self._init_coll_ButtonPanelSizer_Items(self.ButtonPanelSizer)
       
  4178         self._init_coll_ButtonPanelSizer_Growables(self.ButtonPanelSizer)
       
  4179         
       
  4180         self.SetSizer(self.MainSizer)
       
  4181         self.ControlPanel.SetSizer(self.ControlPanelSizer)
       
  4182 
       
  4183     def _init_ctrls(self, prnt):
       
  4184         wx.Panel.__init__(self, id=ID_VARIABLEEDITORPANEL,
       
  4185               name='VariableEditorPanel', parent=prnt, pos=wx.Point(0, 0),
       
  4186               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
  4187 
       
  4188         self.VariablesGrid = wx.grid.Grid(id=ID_VARIABLEEDITORPANELVARIABLESGRID,
       
  4189               name='VariablesGrid', parent=self, pos=wx.Point(0, 0), 
       
  4190               size=wx.Size(0, 0), style=wx.VSCROLL)
       
  4191         self.VariablesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
       
  4192               'Sans'))
       
  4193         self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
       
  4194               False, 'Sans'))
       
  4195         self.VariablesGrid.SetSelectionBackground(wx.WHITE)
       
  4196         self.VariablesGrid.SetSelectionForeground(wx.BLACK)
       
  4197         if wx.VERSION >= (2, 6, 0):
       
  4198             self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
       
  4199             self.VariablesGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnVariablesGridSelectCell)
       
  4200             self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
       
  4201             self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
       
  4202             #self.VariablesGrid.Bind(wx.EVT_KEY_DOWN, self.OnChar)
       
  4203         else:
       
  4204             wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
       
  4205             wx.grid.EVT_GRID_SELECT_CELL(self.VariablesGrid, self.OnVariablesGridSelectCell)
       
  4206             wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
       
  4207             wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
       
  4208             #wx.EVT_KEY_DOWN(self.VariablesGrid, self.OnChar)
       
  4209         self.VariablesGrid.SetDropTarget(VariableDropTarget(self))
       
  4210         
       
  4211         self.ControlPanel = wx.ScrolledWindow(id=ID_VARIABLEEDITORCONTROLPANEL,
       
  4212               name='ControlPanel', parent=self, pos=wx.Point(0, 0),
       
  4213               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
  4214         self.ControlPanel.SetScrollRate(0, 10)
       
  4215         
       
  4216         self.staticText1 = wx.StaticText(id=ID_VARIABLEEDITORPANELSTATICTEXT1,
       
  4217               label=_('Return Type:'), name='staticText1', parent=self.ControlPanel,
       
  4218               pos=wx.Point(0, 0), size=wx.Size(145, 17), style=0)
       
  4219 
       
  4220         self.ReturnType = wx.ComboBox(id=ID_VARIABLEEDITORPANELRETURNTYPE,
       
  4221               name='ReturnType', parent=self.ControlPanel, pos=wx.Point(0, 0),
       
  4222               size=wx.Size(145, 28), style=wx.CB_READONLY)
       
  4223         self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, id=ID_VARIABLEEDITORPANELRETURNTYPE)
       
  4224 
       
  4225         self.staticText2 = wx.StaticText(id=ID_VARIABLEEDITORPANELSTATICTEXT2,
       
  4226               label=_('Class Filter:'), name='staticText2', parent=self.ControlPanel,
       
  4227               pos=wx.Point(0, 0), size=wx.Size(145, 17), style=0)
       
  4228 
       
  4229         self.ClassFilter = wx.ComboBox(id=ID_VARIABLEEDITORPANELCLASSFILTER,
       
  4230               name='ClassFilter', parent=self.ControlPanel, pos=wx.Point(0, 0),
       
  4231               size=wx.Size(145, 28), style=wx.CB_READONLY)
       
  4232         self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, id=ID_VARIABLEEDITORPANELCLASSFILTER)
       
  4233 
       
  4234         self.AddButton = wx.Button(id=ID_VARIABLEEDITORPANELADDBUTTON, label=_('Add'),
       
  4235               name='AddButton', parent=self.ControlPanel, pos=wx.Point(0, 0),
       
  4236               size=wx.DefaultSize, style=0)
       
  4237         self.Bind(wx.EVT_BUTTON, self.OnAddButton, id=ID_VARIABLEEDITORPANELADDBUTTON)
       
  4238 
       
  4239         self.DeleteButton = wx.Button(id=ID_VARIABLEEDITORPANELDELETEBUTTON, label=_('Delete'),
       
  4240               name='DeleteButton', parent=self.ControlPanel, pos=wx.Point(0, 0),
       
  4241               size=wx.DefaultSize, style=0)
       
  4242         self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_VARIABLEEDITORPANELDELETEBUTTON)
       
  4243 
       
  4244         self.UpButton = wx.Button(id=ID_VARIABLEEDITORPANELUPBUTTON, label='^',
       
  4245               name='UpButton', parent=self.ControlPanel, pos=wx.Point(0, 0),
       
  4246               size=wx.Size(32, 32), style=0)
       
  4247         self.Bind(wx.EVT_BUTTON, self.OnUpButton, id=ID_VARIABLEEDITORPANELUPBUTTON)
       
  4248 
       
  4249         self.DownButton = wx.Button(id=ID_VARIABLEEDITORPANELDOWNBUTTON, label='v',
       
  4250               name='DownButton', parent=self.ControlPanel, pos=wx.Point(0, 0),
       
  4251               size=wx.Size(32, 32), style=0)
       
  4252         self.Bind(wx.EVT_BUTTON, self.OnDownButton, id=ID_VARIABLEEDITORPANELDOWNBUTTON)
       
  4253 
       
  4254         self._init_sizers()
       
  4255 
       
  4256     def __init__(self, parent, window, controler, element_type):
       
  4257         self._init_ctrls(parent)
       
  4258         self.ParentWindow = window
       
  4259         self.Controler = controler
       
  4260         self.ElementType = element_type
       
  4261         
       
  4262         self.Filter = "All"
       
  4263         self.FilterChoices = []
       
  4264         self.FilterChoiceTransfer = GetFilterChoiceTransfer()
       
  4265         
       
  4266         if element_type in ["config", "resource"]:
       
  4267             self.DefaultTypes = {"All" : "Global"}
       
  4268             self.DefaultValue = {"Name" : "", "Class" : "", "Type" : "INT", "Location" : "", "Initial Value" : "", "Retain" : "No", "Constant" : "No", "Edit" : True}
       
  4269         else:
       
  4270             self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"}
       
  4271             self.DefaultValue = {"Name" : "", "Class" : "", "Type" : "INT", "Location" : "", "Initial Value" : "", "Retain" : "No", "Constant" : "No", "Edit" : True}
       
  4272         if element_type in ["config", "resource"] or element_type in ["program", "transition", "action"]:
       
  4273             self.Table = VariableTable(self, [], GetVariableTableColnames(True))
       
  4274             if element_type not in ["config", "resource"]:
       
  4275                 self.FilterChoices = ["All", "Interface", "   Input", "   Output", "   InOut", "   External", "Variables", "   Local", "   Temp"]#,"Access"]
       
  4276             else:
       
  4277                 self.FilterChoices = ["All", "Global"]#,"Access"]
       
  4278             self.ColSizes = [40, 80, 70, 80, 80, 80, 60, 70]
       
  4279             self.ColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_CENTER, wx.ALIGN_CENTER]
       
  4280         else:
       
  4281             self.Table = VariableTable(self, [], GetVariableTableColnames(False))
       
  4282             if element_type == "function":
       
  4283                 self.FilterChoices = ["All", "Interface", "   Input", "   Output", "   InOut", "Variables", "   Local", "   Temp"]
       
  4284             else:
       
  4285                 self.FilterChoices = ["All", "Interface", "   Input", "   Output", "   InOut", "   External", "Variables", "   Local", "   Temp"]
       
  4286             self.ColSizes = [40, 120, 70, 80, 120, 60, 70]
       
  4287             self.ColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_CENTER, wx.ALIGN_CENTER]
       
  4288         for choice in self.FilterChoices:
       
  4289             self.ClassFilter.Append(_(choice))
       
  4290         reverse_transfer = {}
       
  4291         for filter, choice in self.FilterChoiceTransfer.items():
       
  4292             reverse_transfer[choice] = filter
       
  4293         self.ClassFilter.SetStringSelection(_(reverse_transfer[self.Filter]))
       
  4294         self.RefreshTypeList()
       
  4295 
       
  4296         self.OptionList = GetAlternativeOptions()
       
  4297         
       
  4298         if element_type == "function":
       
  4299             for base_type in self.Controler.GetBaseTypes():
       
  4300                 self.ReturnType.Append(base_type)
       
  4301             self.ReturnType.Enable(True)
       
  4302         else:
       
  4303             self.ReturnType.Enable(False)
       
  4304             self.staticText1.Hide()
       
  4305             self.ReturnType.Hide()
       
  4306             
       
  4307         self.VariablesGrid.SetTable(self.Table)
       
  4308         self.VariablesGrid.SetRowLabelSize(0)
       
  4309         for col in range(self.Table.GetNumberCols()):
       
  4310             attr = wx.grid.GridCellAttr()
       
  4311             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
       
  4312             self.VariablesGrid.SetColAttr(col, attr)
       
  4313             self.VariablesGrid.SetColMinimalWidth(col, self.ColSizes[col])
       
  4314             self.VariablesGrid.AutoSizeColumn(col, False)
       
  4315     
       
  4316     def SetTagName(self, tagname):
       
  4317         self.TagName = tagname
       
  4318     
       
  4319     def IsFunctionBlockType(self, name):
       
  4320         bodytype = self.Controler.GetEditedElementBodyType(self.TagName)
       
  4321         pouname, poutype = self.Controler.GetEditedElementType(self.TagName)
       
  4322         if poutype != "function" and bodytype in ["ST", "IL"]:
       
  4323             return False
       
  4324         else:
       
  4325             return name in self.Controler.GetFunctionBlockTypes(self.TagName)
       
  4326     
       
  4327     def RefreshView(self):
       
  4328         self.PouNames = self.Controler.GetProjectPouNames()
       
  4329         
       
  4330         words = self.TagName.split("::")
       
  4331         if self.ElementType == "config":
       
  4332             self.PouIsUsed = False
       
  4333             returnType = None
       
  4334             self.Values = self.Controler.GetConfigurationGlobalVars(words[1])
       
  4335         elif self.ElementType == "resource":
       
  4336             self.PouIsUsed = False
       
  4337             returnType = None
       
  4338             self.Values = self.Controler.GetConfigurationResourceGlobalVars(words[1], words[2])
       
  4339         else:
       
  4340             self.PouIsUsed = self.Controler.PouIsUsed(words[1])
       
  4341             returnType = self.Controler.GetEditedElementInterfaceReturnType(self.TagName)
       
  4342             self.Values = self.Controler.GetEditedElementInterfaceVars(self.TagName)
       
  4343         
       
  4344         if returnType and self.ReturnType.IsEnabled():
       
  4345             self.ReturnType.SetStringSelection(returnType)
       
  4346         
       
  4347         self.RefreshValues()
       
  4348         self.RefreshButtons()
       
  4349     
       
  4350     def OnReturnTypeChanged(self, event):
       
  4351         words = self.TagName.split("::")
       
  4352         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
       
  4353         self.Controler.BufferProject()
       
  4354         self.ParentWindow.RefreshEditor(variablepanel = False)
       
  4355         self.ParentWindow._Refresh(TITLE, EDITMENU, INSTANCESTREE, LIBRARYTREE)
       
  4356         event.Skip()
       
  4357     
       
  4358     def OnClassFilter(self, event):
       
  4359         self.Filter = self.FilterChoiceTransfer[self.ClassFilter.GetStringSelection()]
       
  4360         self.RefreshTypeList()
       
  4361         self.RefreshValues()
       
  4362         self.RefreshButtons()
       
  4363         event.Skip()
       
  4364 
       
  4365     def RefreshTypeList(self):
       
  4366         if self.Filter == "All":
       
  4367             self.ClassList = [self.FilterChoiceTransfer[choice] for choice in self.FilterChoices if self.FilterChoiceTransfer[choice] not in ["All","Interface","Variables"]]
       
  4368         elif self.Filter == "Interface":
       
  4369             self.ClassList = ["Input","Output","InOut","External"]
       
  4370         elif self.Filter == "Variables":
       
  4371             self.ClassList = ["Local","Temp"]
       
  4372         else:
       
  4373             self.ClassList = [self.Filter]
       
  4374 
       
  4375     def RefreshButtons(self):
       
  4376         if getattr(self, "Table", None):
       
  4377             table_length = len(self.Table.data)
       
  4378             row_class = None
       
  4379             row_edit = True
       
  4380             if table_length > 0:
       
  4381                 row = self.VariablesGrid.GetGridCursorRow()
       
  4382                 row_edit = self.Table.GetValueByName(row, "Edit")
       
  4383                 if self.PouIsUsed:
       
  4384                     row_class = self.Table.GetValueByName(row, "Class")
       
  4385             self.AddButton.Enable(not self.PouIsUsed or self.Filter not in ["Interface", "Input", "Output", "InOut"])
       
  4386             self.DeleteButton.Enable(table_length > 0 and row_edit and row_class not in ["Input", "Output", "InOut"])
       
  4387             self.UpButton.Enable(table_length > 0 and self.Filter == "All" and row_class not in ["Input", "Output", "InOut"])
       
  4388             self.DownButton.Enable(table_length > 0 and self.Filter == "All" and row_class not in ["Input", "Output", "InOut"])
       
  4389 
       
  4390     def OnAddButton(self, event):
       
  4391         new_row = self.DefaultValue.copy()
       
  4392         if self.Filter in self.DefaultTypes:
       
  4393             new_row["Class"] = self.DefaultTypes[self.Filter]
       
  4394         else:
       
  4395             new_row["Class"] = self.Filter
       
  4396         if self.Filter == "All" and len(self.Values) > 0:
       
  4397             row_index = self.VariablesGrid.GetGridCursorRow() + 1
       
  4398             self.Values.insert(row_index, new_row)
       
  4399         else:
       
  4400             row_index = -1
       
  4401             self.Values.append(new_row)
       
  4402         self.SaveValues()
       
  4403         self.RefreshValues(row_index)
       
  4404         self.RefreshButtons()
       
  4405         event.Skip()
       
  4406 
       
  4407     def OnDeleteButton(self, event):
       
  4408         row = self.Table.GetRow(self.VariablesGrid.GetGridCursorRow())
       
  4409         self.Values.remove(row)
       
  4410         self.SaveValues()
       
  4411         self.RefreshValues()
       
  4412         self.RefreshButtons()
       
  4413         event.Skip()
       
  4414 
       
  4415     def OnUpButton(self, event):
       
  4416         self.MoveValue(self.VariablesGrid.GetGridCursorRow(), -1)
       
  4417         self.RefreshButtons()
       
  4418         event.Skip()
       
  4419 
       
  4420     def OnDownButton(self, event):
       
  4421         self.MoveValue(self.VariablesGrid.GetGridCursorRow(), 1)
       
  4422         self.RefreshButtons()
       
  4423         event.Skip()
       
  4424 
       
  4425     def OnVariablesGridCellChange(self, event):
       
  4426         row, col = event.GetRow(), event.GetCol()
       
  4427         colname = self.Table.GetColLabelValue(col, False)
       
  4428         value = self.Table.GetValue(row, col)
       
  4429         if colname == "Name" and value != "":
       
  4430             if not TestIdentifier(value):
       
  4431                 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%value, _("Error"), wx.OK|wx.ICON_ERROR)
       
  4432                 message.ShowModal()
       
  4433                 message.Destroy()
       
  4434                 event.Veto()
       
  4435             elif value.upper() in IEC_KEYWORDS:
       
  4436                 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%value, _("Error"), wx.OK|wx.ICON_ERROR)
       
  4437                 message.ShowModal()
       
  4438                 message.Destroy()
       
  4439                 event.Veto()
       
  4440             elif value.upper() in self.PouNames:
       
  4441                 message = wx.MessageDialog(self, _("A pou with \"%s\" as name exists!")%value, _("Error"), wx.OK|wx.ICON_ERROR)
       
  4442                 message.ShowModal()
       
  4443                 message.Destroy()
       
  4444                 event.Veto()
       
  4445             elif value.upper() in [var["Name"].upper() for var in self.Values if var != self.Table.data[row]]:
       
  4446                 message = wx.MessageDialog(self, _("A variable with \"%s\" as name already exists in this pou!")%value, _("Error"), wx.OK|wx.ICON_ERROR)
       
  4447                 message.ShowModal()
       
  4448                 message.Destroy()
       
  4449                 event.Veto()
       
  4450             else:
       
  4451                 self.SaveValues(False)
       
  4452                 old_value = self.Table.GetOldValue()
       
  4453                 if old_value != "":
       
  4454                     self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_value, value)
       
  4455                 self.Controler.BufferProject()
       
  4456                 self.ParentWindow.RefreshEditor(variablepanel = False)
       
  4457                 self.ParentWindow._Refresh(TITLE, EDITMENU, INSTANCESTREE, LIBRARYTREE)
       
  4458                 event.Skip()
       
  4459         else:
       
  4460             self.SaveValues()
       
  4461             if colname == "Class":
       
  4462                 self.Table.ResetView(self.VariablesGrid)
       
  4463             event.Skip()
       
  4464     
       
  4465     def OnVariablesGridEditorShown(self, event):
       
  4466         row, col = event.GetRow(), event.GetCol() 
       
  4467         classtype = self.Table.GetValueByName(row, "Class")
       
  4468         if self.Table.GetColLabelValue(col) == "Type":
       
  4469             type_menu = wx.Menu(title='')
       
  4470             base_menu = wx.Menu(title='')
       
  4471             for base_type in self.Controler.GetBaseTypes():
       
  4472                 new_id = wx.NewId()
       
  4473                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
       
  4474                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
       
  4475             type_menu.AppendMenu(wx.NewId(), _("Base Types"), base_menu)
       
  4476             datatype_menu = wx.Menu(title='')
       
  4477             for datatype in self.Controler.GetDataTypes(basetypes = False):
       
  4478                 new_id = wx.NewId()
       
  4479                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
       
  4480                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
       
  4481             type_menu.AppendMenu(wx.NewId(), _("User Data Types"), datatype_menu)
       
  4482             functionblock_menu = wx.Menu(title='')
       
  4483             bodytype = self.Controler.GetEditedElementBodyType(self.TagName)
       
  4484             pouname, poutype = self.Controler.GetEditedElementType(self.TagName)
       
  4485             if classtype in ["Input","Output","InOut","External","Global"] or poutype != "function" and bodytype in ["ST", "IL"]:
       
  4486                 for functionblock_type in self.Controler.GetFunctionBlockTypes(self.TagName):
       
  4487                     new_id = wx.NewId()
       
  4488                     AppendMenu(functionblock_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=functionblock_type)
       
  4489                     self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(functionblock_type), id=new_id)
       
  4490                 type_menu.AppendMenu(wx.NewId(), _("Function Block Types"), functionblock_menu)
       
  4491             rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
       
  4492             self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
       
  4493             event.Veto()
       
  4494         else:
       
  4495             event.Skip()
       
  4496     
       
  4497     def GetVariableTypeFunction(self, base_type):
       
  4498         def VariableTypeFunction(event):
       
  4499             row = self.VariablesGrid.GetGridCursorRow()
       
  4500             self.Table.SetValueByName(row, "Type", base_type)
       
  4501             self.Table.ResetView(self.VariablesGrid)
       
  4502             self.SaveValues(False)
       
  4503             self.ParentWindow.RefreshEditor(variablepanel = False)
       
  4504             self.Controler.BufferProject()
       
  4505             self.ParentWindow._Refresh(TITLE, EDITMENU, INSTANCESTREE, LIBRARYTREE)
       
  4506             event.Skip()
       
  4507         return VariableTypeFunction
       
  4508     
       
  4509     def OnVariablesGridCellLeftClick(self, event):
       
  4510         row = event.GetRow()
       
  4511         if event.GetCol() == 0 and self.Table.GetValueByName(row, "Edit"):
       
  4512             row = event.GetRow()
       
  4513             var_name = self.Table.GetValueByName(row, "Name")
       
  4514             var_class = self.Table.GetValueByName(row, "Class")
       
  4515             var_type = self.Table.GetValueByName(row, "Type")
       
  4516             data = wx.TextDataObject(str((var_name, var_class, var_type, self.TagName)))
       
  4517             dragSource = wx.DropSource(self.VariablesGrid)
       
  4518             dragSource.SetData(data)
       
  4519             dragSource.DoDragDrop()
       
  4520         event.Skip()
       
  4521     
       
  4522     def OnVariablesGridSelectCell(self, event):
       
  4523         wx.CallAfter(self.RefreshButtons)
       
  4524         event.Skip()
       
  4525 
       
  4526     def OnChar(self, event):
       
  4527         keycode = event.GetKeyCode()
       
  4528         if keycode == wx.WXK_DELETE:
       
  4529             row = self.Table.GetRow(self.VariablesGrid.GetGridCursorRow())
       
  4530             self.Values.remove(row)
       
  4531             self.SaveValues()
       
  4532             self.RefreshValues()
       
  4533             self.RefreshButtons()
       
  4534         event.Skip()
       
  4535 
       
  4536     def MoveValue(self, value_index, move):
       
  4537         new_index = max(0, min(value_index + move, len(self.Values) - 1))
       
  4538         if new_index != value_index:
       
  4539             self.Values.insert(new_index, self.Values.pop(value_index))
       
  4540             self.SaveValues()
       
  4541             self.RefreshValues()
       
  4542             self.VariablesGrid.SetGridCursor(new_index, self.VariablesGrid.GetGridCursorCol())
       
  4543         
       
  4544     def RefreshValues(self, select=0):
       
  4545         if len(self.Table.data) > 0:
       
  4546             self.VariablesGrid.SetGridCursor(0, 1)
       
  4547         data = []
       
  4548         for num, variable in enumerate(self.Values):
       
  4549             if variable["Class"] in self.ClassList:
       
  4550                 variable["Number"] = num + 1
       
  4551                 data.append(variable)
       
  4552         self.Table.SetData(data)
       
  4553         if len(self.Table.data) > 0:
       
  4554             if select == -1:
       
  4555                 select = len(self.Table.data) - 1
       
  4556             self.VariablesGrid.SetGridCursor(select, 1)
       
  4557             self.VariablesGrid.MakeCellVisible(select, 1)
       
  4558         self.Table.ResetView(self.VariablesGrid)
       
  4559 
       
  4560     def SaveValues(self, buffer = True):
       
  4561         words = self.TagName.split("::")
       
  4562         if self.ElementType == "config":
       
  4563             self.Controler.SetConfigurationGlobalVars(words[1], self.Values)
       
  4564         elif self.ElementType == "resource":
       
  4565             self.Controler.SetConfigurationResourceGlobalVars(words[1], words[2], self.Values)
       
  4566         else:
       
  4567             if self.ReturnType.IsEnabled():
       
  4568                 self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
       
  4569             self.Controler.SetPouInterfaceVars(words[1], self.Values)
       
  4570         if buffer:
       
  4571             self.Controler.BufferProject()
       
  4572             self.ParentWindow._Refresh(TITLE, EDITMENU, INSTANCESTREE, LIBRARYTREE)
       
  4573 
       
  4574     def AddVariableError(self, infos):
       
  4575         if isinstance(infos[0], TupleType):
       
  4576             for i in xrange(*infos[0]):
       
  4577                 self.Table.AddError((i,) + infos[1:])
       
  4578         else:
       
  4579             self.Table.AddError(infos)
       
  4580         self.Table.ResetView(self.VariablesGrid)
       
  4581 
       
  4582     def ClearErrors(self):
       
  4583         self.Table.ClearErrors()
       
  4584         self.Table.ResetView(self.VariablesGrid)
       
  4585 
       
  4586 #-------------------------------------------------------------------------------
       
  4587 #                            Debug Variables Panel
  3877 #                            Debug Variables Panel
  4588 #-------------------------------------------------------------------------------
  3878 #-------------------------------------------------------------------------------
  4589 
  3879 
  4590 def GetDebugVariablesTableColnames():
  3880 def GetDebugVariablesTableColnames():
  4591     _ = lambda x : x
  3881     _ = lambda x : x
  4842               size=wx.DefaultSize, style=0)
  4132               size=wx.DefaultSize, style=0)
  4843         self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DEBUGVARIABLEPANELDELETEBUTTON)
  4133         self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DEBUGVARIABLEPANELDELETEBUTTON)
  4844         
  4134         
  4845         self._init_sizers()
  4135         self._init_sizers()
  4846     
  4136     
  4847     def __init__(self, parent, controler):
  4137     def __init__(self, parent, producer):
  4848         self._init_ctrls(parent)
  4138         self._init_ctrls(parent)
  4849         DebugViewer.__init__(self, controler, True)
  4139         DebugViewer.__init__(self, producer, True)
  4850         self.Controler = controler
       
  4851         self.HasNewData = False
  4140         self.HasNewData = False
  4852         
  4141         
  4853         self.Table = DebugVariableTable(self, [], GetDebugVariablesTableColnames())
  4142         self.Table = DebugVariableTable(self, [], GetDebugVariablesTableColnames())
  4854         self.VariablesGrid.SetTable(self.Table)
  4143         self.VariablesGrid.SetTable(self.Table)
  4855         self.VariablesGrid.SetRowLabelSize(0)
  4144         self.VariablesGrid.SetRowLabelSize(0)
  5025     if cap:
  4314     if cap:
  5026         cap.ReleaseMouse()
  4315         cap.ReleaseMouse()
  5027 
  4316 
  5028     dlg = wx.SingleChoiceDialog(None, 
  4317     dlg = wx.SingleChoiceDialog(None, 
  5029         _("""
  4318         _("""
  5030 An error happens.
  4319 An error has occurred.
  5031 
  4320 
  5032 Click on OK for saving an error report.
  4321 Click OK to save an error report.
  5033 
  4322 
  5034 Please contact LOLITech at:
  4323 Please contact LOLITech at:
  5035 +33 (0)3 29 57 60 42
  4324 +33 (0)3 29 57 60 42
  5036 bugs_PLCOpenEditor@lolitech.fr
  4325 bugs_PLCOpenEditor@lolitech.fr
  5037 
  4326