]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/subindextable.py
Problem with Real types unsupported fixed
[CanFestival-3.git] / objdictgen / subindextable.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
5 #
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
7 #
8 #See COPYING file for copyrights details.
9 #
10 #This library is free software; you can redistribute it and/or
11 #modify it under the terms of the GNU Lesser General Public
12 #License as published by the Free Software Foundation; either
13 #version 2.1 of the License, or (at your option) any later version.
14 #
15 #This library is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 #Lesser General Public License for more details.
19 #
20 #You should have received a copy of the GNU Lesser General Public
21 #License along with this library; if not, write to the Free Software
22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24 import wx
25 import wx.grid
26
27 from types import *
28 from commondialogs import *
29
30 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes
31
32 ColSizes = [75, 250, 150, 125, 100, 60, 250]
33 ColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_CENTER, wx.ALIGN_CENTER, wx.ALIGN_LEFT]
34 AccessList = "Read Only,Write Only,Read/Write"
35 RAccessList = "Read Only,Read/Write"
36 BoolList = "True,False"
37 OptionList = "Yes,No"
38
39 DictionaryOrganisation = [
40     {"minIndex" : 0x0001, "maxIndex" : 0x0FFF, "name" : "Data Type Definitions"},
41     {"minIndex" : 0x1000, "maxIndex" : 0x1029, "name" : "Communication Parameters"},
42     {"minIndex" : 0x1200, "maxIndex" : 0x12FF, "name" : "SDO Parameters"},
43     {"minIndex" : 0x1400, "maxIndex" : 0x15FF, "name" : "Receive PDO Parameters"},
44     {"minIndex" : 0x1600, "maxIndex" : 0x17FF, "name" : "Receive PDO Mapping"},
45     {"minIndex" : 0x1800, "maxIndex" : 0x19FF, "name" : "Transmit PDO Parameters"},
46     {"minIndex" : 0x1A00, "maxIndex" : 0x1BFF, "name" : "Transmit PDO Mapping"},
47     {"minIndex" : 0x1C00, "maxIndex" : 0x1FFF, "name" : "Other Communication Parameters"},
48     {"minIndex" : 0x2000, "maxIndex" : 0x5FFF, "name" : "Manufacturer Specific"},
49     {"minIndex" : 0x6000, "maxIndex" : 0x9FFF, "name" : "Standardized Device Profile"},
50     {"minIndex" : 0xA000, "maxIndex" : 0xBFFF, "name" : "Standardized Interface Profile"}]
51
52 SizeConversion = {1 : "X", 8 : "B", 16 : "W", 24 : "D", 32 : "D", 40 : "L", 48 : "L", 56 : "L", 64 : "L"}
53
54 class SubindexTable(wx.grid.PyGridTableBase):
55     
56     """
57     A custom wxGrid Table using user supplied data
58     """
59     def __init__(self, parent, data, editors, colnames):
60         # The base class must be initialized *first*
61         wx.grid.PyGridTableBase.__init__(self)
62         self.data = data
63         self.editors = editors
64         self.CurrentIndex = 0
65         self.colnames = colnames
66         self.Parent = parent
67         self.Editable = True
68         # XXX
69         # we need to store the row length and collength to
70         # see if the table has changed size
71         self._rows = self.GetNumberRows()
72         self._cols = self.GetNumberCols()
73     
74     def Disable(self):
75         self.Editable = False
76         
77     def Enable(self):
78         self.Editable = True
79     
80     def GetNumberCols(self):
81         return len(self.colnames)
82         
83     def GetNumberRows(self):
84         return len(self.data)
85
86     def GetColLabelValue(self, col):
87         if col < len(self.colnames):
88             return self.colnames[col]
89
90     def GetRowLabelValues(self, row):
91         return row
92
93     def GetValue(self, row, col):
94         if row < self.GetNumberRows():
95             return str(self.data[row].get(self.GetColLabelValue(col), ""))
96             
97     def GetEditor(self, row, col):
98         if row < self.GetNumberRows():
99             return self.editors[row].get(self.GetColLabelValue(col), "")
100     
101     def GetValueByName(self, row, colname):
102         return self.data[row].get(colname)
103
104     def SetValue(self, row, col, value):
105         if col < len(self.colnames):
106             self.data[row][self.GetColLabelValue(col)] = value
107         
108     def ResetView(self, grid):
109         """
110         (wx.grid.Grid) -> Reset the grid view.   Call this to
111         update the grid if rows and columns have been added or deleted
112         """
113         grid.BeginBatch()
114         for current, new, delmsg, addmsg in [
115             (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
116             (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
117         ]:
118             if new < current:
119                 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
120                 grid.ProcessTableMessage(msg)
121             elif new > current:
122                 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
123                 grid.ProcessTableMessage(msg)
124                 self.UpdateValues(grid)
125         grid.EndBatch()
126
127         self._rows = self.GetNumberRows()
128         self._cols = self.GetNumberCols()
129         # update the column rendering scheme
130         self._updateColAttrs(grid)
131
132         # update the scrollbars and the displayed part of the grid
133         grid.AdjustScrollbars()
134         grid.ForceRefresh()
135
136
137     def UpdateValues(self, grid):
138         """Update all displayed values"""
139         # This sends an event to the grid table to update all of the values
140         msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
141         grid.ProcessTableMessage(msg)
142
143     def _updateColAttrs(self, grid):
144         """
145         wx.grid.Grid -> update the column attributes to add the
146         appropriate renderer given the column name.
147
148         Otherwise default to the default renderer.
149         """
150         
151         for col in range(self.GetNumberCols()):
152             attr = wx.grid.GridCellAttr()
153             attr.SetAlignment(ColAlignements[col], wx.ALIGN_CENTRE)
154             grid.SetColAttr(col, attr)
155             grid.SetColSize(col, ColSizes[col])
156         
157         typelist = None
158         maplist = None
159         for row in range(self.GetNumberRows()):
160             editors = self.editors[row]
161             for col in range(self.GetNumberCols()):
162                 editor = None
163                 renderer = None
164                 
165                 colname = self.GetColLabelValue(col)
166                 editortype = editors[colname]
167                 if editortype and self.Editable:
168                     grid.SetReadOnly(row, col, False)
169                     if editortype == "string":
170                         editor = wx.grid.GridCellTextEditor()
171                         renderer = wx.grid.GridCellStringRenderer()
172                         if colname == "value" and "length" in editors:
173                             editor.SetParameters(editors["length"]) 
174                     elif editortype == "number":
175                         editor = wx.grid.GridCellNumberEditor()
176                         renderer = wx.grid.GridCellNumberRenderer()
177                         if colname == "value" and "min" in editors and "max" in editors:
178                             editor.SetParameters("%s,%s"%(editors["min"],editors["max"]))
179                     elif editortype == "float":
180                         editor = wx.grid.GridCellTextEditor()
181                         renderer = wx.grid.GridCellStringRenderer()
182                     elif editortype == "bool":
183                         editor = wx.grid.GridCellChoiceEditor()
184                         editor.SetParameters(BoolList)
185                     elif editortype == "access":
186                         editor = wx.grid.GridCellChoiceEditor()
187                         editor.SetParameters(AccessList)
188                     elif editortype == "raccess":
189                         editor = wx.grid.GridCellChoiceEditor()
190                         editor.SetParameters(RAccessList)
191                     elif editortype == "option":
192                         editor = wx.grid.GridCellChoiceEditor()
193                         editor.SetParameters(OptionList)
194                     elif editortype == "type":
195                         editor = wx.grid.GridCellChoiceEditor()
196                         if typelist == None:
197                             typelist = self.Parent.Manager.GetCurrentTypeList()
198                         editor.SetParameters(typelist)
199                     elif editortype == "map":
200                         editor = wx.grid.GridCellChoiceEditor()
201                         if maplist == None:
202                             maplist = self.Parent.Manager.GetCurrentMapList()
203                         editor.SetParameters(maplist)
204                     elif editortype == "time":
205                         editor = wx.grid.GridCellTextEditor()
206                         renderer = wx.grid.GridCellStringRenderer()
207                     elif editortype == "domain":
208                         editor = wx.grid.GridCellTextEditor()
209                         renderer = wx.grid.GridCellStringRenderer()
210                     elif editortype == "dcf":
211                         editor = wx.grid.GridCellTextEditor()
212                         renderer = wx.grid.GridCellStringRenderer()
213                 else:
214                     grid.SetReadOnly(row, col, True)
215                     
216                 grid.SetCellEditor(row, col, editor)
217                 grid.SetCellRenderer(row, col, renderer)
218                 
219                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
220     
221     def SetData(self, data):
222         self.data = data
223         
224     def SetEditors(self, editors):
225         self.editors = editors
226     
227     def GetCurrentIndex(self):
228         return self.CurrentIndex
229     
230     def SetCurrentIndex(self, index):
231         self.CurrentIndex = index
232     
233     def AppendRow(self, row_content):
234         self.data.append(row_content)
235
236     def Empty(self):
237         self.data = []
238         self.editors = []
239
240 [ID_EDITINGPANEL, ID_EDITINGPANELADDBUTTON, ID_EDITINGPANELINDEXCHOICE, 
241  ID_EDITINGPANELINDEXLIST, ID_EDITINGPANELINDEXLISTPANEL, ID_EDITINGPANELPARTLIST, 
242  ID_EDITINGPANELSECONDSPLITTER, ID_EDITINGPANELSUBINDEXGRID,
243  ID_EDITINGPANELSUBINDEXGRIDPANEL, ID_EDITINGPANELCALLBACKCHECK,
244 ] = [wx.NewId() for _init_ctrls in range(10)]
245
246 [ID_EDITINGPANELINDEXLISTMENUITEMS0, ID_EDITINGPANELINDEXLISTMENUITEMS1, 
247  ID_EDITINGPANELINDEXLISTMENUITEMS2, 
248 ] = [wx.NewId() for _init_coll_IndexListMenu_Items in range(3)]
249
250 [ID_EDITINGPANELMENU1ITEMS0, ID_EDITINGPANELMENU1ITEMS1, 
251  ID_EDITINGPANELMENU1ITEMS3, ID_EDITINGPANELMENU1ITEMS4, 
252 ] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(4)]
253
254 class EditingPanel(wx.SplitterWindow):
255     def _init_coll_AddToListSizer_Items(self, parent):
256         parent.AddWindow(self.AddButton, 0, border=0, flag=0)
257         parent.AddWindow(self.IndexChoice, 0, border=0, flag=wx.GROW)
258
259     def _init_coll_SubindexGridSizer_Items(self, parent):
260         parent.AddWindow(self.CallbackCheck, 0, border=0, flag=0)
261         parent.AddWindow(self.SubindexGrid, 0, border=0, flag=wx.GROW)
262
263     def _init_coll_IndexListSizer_Items(self, parent):
264         parent.AddWindow(self.IndexList, 0, border=0, flag=wx.GROW)
265         parent.AddSizer(self.AddToListSizer, 0, border=0, flag=wx.GROW)
266
267     def _init_coll_AddToListSizer_Growables(self, parent):
268         parent.AddGrowableCol(1)
269
270     def _init_coll_SubindexGridSizer_Growables(self, parent):
271         parent.AddGrowableCol(0)
272         parent.AddGrowableRow(1)
273
274     def _init_coll_IndexListSizer_Growables(self, parent):
275         parent.AddGrowableCol(0)
276         parent.AddGrowableRow(0)
277
278     def _init_coll_SubindexGridMenu_Items(self, parent):
279         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS0,
280               kind=wx.ITEM_NORMAL, text='Add subindexes')
281         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS1,
282               kind=wx.ITEM_NORMAL, text='Delete subindexes')
283         parent.AppendSeparator()
284         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3,
285               kind=wx.ITEM_NORMAL, text='Default value')
286         if not self.Editable:
287             parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS4,
288                   kind=wx.ITEM_NORMAL, text='Add to DCF')
289         self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu,
290               id=ID_EDITINGPANELMENU1ITEMS0)
291         self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu,
292               id=ID_EDITINGPANELMENU1ITEMS1)
293         self.Bind(wx.EVT_MENU, self.OnDefaultValueSubindexMenu,
294               id=ID_EDITINGPANELMENU1ITEMS3)
295         if not self.Editable:
296             self.Bind(wx.EVT_MENU, self.OnAddToDCFSubindexMenu,
297                   id=ID_EDITINGPANELMENU1ITEMS4)
298
299     def _init_coll_IndexListMenu_Items(self, parent):
300         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0,
301               kind=wx.ITEM_NORMAL, text='Rename')
302         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS2,
303               kind=wx.ITEM_NORMAL, text='Modify')
304         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS1,
305               kind=wx.ITEM_NORMAL, text='Delete')
306         self.Bind(wx.EVT_MENU, self.OnRenameIndexMenu,
307               id=ID_EDITINGPANELINDEXLISTMENUITEMS0)
308         self.Bind(wx.EVT_MENU, self.OnDeleteIndexMenu,
309               id=ID_EDITINGPANELINDEXLISTMENUITEMS1)
310         self.Bind(wx.EVT_MENU, self.OnModifyIndexMenu,
311               id=ID_EDITINGPANELINDEXLISTMENUITEMS2)
312
313     def _init_utils(self):
314         self.IndexListMenu = wx.Menu(title='')
315         self.SubindexGridMenu = wx.Menu(title='')
316
317         self._init_coll_IndexListMenu_Items(self.IndexListMenu)
318         self._init_coll_SubindexGridMenu_Items(self.SubindexGridMenu)
319
320     def _init_sizers(self):
321         self.IndexListSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
322         self.SubindexGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
323         self.AddToListSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0)
324
325         self._init_coll_IndexListSizer_Growables(self.IndexListSizer)
326         self._init_coll_IndexListSizer_Items(self.IndexListSizer)
327         self._init_coll_SubindexGridSizer_Growables(self.SubindexGridSizer)
328         self._init_coll_SubindexGridSizer_Items(self.SubindexGridSizer)
329         self._init_coll_AddToListSizer_Growables(self.AddToListSizer)
330         self._init_coll_AddToListSizer_Items(self.AddToListSizer)
331
332         self.SubindexGridPanel.SetSizer(self.SubindexGridSizer)
333         self.IndexListPanel.SetSizer(self.IndexListSizer)
334         
335     def _init_ctrls(self, prnt):
336         wx.SplitterWindow.__init__(self, id=ID_EDITINGPANEL,
337               name='MainSplitter', parent=prnt, point=wx.Point(0, 0),
338               size=wx.Size(-1, -1), style=wx.SP_3D)
339         self._init_utils()
340         self.SetNeedUpdating(True)
341         self.SetMinimumPaneSize(1)
342
343         self.PartList = wx.ListBox(choices=[], id=ID_EDITINGPANELPARTLIST,
344               name='PartList', parent=self, pos=wx.Point(0, 0),
345               size=wx.Size(-1, -1), style=0)
346         self.PartList.Bind(wx.EVT_LISTBOX, self.OnPartListBoxClick,
347               id=ID_EDITINGPANELPARTLIST)
348
349         self.SecondSplitter = wx.SplitterWindow(id=ID_EDITINGPANELSECONDSPLITTER,
350               name='SecondSplitter', parent=self, point=wx.Point(0, 0), 
351               size=wx.Size(-1, -1), style=wx.SP_3D)
352         self.SecondSplitter.SetMinimumPaneSize(1)
353         self.SplitHorizontally(self.PartList, self.SecondSplitter,
354               110)
355
356         self.SubindexGridPanel = wx.Panel(id=ID_EDITINGPANELSUBINDEXGRIDPANEL,
357               name='SubindexGridPanel', parent=self.SecondSplitter, 
358               pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
359
360         self.IndexListPanel = wx.Panel(id=ID_EDITINGPANELINDEXLISTPANEL,
361               name='IndexListPanel', parent=self.SecondSplitter, 
362               pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
363         self.SecondSplitter.SplitVertically(self.IndexListPanel,
364               self.SubindexGridPanel, 280)
365
366         self.SubindexGrid = wx.grid.Grid(id=ID_EDITINGPANELSUBINDEXGRID,
367               name='SubindexGrid', parent=self.SubindexGridPanel, pos=wx.Point(0,
368               0), size=wx.Size(-1, -1), style=0)
369         self.SubindexGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
370               'Sans'))
371         self.SubindexGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
372               False, 'Sans'))
373         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
374               self.OnSubindexGridCellChange)
375         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK,
376               self.OnSubindexGridRightClick)
377         self.SubindexGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL,
378               self.OnSubindexGridSelectCell)
379         self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, 
380               self.OnSubindexGridCellLeftClick)
381         self.SubindexGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, 
382               self.OnSubindexGridEditorShown)
383
384         self.CallbackCheck = wx.CheckBox(id=ID_EDITINGPANELCALLBACKCHECK,
385               label='Have Callbacks', name='CallbackCheck',
386               parent=self.SubindexGridPanel, pos=wx.Point(0, 0), size=wx.Size(152,
387               24), style=0)
388         self.CallbackCheck.Bind(wx.EVT_CHECKBOX, self.OnCallbackCheck,
389               id=ID_EDITINGPANELCALLBACKCHECK)
390
391         self.IndexList = wx.ListBox(choices=[], id=ID_EDITINGPANELINDEXLIST,
392               name='IndexList', parent=self.IndexListPanel, pos=wx.Point(0, 0),
393               size=wx.Size(-1, -1), style=0)
394         self.IndexList.Bind(wx.EVT_LISTBOX, self.OnIndexListClick,
395               id=ID_EDITINGPANELINDEXLIST)
396         self.IndexList.Bind(wx.EVT_RIGHT_UP, self.OnIndexListRightUp)
397
398         self.AddButton = wx.Button(id=ID_EDITINGPANELADDBUTTON, label='Add',
399               name='AddButton', parent=self.IndexListPanel, pos=wx.Point(0, 0),
400               size=wx.Size(50, 30), style=0)
401         self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButtonClick,
402               id=ID_EDITINGPANELADDBUTTON)
403
404         self.IndexChoice = wx.Choice(choices=[], id=ID_EDITINGPANELINDEXCHOICE,
405               name='IndexChoice', parent=self.IndexListPanel, pos=wx.Point(50,
406               0), size=wx.Size(-1, 30), style=0)
407
408         self._init_sizers()
409
410     def __init__(self, parent, window, manager, editable = True):
411         self.Editable = editable
412         self._init_ctrls(parent)
413         self.ParentWindow = window
414         self.Manager = manager
415         self.ListIndex = []
416         self.ChoiceIndex = []
417         self.FirstCall = False
418         self.Index = None
419         
420         for values in DictionaryOrganisation:
421             text = "   0x%04X-0x%04X      %s"%(values["minIndex"], values["maxIndex"], values["name"])
422             self.PartList.Append(text)
423         self.Table = SubindexTable(self, [], [], ["subindex", "name", "type", "value", "access", "save", "comment"])
424         self.SubindexGrid.SetTable(self.Table)
425         self.SubindexGrid.SetRowLabelSize(0)
426         self.CallbackCheck.Disable()
427         self.Table.ResetView(self.SubindexGrid)
428
429         if not self.Editable:
430             self.AddButton.Disable()
431             self.IndexChoice.Disable()
432             self.CallbackCheck.Disable()
433             self.Table.Disable()
434
435     def GetIndex(self):
436         return self.Index
437     
438     def SetIndex(self, index):
439         self.Index = index
440
441     def GetSelection(self):
442         selected = self.IndexList.GetSelection()
443         if selected != wx.NOT_FOUND:
444             index = self.ListIndex[selected]
445             subIndex = self.SubindexGrid.GetGridCursorRow()
446             return index, subIndex
447         return None
448
449     def OnSubindexGridCellLeftClick(self, event):
450         if not self.ParentWindow.ModeSolo:
451             col = event.GetCol()
452             if not self.Editable and col == 0:
453                 selected = self.IndexList.GetSelection()
454                 if selected != wx.NOT_FOUND:
455                     index = self.ListIndex[selected]
456                     subindex = event.GetRow()
457                     entry_infos = self.Manager.GetEntryInfos(index)
458                     if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
459                         subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
460                         typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
461                         if subentry_infos["pdo"] and typeinfos:
462                             bus_id = '.'.join(map(str, self.ParentWindow.GetBusId()))
463                             node_id = self.ParentWindow.GetCurrentNodeId()
464                             size = typeinfos["size"]
465                             data = wx.TextDataObject(str(("%s%s.%d.%d.%d"%(SizeConversion[size], bus_id, node_id, index, subindex), "location")))
466                             dragSource = wx.DropSource(self.SubindexGrid)
467                             dragSource.SetData(data)
468                             dragSource.DoDragDrop()
469         event.Skip()
470
471     def OnAddButtonClick(self, event):
472         if self.Editable:
473             self.SubindexGrid.SetGridCursor(0, 0)
474             selected = self.IndexChoice.GetStringSelection()
475             if selected != "":
476                 if selected == "User Type":
477                     self.ParentWindow.AddUserType()
478                 elif selected == "SDO Server":
479                     self.Manager.AddSDOServerToCurrent()
480                 elif selected == "SDO Client":
481                     self.Manager.AddSDOClientToCurrent()
482                 elif selected == "PDO Receive":
483                     self.Manager.AddPDOReceiveToCurrent()
484                 elif selected == "PDO Transmit":
485                     self.Manager.AddPDOTransmitToCurrent()
486                 elif selected == "Map Variable":
487                     self.ParentWindow.AddMapVariable()
488                 elif selected in [menu for menu, indexes in self.Manager.GetCurrentSpecificMenu()]:
489                     self.Manager.AddSpecificEntryToCurrent(selected)
490                 else:
491                     index = self.ChoiceIndex[self.IndexChoice.GetSelection()]
492                     self.Manager.ManageEntriesOfCurrent([index], [])
493                 self.ParentWindow.RefreshBufferState()
494                 self.RefreshIndexList()
495         event.Skip()
496
497     def OnPartListBoxClick(self, event):
498         self.SubindexGrid.SetGridCursor(0, 0)
499         self.RefreshIndexList()
500         event.Skip()
501
502     def OnIndexListClick(self, event):
503         self.SubindexGrid.SetGridCursor(0, 0)
504         self.RefreshTable()
505         event.Skip()
506
507     def OnSubindexGridSelectCell(self, event):
508         wx.CallAfter(self.ParentWindow.RefreshStatusBar)
509         event.Skip()
510
511 #-------------------------------------------------------------------------------
512 #                             Refresh Functions
513 #-------------------------------------------------------------------------------
514
515     def RefreshIndexList(self):
516         selected = self.IndexList.GetSelection()
517         choice = self.IndexChoice.GetStringSelection()
518         choiceindex = self.IndexChoice.GetSelection()
519         if selected != wx.NOT_FOUND:
520             selectedindex = self.ListIndex[selected]
521         self.IndexList.Clear()
522         self.IndexChoice.Clear()
523         i = self.PartList.GetSelection()
524         if i < len(DictionaryOrganisation):
525             values = DictionaryOrganisation[i]
526             self.ListIndex = []
527             for name, index in self.Manager.GetCurrentValidIndexes(values["minIndex"], values["maxIndex"]):
528                 self.IndexList.Append("0x%04X   %s"%(index, name))
529                 self.ListIndex.append(index)
530             if self.Editable:
531                 self.ChoiceIndex = []
532                 if i == 0:
533                     self.IndexChoice.Append("User Type")
534                     self.IndexChoice.SetStringSelection("User Type")
535                 elif i == 2:
536                     self.IndexChoice.Append("SDO Server")
537                     self.IndexChoice.Append("SDO Client")
538                     if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
539                          self.IndexChoice.SetStringSelection(choice)
540                 elif i in (3, 4):
541                     self.IndexChoice.Append("PDO Receive")
542                     self.IndexChoice.SetStringSelection("PDO Receive")
543                 elif i in (5, 6):
544                     self.IndexChoice.Append("PDO Transmit")
545                     self.IndexChoice.SetStringSelection("PDO Transmit")
546                 elif i == 8:
547                     self.IndexChoice.Append("Map Variable")
548                     self.IndexChoice.SetStringSelection("Map Variable")
549                 else:
550                     for name, index in self.Manager.GetCurrentValidChoices(values["minIndex"], values["maxIndex"]):
551                         if index:
552                             self.IndexChoice.Append("0x%04X   %s"%(index, name))
553                         else:
554                             self.IndexChoice.Append(name)
555                         self.ChoiceIndex.append(index)
556                 if choiceindex != wx.NOT_FOUND and choiceindex < self.IndexChoice.GetCount() and choice == self.IndexChoice.GetString(choiceindex):
557                     self.IndexChoice.SetStringSelection(choice)
558         if self.Editable:
559             self.IndexChoice.Enable(self.IndexChoice.GetCount() != 0)
560             self.AddButton.Enable(self.IndexChoice.GetCount() != 0)
561         if selected == wx.NOT_FOUND or selected >= len(self.ListIndex) or selectedindex != self.ListIndex[selected]:
562             self.Table.Empty()
563             self.CallbackCheck.SetValue(False)
564             self.CallbackCheck.Disable()
565             self.Table.ResetView(self.SubindexGrid)
566             self.ParentWindow.RefreshStatusBar()
567         else:
568             self.IndexList.SetSelection(selected)
569             self.RefreshTable()
570
571     def RefreshTable(self):
572         selected = self.IndexList.GetSelection()
573         if selected != wx.NOT_FOUND:
574             index = self.ListIndex[selected]
575             if index > 0x260 and self.Editable:
576                 self.CallbackCheck.Enable()
577                 self.CallbackCheck.SetValue(self.Manager.HasCurrentEntryCallbacks(index))
578             result = self.Manager.GetCurrentEntryValues(index)
579             if result != None:
580                 self.Table.SetCurrentIndex(index)
581                 data, editors = result
582                 self.Table.SetData(data)
583                 self.Table.SetEditors(editors)
584                 self.Table.ResetView(self.SubindexGrid)
585         self.ParentWindow.RefreshStatusBar()
586
587 #-------------------------------------------------------------------------------
588 #                        Editing Table value function
589 #-------------------------------------------------------------------------------
590
591     def OnSubindexGridEditorShown(self, event):
592         row, col = event.GetRow(), event.GetCol() 
593         if self.Table.GetEditor(row, col) == "dcf":
594             wx.CallAfter(self.ShowDCFEntryDialog, row, col)
595             event.Veto()
596         else:
597             event.Skip()
598
599     def ShowDCFEntryDialog(self, row, col):
600         if self.Editable:
601             selected = self.IndexList.GetSelection()
602             if selected != wx.NOT_FOUND:
603                 index = self.ListIndex[selected]
604                 if self.Manager.IsCurrentEntry(index):
605                     dialog = DCFEntryValuesDialog(self)
606                     dialog.SetValues(self.Table.GetValue(row, col).decode("hex_codec"))
607                     if dialog.ShowModal() == wx.ID_OK:
608                         value = dialog.GetValues()
609                         self.Manager.SetCurrentEntry(index, row, value, "value", "dcf")
610                         self.ParentWindow.RefreshBufferState()
611                         wx.CallAfter(self.RefreshTable)
612
613     def OnSubindexGridCellChange(self, event):
614         if self.Editable:
615             index = self.Table.GetCurrentIndex()
616             subIndex = event.GetRow()
617             col = event.GetCol()
618             name = self.Table.GetColLabelValue(col)
619             value = self.Table.GetValue(subIndex, col)
620             editor = self.Table.GetEditor(subIndex, col)
621             self.Manager.SetCurrentEntry(index, subIndex, value, name, editor)
622             self.ParentWindow.RefreshBufferState()
623             wx.CallAfter(self.RefreshTable)
624         event.Skip()
625
626     def OnCallbackCheck(self, event):
627         if self.Editable:
628             index = self.Table.GetCurrentIndex()
629             self.Manager.SetCurrentEntryCallbacks(index, self.CallbackCheck.GetValue())
630             self.ParentWindow.RefreshBufferState()
631             wx.CallAfter(self.RefreshTable)
632         event.Skip()
633
634 #-------------------------------------------------------------------------------
635 #                          Contextual Menu functions
636 #-------------------------------------------------------------------------------
637
638     def OnIndexListRightUp(self, event):
639         if self.Editable:
640             if not self.FirstCall:
641                 self.FirstCall = True
642                 selected = self.IndexList.GetSelection()
643                 if selected != wx.NOT_FOUND:
644                     index = self.ListIndex[selected]
645                     if index < 0x260:
646                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
647                         self.IndexListMenu.FindItemByPosition(1).Enable(True)
648                         self.PopupMenu(self.IndexListMenu)
649                     elif 0x1000 <= index <= 0x1FFF:
650                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
651                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
652                         self.PopupMenu(self.IndexListMenu)
653                     elif 0x2000 <= index <= 0x5FFF:
654                         self.IndexListMenu.FindItemByPosition(0).Enable(True)
655                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
656                         self.PopupMenu(self.IndexListMenu)
657                     elif index >= 0x6000:
658                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
659                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
660                         self.PopupMenu(self.IndexListMenu)
661             else:
662                 self.FirstCall = False
663         event.Skip()
664
665     def OnSubindexGridRightClick(self, event):
666         self.SubindexGrid.SetGridCursor(event.GetRow(), event.GetCol())
667         if self.Editable:
668             selected = self.IndexList.GetSelection()
669             if selected != wx.NOT_FOUND:
670                 index = self.ListIndex[selected]
671                 if self.Manager.IsCurrentEntry(index):
672                     showpopup = False
673                     infos = self.Manager.GetEntryInfos(index)
674                     if 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_MultipleSubindexes or infos["struct"] & OD_IdenticalSubindexes:
675                         showpopup = True
676                         self.SubindexGridMenu.FindItemByPosition(0).Enable(True)
677                         self.SubindexGridMenu.FindItemByPosition(1).Enable(True)
678                     else:
679                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
680                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
681                     if self.Table.GetColLabelValue(event.GetCol()) == "value":
682                         showpopup = True
683                         self.SubindexGridMenu.FindItemByPosition(3).Enable(True)
684                     else:
685                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
686                     if showpopup:
687                         self.PopupMenu(self.SubindexGridMenu)
688         elif self.Table.GetColLabelValue(event.GetCol()) == "value":
689             selected = self.IndexList.GetSelection()
690             if selected != wx.NOT_FOUND:
691                 index = self.ListIndex[selected]
692                 if self.Manager.IsCurrentEntry(index):
693                     infos = self.Manager.GetEntryInfos(index)
694                     if not infos["struct"] & OD_MultipleSubindexes or event.GetRow() > 0:
695                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
696                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
697                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
698                         self.SubindexGridMenu.FindItemByPosition(4).Enable(True)
699                         self.PopupMenu(self.SubindexGridMenu)
700         event.Skip()
701
702     def OnAddToDCFSubindexMenu(self, event):
703         if not self.Editable:
704             selected = self.IndexList.GetSelection()
705             if selected != wx.NOT_FOUND:
706                 index = self.ListIndex[selected]
707                 subindex = self.SubindexGrid.GetGridCursorRow()
708                 entry_infos = self.Manager.GetEntryInfos(index)
709                 if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
710                     subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
711                     typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
712                     if typeinfos:
713                         node_id = self.ParentWindow.GetCurrentNodeId()
714                         value = self.Table.GetValueByName(subindex, "value")
715                         if value == "True":
716                             value = 1
717                         elif value == "False":
718                             value = 0
719                         elif value.isdigit():
720                             value = int(value)
721                         elif value.startswith("0x"):
722                             value = int(value, 16)
723                         else:
724                             value = int(value.encode("hex_codec"), 16)
725                         self.Manager.AddToMasterDCF(node_id, index, subindex, max(1, typeinfos["size"] / 8), value)    
726                         self.ParentWindow.OpenMasterDCFDialog(node_id)
727
728     def OpenDCFDialog(self, node_id):
729         self.PartList.SetSelection(7)
730         self.RefreshIndexList()
731         self.IndexList.SetSelection(self.ListIndex.index(0x1F22))
732         self.RefreshTable()
733         self.SubindexGrid.SetGridCursor(node_id, 3)
734         self.ShowDCFEntryDialog(node_id, 3)
735
736     def OnRenameIndexMenu(self, event):
737         if self.Editable:
738             selected = self.IndexList.GetSelection()
739             if selected != wx.NOT_FOUND:
740                 index = self.ListIndex[selected]
741                 if self.Manager.IsCurrentEntry(index):
742                     infos = self.Manager.GetEntryInfos(index)
743                     dialog = wx.TextEntryDialog(self, "Give a new name for index 0x%04X"%index,
744                                  "Rename an index", infos["name"], wx.OK|wx.CANCEL)
745                     if dialog.ShowModal() == wx.ID_OK:
746                         self.Manager.SetCurrentEntryName(index, dialog.GetValue())
747                         self.ParentWindow.RefreshBufferState()
748                         self.RefreshIndexList()
749                     dialog.Destroy()
750         event.Skip()
751
752     def OnModifyIndexMenu(self, event):
753         if self.Editable:
754             selected = self.IndexList.GetSelection()
755             if selected != wx.NOT_FOUND:
756                 index = self.ListIndex[selected]
757                 if self.Manager.IsCurrentEntry(index) and index < 0x260:
758                     values, valuetype = self.Manager.GetCustomisedTypeValues(index)
759                     dialog = UserTypeDialog(self)
760                     dialog.SetTypeList(self.Manager.GetCustomisableTypes(), values[1])
761                     if valuetype == 0:
762                         dialog.SetValues(min = values[2], max = values[3])
763                     elif valuetype == 1:
764                         dialog.SetValues(length = values[2])
765                     if dialog.ShowModal() == wx.ID_OK:
766                         type, min, max, length = dialog.GetValues()
767                         self.Manager.SetCurrentUserType(index, type, min, max, length)
768                         self.ParentWindow.RefreshBufferState()
769                         self.RefreshIndexList()
770         event.Skip()
771         
772     def OnDeleteIndexMenu(self, event):
773         if self.Editable:
774             selected = self.IndexList.GetSelection()
775             if selected != wx.NOT_FOUND:
776                 index = self.ListIndex[selected]
777                 if self.Manager.IsCurrentEntry(index):
778                     self.Manager.ManageEntriesOfCurrent([],[index])
779                     self.ParentWindow.RefreshBufferState()
780                     self.RefreshIndexList()
781         event.Skip()
782
783     def OnAddSubindexMenu(self, event):
784         if self.Editable:
785             selected = self.IndexList.GetSelection()
786             if selected != wx.NOT_FOUND:
787                 index = self.ListIndex[selected]
788                 if self.Manager.IsCurrentEntry(index):
789                     dialog = wx.TextEntryDialog(self, "Number of subindexes to add:",
790                                  "Add subindexes", "1", wx.OK|wx.CANCEL)
791                     if dialog.ShowModal() == wx.ID_OK:
792                         try:
793                             number = int(dialog.GetValue())
794                             self.Manager.AddSubentriesToCurrent(index, number)
795                             self.ParentWindow.RefreshBufferState()
796                             self.RefreshIndexList()
797                         except:
798                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
799                             message.ShowModal()
800                             message.Destroy()
801                     dialog.Destroy()
802         event.Skip()
803
804     def OnDeleteSubindexMenu(self, event):
805         if self.Editable:
806             selected = self.IndexList.GetSelection()
807             if selected != wx.NOT_FOUND:
808                 index = self.ListIndex[selected]
809                 if self.Manager.IsCurrentEntry(index):
810                     dialog = wx.TextEntryDialog(self, "Number of subindexes to delete:",
811                                  "Delete subindexes", "1", wx.OK|wx.CANCEL)
812                     if dialog.ShowModal() == wx.ID_OK:
813                         try:
814                             number = int(dialog.GetValue())
815                             self.Manager.RemoveSubentriesFromCurrent(index, number)
816                             self.ParentWindow.RefreshBufferState()
817                             self.RefreshIndexList()
818                         except:
819                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
820                             message.ShowModal()
821                             message.Destroy()
822                     dialog.Destroy()
823         event.Skip()
824
825     def OnDefaultValueSubindexMenu(self, event):
826         if self.Editable:
827             selected = self.IndexList.GetSelection()
828             if selected != wx.NOT_FOUND:
829                 index = self.ListIndex[selected]
830                 if self.Manager.IsCurrentEntry(index):
831                     row = self.SubindexGrid.GetGridCursorRow()
832                     self.Manager.SetCurrentEntryToDefault(index, row)
833                     self.ParentWindow.RefreshBufferState()
834                     self.RefreshIndexList()
835         event.Skip()