]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/subindextable.py
Remover SillySlave from LSS build
[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 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 typeinfos:
462                             bus_id = '.'.join(map(str, self.ParentWindow.GetBusId()))
463                             size = typeinfos["size"]
464                             data = wx.TextDataObject(str(("%s%s.%d.%d"%(SizeConversion[size], bus_id, index, subindex), "location")))
465                             dragSource = wx.DropSource(self.SubindexGrid)
466                             dragSource.SetData(data)
467                             dragSource.DoDragDrop()
468             elif col == 0:
469                 selected = self.IndexList.GetSelection()
470                 if selected != wx.NOT_FOUND:
471                     index = self.ListIndex[selected]
472                     subindex = event.GetRow()
473                     entry_infos = self.Manager.GetEntryInfos(index)
474                     if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
475                         subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
476                         typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
477                         if subentry_infos["pdo"] and typeinfos:
478                             bus_id = '.'.join(map(str, self.ParentWindow.GetBusId()))
479                             node_id = self.ParentWindow.GetCurrentNodeId()
480                             size = typeinfos["size"]
481                             data = wx.TextDataObject(str(("%s%s.%d.%d.%d"%(SizeConversion[size], bus_id, node_id, index, subindex), "location")))
482                             dragSource = wx.DropSource(self.SubindexGrid)
483                             dragSource.SetData(data)
484                             dragSource.DoDragDrop()
485         event.Skip()
486
487     def OnAddButtonClick(self, event):
488         if self.Editable:
489             self.SubindexGrid.SetGridCursor(0, 0)
490             selected = self.IndexChoice.GetStringSelection()
491             if selected != "":
492                 if selected == "User Type":
493                     self.ParentWindow.AddUserType()
494                 elif selected == "SDO Server":
495                     self.Manager.AddSDOServerToCurrent()
496                 elif selected == "SDO Client":
497                     self.Manager.AddSDOClientToCurrent()
498                 elif selected == "PDO Receive":
499                     self.Manager.AddPDOReceiveToCurrent()
500                 elif selected == "PDO Transmit":
501                     self.Manager.AddPDOTransmitToCurrent()
502                 elif selected == "Map Variable":
503                     self.ParentWindow.AddMapVariable()
504                 elif selected in [menu for menu, indexes in self.Manager.GetCurrentSpecificMenu()]:
505                     self.Manager.AddSpecificEntryToCurrent(selected)
506                 else:
507                     index = self.ChoiceIndex[self.IndexChoice.GetSelection()]
508                     self.Manager.ManageEntriesOfCurrent([index], [])
509                 self.ParentWindow.RefreshBufferState()
510                 self.RefreshIndexList()
511         event.Skip()
512
513     def OnPartListBoxClick(self, event):
514         if not self.ParentWindow.IsClosing():
515             self.SubindexGrid.SetGridCursor(0, 0)
516             self.RefreshIndexList()
517         event.Skip()
518
519     def OnIndexListClick(self, event):
520         if not self.ParentWindow.IsClosing():
521             self.SubindexGrid.SetGridCursor(0, 0)
522             self.RefreshTable()
523         event.Skip()
524
525     def OnSubindexGridSelectCell(self, event):
526         if not self.ParentWindow.IsClosing():
527             wx.CallAfter(self.ParentWindow.RefreshStatusBar)
528         event.Skip()
529
530 #-------------------------------------------------------------------------------
531 #                             Refresh Functions
532 #-------------------------------------------------------------------------------
533
534     def RefreshIndexList(self):
535         selected = self.IndexList.GetSelection()
536         choice = self.IndexChoice.GetStringSelection()
537         choiceindex = self.IndexChoice.GetSelection()
538         if selected != wx.NOT_FOUND:
539             selectedindex = self.ListIndex[selected]
540         self.IndexList.Clear()
541         self.IndexChoice.Clear()
542         i = self.PartList.GetSelection()
543         if i < len(DictionaryOrganisation):
544             values = DictionaryOrganisation[i]
545             self.ListIndex = []
546             for name, index in self.Manager.GetCurrentValidIndexes(values["minIndex"], values["maxIndex"]):
547                 self.IndexList.Append("0x%04X   %s"%(index, name))
548                 self.ListIndex.append(index)
549             if self.Editable:
550                 self.ChoiceIndex = []
551                 if i == 0:
552                     self.IndexChoice.Append("User Type")
553                     self.IndexChoice.SetStringSelection("User Type")
554                 elif i == 2:
555                     self.IndexChoice.Append("SDO Server")
556                     self.IndexChoice.Append("SDO Client")
557                     if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
558                          self.IndexChoice.SetStringSelection(choice)
559                 elif i in (3, 4):
560                     self.IndexChoice.Append("PDO Receive")
561                     self.IndexChoice.SetStringSelection("PDO Receive")
562                 elif i in (5, 6):
563                     self.IndexChoice.Append("PDO Transmit")
564                     self.IndexChoice.SetStringSelection("PDO Transmit")
565                 elif i == 8:
566                     self.IndexChoice.Append("Map Variable")
567                     self.IndexChoice.SetStringSelection("Map Variable")
568                 else:
569                     for name, index in self.Manager.GetCurrentValidChoices(values["minIndex"], values["maxIndex"]):
570                         if index:
571                             self.IndexChoice.Append("0x%04X   %s"%(index, name))
572                         else:
573                             self.IndexChoice.Append(name)
574                         self.ChoiceIndex.append(index)
575                 if choiceindex != wx.NOT_FOUND and choiceindex < self.IndexChoice.GetCount() and choice == self.IndexChoice.GetString(choiceindex):
576                     self.IndexChoice.SetStringSelection(choice)
577         if self.Editable:
578             self.IndexChoice.Enable(self.IndexChoice.GetCount() != 0)
579             self.AddButton.Enable(self.IndexChoice.GetCount() != 0)
580         if selected == wx.NOT_FOUND or selected >= len(self.ListIndex) or selectedindex != self.ListIndex[selected]:
581             self.Table.Empty()
582             self.CallbackCheck.SetValue(False)
583             self.CallbackCheck.Disable()
584             self.Table.ResetView(self.SubindexGrid)
585             self.ParentWindow.RefreshStatusBar()
586         else:
587             self.IndexList.SetSelection(selected)
588             self.RefreshTable()
589
590     def RefreshTable(self):
591         selected = self.IndexList.GetSelection()
592         if selected != wx.NOT_FOUND:
593             index = self.ListIndex[selected]
594             if index > 0x260 and self.Editable:
595                 self.CallbackCheck.Enable()
596                 self.CallbackCheck.SetValue(self.Manager.HasCurrentEntryCallbacks(index))
597             result = self.Manager.GetCurrentEntryValues(index)
598             if result != None:
599                 self.Table.SetCurrentIndex(index)
600                 data, editors = result
601                 self.Table.SetData(data)
602                 self.Table.SetEditors(editors)
603                 self.Table.ResetView(self.SubindexGrid)
604         self.ParentWindow.RefreshStatusBar()
605
606 #-------------------------------------------------------------------------------
607 #                        Editing Table value function
608 #-------------------------------------------------------------------------------
609
610     def OnSubindexGridEditorShown(self, event):
611         row, col = event.GetRow(), event.GetCol() 
612         if self.Table.GetEditor(row, col) == "dcf":
613             wx.CallAfter(self.ShowDCFEntryDialog, row, col)
614             event.Veto()
615         else:
616             event.Skip()
617
618     def ShowDCFEntryDialog(self, row, col):
619         if self.Editable:
620             selected = self.IndexList.GetSelection()
621             if selected != wx.NOT_FOUND:
622                 index = self.ListIndex[selected]
623                 if self.Manager.IsCurrentEntry(index):
624                     dialog = DCFEntryValuesDialog(self)
625                     dialog.SetValues(self.Table.GetValue(row, col).decode("hex_codec"))
626                     if dialog.ShowModal() == wx.ID_OK:
627                         value = dialog.GetValues()
628                         self.Manager.SetCurrentEntry(index, row, value, "value", "dcf")
629                         self.ParentWindow.RefreshBufferState()
630                         wx.CallAfter(self.RefreshTable)
631
632     def OnSubindexGridCellChange(self, event):
633         if self.Editable:
634             index = self.Table.GetCurrentIndex()
635             subIndex = event.GetRow()
636             col = event.GetCol()
637             name = self.Table.GetColLabelValue(col)
638             value = self.Table.GetValue(subIndex, col)
639             editor = self.Table.GetEditor(subIndex, col)
640             self.Manager.SetCurrentEntry(index, subIndex, value, name, editor)
641             self.ParentWindow.RefreshBufferState()
642             wx.CallAfter(self.RefreshTable)
643         event.Skip()
644
645     def OnCallbackCheck(self, event):
646         if self.Editable:
647             index = self.Table.GetCurrentIndex()
648             self.Manager.SetCurrentEntryCallbacks(index, self.CallbackCheck.GetValue())
649             self.ParentWindow.RefreshBufferState()
650             wx.CallAfter(self.RefreshTable)
651         event.Skip()
652
653 #-------------------------------------------------------------------------------
654 #                          Contextual Menu functions
655 #-------------------------------------------------------------------------------
656
657     def OnIndexListRightUp(self, event):
658         if self.Editable:
659             if not self.FirstCall:
660                 self.FirstCall = True
661                 selected = self.IndexList.GetSelection()
662                 if selected != wx.NOT_FOUND:
663                     index = self.ListIndex[selected]
664                     if index < 0x260:
665                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
666                         self.IndexListMenu.FindItemByPosition(1).Enable(True)
667                         self.PopupMenu(self.IndexListMenu)
668                     elif 0x1000 <= index <= 0x1FFF:
669                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
670                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
671                         self.PopupMenu(self.IndexListMenu)
672                     elif 0x2000 <= index <= 0x5FFF:
673                         self.IndexListMenu.FindItemByPosition(0).Enable(True)
674                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
675                         self.PopupMenu(self.IndexListMenu)
676                     elif index >= 0x6000:
677                         self.IndexListMenu.FindItemByPosition(0).Enable(False)
678                         self.IndexListMenu.FindItemByPosition(1).Enable(False)
679                         self.PopupMenu(self.IndexListMenu)
680             else:
681                 self.FirstCall = False
682         event.Skip()
683
684     def OnSubindexGridRightClick(self, event):
685         self.SubindexGrid.SetGridCursor(event.GetRow(), event.GetCol())
686         if self.Editable:
687             selected = self.IndexList.GetSelection()
688             if selected != wx.NOT_FOUND:
689                 index = self.ListIndex[selected]
690                 if self.Manager.IsCurrentEntry(index):
691                     showpopup = False
692                     infos = self.Manager.GetEntryInfos(index)
693                     if 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_MultipleSubindexes or infos["struct"] & OD_IdenticalSubindexes:
694                         showpopup = True
695                         self.SubindexGridMenu.FindItemByPosition(0).Enable(True)
696                         self.SubindexGridMenu.FindItemByPosition(1).Enable(True)
697                     else:
698                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
699                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
700                     if self.Table.GetColLabelValue(event.GetCol()) == "value":
701                         showpopup = True
702                         self.SubindexGridMenu.FindItemByPosition(3).Enable(True)
703                     else:
704                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
705                     if showpopup:
706                         self.PopupMenu(self.SubindexGridMenu)
707         elif self.Table.GetColLabelValue(event.GetCol()) == "value":
708             selected = self.IndexList.GetSelection()
709             if selected != wx.NOT_FOUND:
710                 index = self.ListIndex[selected]
711                 if self.Manager.IsCurrentEntry(index):
712                     infos = self.Manager.GetEntryInfos(index)
713                     if not infos["struct"] & OD_MultipleSubindexes or event.GetRow() > 0:
714                         self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
715                         self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
716                         self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
717                         self.SubindexGridMenu.FindItemByPosition(4).Enable(True)
718                         self.PopupMenu(self.SubindexGridMenu)
719         event.Skip()
720
721     def OnAddToDCFSubindexMenu(self, event):
722         if not self.Editable:
723             selected = self.IndexList.GetSelection()
724             if selected != wx.NOT_FOUND:
725                 index = self.ListIndex[selected]
726                 subindex = self.SubindexGrid.GetGridCursorRow()
727                 entry_infos = self.Manager.GetEntryInfos(index)
728                 if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0:
729                     subentry_infos = self.Manager.GetSubentryInfos(index, subindex)
730                     typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"])
731                     if typeinfos:
732                         node_id = self.ParentWindow.GetCurrentNodeId()
733                         value = self.Table.GetValueByName(subindex, "value")
734                         if value == "True":
735                             value = 1
736                         elif value == "False":
737                             value = 0
738                         elif value.isdigit():
739                             value = int(value)
740                         elif value.startswith("0x"):
741                             value = int(value, 16)
742                         else:
743                             value = int(value.encode("hex_codec"), 16)
744                         self.Manager.AddToMasterDCF(node_id, index, subindex, max(1, typeinfos["size"] / 8), value)    
745                         self.ParentWindow.OpenMasterDCFDialog(node_id)
746
747     def OpenDCFDialog(self, node_id):
748         self.PartList.SetSelection(7)
749         self.RefreshIndexList()
750         self.IndexList.SetSelection(self.ListIndex.index(0x1F22))
751         self.RefreshTable()
752         self.SubindexGrid.SetGridCursor(node_id, 3)
753         self.ShowDCFEntryDialog(node_id, 3)
754
755     def OnRenameIndexMenu(self, event):
756         if self.Editable:
757             selected = self.IndexList.GetSelection()
758             if selected != wx.NOT_FOUND:
759                 index = self.ListIndex[selected]
760                 if self.Manager.IsCurrentEntry(index):
761                     infos = self.Manager.GetEntryInfos(index)
762                     dialog = wx.TextEntryDialog(self, "Give a new name for index 0x%04X"%index,
763                                  "Rename an index", infos["name"], wx.OK|wx.CANCEL)
764                     if dialog.ShowModal() == wx.ID_OK:
765                         self.Manager.SetCurrentEntryName(index, dialog.GetValue())
766                         self.ParentWindow.RefreshBufferState()
767                         self.RefreshIndexList()
768                     dialog.Destroy()
769         event.Skip()
770
771     def OnModifyIndexMenu(self, event):
772         if self.Editable:
773             selected = self.IndexList.GetSelection()
774             if selected != wx.NOT_FOUND:
775                 index = self.ListIndex[selected]
776                 if self.Manager.IsCurrentEntry(index) and index < 0x260:
777                     values, valuetype = self.Manager.GetCustomisedTypeValues(index)
778                     dialog = UserTypeDialog(self)
779                     dialog.SetTypeList(self.Manager.GetCustomisableTypes(), values[1])
780                     if valuetype == 0:
781                         dialog.SetValues(min = values[2], max = values[3])
782                     elif valuetype == 1:
783                         dialog.SetValues(length = values[2])
784                     if dialog.ShowModal() == wx.ID_OK:
785                         type, min, max, length = dialog.GetValues()
786                         self.Manager.SetCurrentUserType(index, type, min, max, length)
787                         self.ParentWindow.RefreshBufferState()
788                         self.RefreshIndexList()
789         event.Skip()
790         
791     def OnDeleteIndexMenu(self, event):
792         if self.Editable:
793             selected = self.IndexList.GetSelection()
794             if selected != wx.NOT_FOUND:
795                 index = self.ListIndex[selected]
796                 if self.Manager.IsCurrentEntry(index):
797                     self.Manager.ManageEntriesOfCurrent([],[index])
798                     self.ParentWindow.RefreshBufferState()
799                     self.RefreshIndexList()
800         event.Skip()
801
802     def OnAddSubindexMenu(self, event):
803         if self.Editable:
804             selected = self.IndexList.GetSelection()
805             if selected != wx.NOT_FOUND:
806                 index = self.ListIndex[selected]
807                 if self.Manager.IsCurrentEntry(index):
808                     dialog = wx.TextEntryDialog(self, "Number of subindexes to add:",
809                                  "Add subindexes", "1", wx.OK|wx.CANCEL)
810                     if dialog.ShowModal() == wx.ID_OK:
811                         try:
812                             number = int(dialog.GetValue())
813                             self.Manager.AddSubentriesToCurrent(index, number)
814                             self.ParentWindow.RefreshBufferState()
815                             self.RefreshIndexList()
816                         except:
817                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
818                             message.ShowModal()
819                             message.Destroy()
820                     dialog.Destroy()
821         event.Skip()
822
823     def OnDeleteSubindexMenu(self, event):
824         if self.Editable:
825             selected = self.IndexList.GetSelection()
826             if selected != wx.NOT_FOUND:
827                 index = self.ListIndex[selected]
828                 if self.Manager.IsCurrentEntry(index):
829                     dialog = wx.TextEntryDialog(self, "Number of subindexes to delete:",
830                                  "Delete subindexes", "1", wx.OK|wx.CANCEL)
831                     if dialog.ShowModal() == wx.ID_OK:
832                         try:
833                             number = int(dialog.GetValue())
834                             self.Manager.RemoveSubentriesFromCurrent(index, number)
835                             self.ParentWindow.RefreshBufferState()
836                             self.RefreshIndexList()
837                         except:
838                             message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
839                             message.ShowModal()
840                             message.Destroy()
841                     dialog.Destroy()
842         event.Skip()
843
844     def OnDefaultValueSubindexMenu(self, event):
845         if self.Editable:
846             selected = self.IndexList.GetSelection()
847             if selected != wx.NOT_FOUND:
848                 index = self.ListIndex[selected]
849                 if self.Manager.IsCurrentEntry(index):
850                     row = self.SubindexGrid.GetGridCursorRow()
851                     self.Manager.SetCurrentEntryToDefault(index, row)
852                     self.ParentWindow.RefreshBufferState()
853                     self.RefreshIndexList()
854         event.Skip()