]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/commondialogs.py
Bug on Concise DCF edit dialog value generating fixed
[CanFestival-3.git] / objdictgen / commondialogs.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 import os
28
29 from node import BE_to_LE, LE_to_BE
30
31 ScriptDirectory = os.path.split(__file__)[0]
32
33 #-------------------------------------------------------------------------------
34 #                          Editing Communication Dialog
35 #-------------------------------------------------------------------------------
36
37
38 [ID_COMMUNICATIONDIALOG, ID_COMMUNICATIONDIALOGPOSSIBLEINDEXES, 
39  ID_COMMUNICATIONDIALOGCURRENTINDEXES, ID_COMMUNICATIONDIALOGSELECT, 
40  ID_COMMUNICATIONDIALOGUNSELECT, ID_COMMUNICATIONDIALOGSTATICTEXT1, 
41  ID_COMMUNICATIONDIALOGSTATICTEXT2
42 ] = [wx.NewId() for _init_ctrls in range(7)]
43
44 class CommunicationDialog(wx.Dialog):
45     def _init_coll_flexGridSizer1_Items(self, parent):
46         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
47         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
48
49     def _init_coll_flexGridSizer1_Growables(self, parent):
50         parent.AddGrowableCol(0)
51         parent.AddGrowableRow(0)
52
53     def _init_coll_MainSizer_Items(self, parent):
54         parent.AddSizer(self.LeftGridSizer, 0, border=0, flag=wx.GROW)
55         parent.AddSizer(self.MiddleGridSizer, 0, border=0, flag=wx.GROW)
56         parent.AddSizer(self.RightGridSizer, 0, border=0, flag=wx.GROW)
57
58     def _init_coll_MainSizer_Growables(self, parent):
59         parent.AddGrowableCol(0)
60         parent.AddGrowableCol(2)
61         parent.AddGrowableRow(0)
62
63     def _init_coll_LeftGridSizer_Items(self, parent):
64         parent.AddWindow(self.staticText1, 0, border=0, flag=wx.GROW)
65         parent.AddWindow(self.PossibleIndexes, 0, border=0, flag=wx.GROW)
66
67     def _init_coll_LeftGridSizer_Growables(self, parent):
68         parent.AddGrowableCol(0)
69         parent.AddGrowableRow(1)
70
71     def _init_coll_MiddleGridSizer_Items(self, parent):
72         parent.AddWindow(self.Select, 0, border=0, flag=wx.ALIGN_BOTTOM)
73         parent.AddWindow(self.Unselect, 0, border=0, flag=wx.ALIGN_TOP)
74
75     def _init_coll_MiddleGridSizer_Growables(self, parent):
76         parent.AddGrowableCol(0)
77         parent.AddGrowableRow(0)
78         parent.AddGrowableRow(1)
79
80     def _init_coll_RightGridSizer_Items(self, parent):
81         parent.AddWindow(self.staticText2, 0, border=0, flag=wx.GROW)
82         parent.AddWindow(self.CurrentIndexes, 0, border=0, flag=wx.GROW)
83
84     def _init_coll_RightGridSizer_Growables(self, parent):
85         parent.AddGrowableCol(0)
86         parent.AddGrowableRow(1)
87
88     def _init_sizers(self):
89         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
90         self.MainSizer = wx.FlexGridSizer(cols=3, hgap=15, rows=1, vgap=0)
91         self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
92         self.MiddleGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=40)
93         self.RightGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
94         
95         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
96         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
97         self._init_coll_MainSizer_Items(self.MainSizer)
98         self._init_coll_MainSizer_Growables(self.MainSizer)
99         self._init_coll_LeftGridSizer_Items(self.LeftGridSizer)
100         self._init_coll_LeftGridSizer_Growables(self.LeftGridSizer)
101         self._init_coll_MiddleGridSizer_Items(self.MiddleGridSizer)
102         self._init_coll_MiddleGridSizer_Growables(self.MiddleGridSizer)
103         self._init_coll_RightGridSizer_Items(self.RightGridSizer)
104         self._init_coll_RightGridSizer_Growables(self.RightGridSizer)
105         
106         self.SetSizer(self.flexGridSizer1)
107
108     def _init_ctrls(self, prnt):
109         wx.Dialog.__init__(self, id=ID_COMMUNICATIONDIALOG,
110               name='CommunicationDialog', parent=prnt, pos=wx.Point(234, 216),
111               size=wx.Size(726, 437), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
112               title='Edit Communication Profile')
113         self.SetClientSize(wx.Size(726, 437))
114
115         self.staticText1 = wx.StaticText(id=ID_COMMUNICATIONDIALOGSTATICTEXT1,
116               label='Possible Profile Indexes:', name='staticText1',
117               parent=self, pos=wx.Point(0, 0), size=wx.Size(0,
118               17), style=0)
119
120         self.PossibleIndexes = wx.ListBox(choices=[],
121               id=ID_COMMUNICATIONDIALOGPOSSIBLEINDEXES,
122               name='PossibleIndexes', parent=self, pos=wx.Point(0, 0), 
123               size=wx.Size(0, 0), style=wx.LB_EXTENDED)
124         self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnPossibleIndexesDClick,
125               id=ID_COMMUNICATIONDIALOGPOSSIBLEINDEXES)
126
127         self.Select = wx.Button(id=ID_COMMUNICATIONDIALOGSELECT, label='>>',
128               name='Select', parent=self, pos=wx.Point(0, 0),
129               size=wx.Size(32, 32), style=0)
130         self.Select.Bind(wx.EVT_BUTTON, self.OnSelectButton,
131               id=ID_COMMUNICATIONDIALOGSELECT)
132
133         self.Unselect = wx.Button(id=ID_COMMUNICATIONDIALOGUNSELECT,
134               label='<<', name='Unselect', parent=self,
135               pos=wx.Point(0, 0), size=wx.Size(32, 32), style=0)
136         self.Unselect.Bind(wx.EVT_BUTTON, self.OnUnselectButton,
137               id=ID_COMMUNICATIONDIALOGUNSELECT)
138
139         self.staticText2 = wx.StaticText(id=ID_COMMUNICATIONDIALOGSTATICTEXT2,
140               label='Current Profile Indexes:', name='staticText2',
141               parent=self, pos=wx.Point(0, 0), size=wx.Size(0,
142               17), style=0)
143
144         self.CurrentIndexes = wx.ListBox(choices=[],
145               id=ID_COMMUNICATIONDIALOGCURRENTINDEXES, name='CurrentIndexes',
146               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 0), 
147               style=wx.LB_EXTENDED)
148         self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnCurrentIndexesDClick,
149               id=ID_COMMUNICATIONDIALOGCURRENTINDEXES)
150
151         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
152         
153         self._init_sizers()
154
155     def __init__(self, parent):
156         self._init_ctrls(parent)
157         self.AllList = []
158         self.CurrentList = []
159         self.IndexDictionary = {}
160
161     def SetIndexDictionary(self, dictionary):
162         self.IndexDictionary = dictionary
163         
164     def SetCurrentList(self, list):
165         self.CurrentList = []
166         self.CurrentList.extend(list)
167         self.CurrentList.sort()
168         
169     def GetCurrentList(self):
170         return self.CurrentList
171         
172     def RefreshLists(self):
173         self.PossibleIndexes.Clear()
174         self.CurrentIndexes.Clear()
175         self.AllList = []
176         for index in self.IndexDictionary.iterkeys():
177             if index not in self.CurrentList:
178                 self.AllList.append(index)
179         self.AllList.sort()
180         for index in self.AllList:
181             self.PossibleIndexes.Append("0x%04X   %s"%(index, self.IndexDictionary[index][0]))
182         for index in self.CurrentList:
183             if index in self.IndexDictionary:
184                 self.CurrentIndexes.Append("0x%04X   %s"%(index, self.IndexDictionary[index][0]))
185
186     def OnPossibleIndexesDClick(self, event):
187         self.SelectPossible()
188         event.Skip()
189
190     def OnCurrentIndexesDClick(self, event):
191         self.UnselectCurrent()
192         event.Skip()
193
194     def OnSelectButton(self, event):
195         self.SelectPossible()
196         event.Skip()
197
198     def OnUnselectButton(self, event):
199         self.UnselectCurrent()
200         event.Skip()
201
202     def SelectPossible(self):
203         selected = self.PossibleIndexes.GetSelections()
204         for i in selected:
205             self.CurrentList.append(self.AllList[i])
206         self.CurrentList.sort()
207         self.RefreshLists()
208
209     def UnselectCurrent(self):
210         selected = self.CurrentIndexes.GetSelections()
211         for i in selected:
212             if not self.IndexDictionary[self.CurrentList[i]][1]:
213                 self.CurrentList.pop(i)
214         self.CurrentList.sort()
215         self.RefreshLists()
216
217
218
219 #-------------------------------------------------------------------------------
220 #                          Create Map Variable Dialog
221 #-------------------------------------------------------------------------------
222
223
224 [ID_MAPVARIABLEDIALOG, ID_MAPVARIABLEDIALOGINDEX, 
225  ID_MAPVARIABLEDIALOGINDEXNAME, ID_MAPVARIABLEDIALOGSPACER, 
226  ID_MAPVARIABLEDIALOGSPACER2, ID_MAPVARIABLEDIALOGNUMBER, 
227  ID_MAPVARIABLEDIALOGRADIOBUTTON1, ID_MAPVARIABLEDIALOGRADIOBUTTON2, 
228  ID_MAPVARIABLEDIALOGRADIOBUTTON3, ID_MAPVARIABLEDIALOGSTATICTEXT1, 
229  ID_MAPVARIABLEDIALOGSTATICTEXT2, ID_MAPVARIABLEDIALOGSTATICTEXT3, 
230  ID_MAPVARIABLEDIALOGSTATICTEXT4, 
231 ] = [wx.NewId() for _init_ctrls in range(13)]
232
233 class MapVariableDialog(wx.Dialog):
234     def _init_coll_flexGridSizer1_Items(self, parent):
235         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
236         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
237
238     def _init_coll_flexGridSizer1_Growables(self, parent):
239         parent.AddGrowableCol(0)
240         parent.AddGrowableRow(0)
241
242     def _init_coll_MainSizer_Items(self, parent):
243         parent.AddWindow(self.staticText1, 0, border=0, flag=wx.GROW)
244         parent.AddWindow(self.staticText2, 0, border=0, flag=wx.GROW)
245         parent.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
246         parent.AddWindow(self.Index, 0, border=0, flag=wx.GROW)
247         parent.AddWindow(self.radioButton1, 0, border=0, flag=wx.GROW)
248         parent.AddWindow(self.Spacer2, 0, border=0, flag=wx.GROW)
249         parent.AddWindow(self.staticText3, 0, border=0, flag=wx.GROW)
250         parent.AddWindow(self.radioButton2, 0, border=0, flag=wx.GROW)
251         parent.AddWindow(self.staticText4, 0, border=0, flag=wx.GROW)
252         parent.AddWindow(self.IndexName, 0, border=0, flag=wx.GROW)
253         parent.AddWindow(self.radioButton3, 0, border=0, flag=wx.GROW)
254         parent.AddWindow(self.Number, 0, border=0, flag=wx.GROW)
255         
256     def _init_coll_MainSizer_Growables(self, parent):
257         parent.AddGrowableCol(0)
258         parent.AddGrowableCol(2)
259
260     def _init_sizers(self):
261         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
262         self.MainSizer = wx.FlexGridSizer(cols=3, hgap=30, rows=4, vgap=5)
263         
264         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
265         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
266         self._init_coll_MainSizer_Items(self.MainSizer)
267         self._init_coll_MainSizer_Growables(self.MainSizer)
268         
269         self.SetSizer(self.flexGridSizer1)
270
271     def _init_ctrls(self, prnt):
272         wx.Dialog.__init__(self, id=ID_MAPVARIABLEDIALOG,
273               name='CommunicationDialog', parent=prnt, pos=wx.Point(376, 223),
274               size=wx.Size(444, 186), style=wx.DEFAULT_DIALOG_STYLE,
275               title='Add Map Variable')
276         self.SetClientSize(wx.Size(444, 186))
277
278         self.staticText1 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT1,
279               label='Index:', name='staticText1', parent=self,
280               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
281
282         self.staticText2 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT2,
283               label='Type:', name='staticText2', parent=self,
284               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
285
286         self.staticText3 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT3,
287               label='Name:', name='staticText3', parent=self,
288               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
289
290         self.staticText4 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT4,
291               label='Number:', name='staticText4', parent=self,
292               pos=wx.Point(0, 0), size=wx.Size(0, 16), style=0)
293
294         self.radioButton1 = wx.RadioButton(id=ID_MAPVARIABLEDIALOGRADIOBUTTON1,
295               label='VAR', name='radioButton1', parent=self,
296               pos=wx.Point(0, 0), size=wx.Size(80, 24), style=wx.RB_GROUP)
297         self.radioButton1.SetValue(True)
298         self.radioButton1.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton1Click,
299               id=ID_MAPVARIABLEDIALOGRADIOBUTTON1)
300
301         self.radioButton2 = wx.RadioButton(id=ID_MAPVARIABLEDIALOGRADIOBUTTON2,
302               label='ARRAY', name='radioButton2', parent=self,
303               pos=wx.Point(0, 0), size=wx.Size(80, 24), style=wx.RB_SINGLE)
304         self.radioButton2.SetValue(False)
305         self.radioButton2.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton2Click,
306               id=ID_MAPVARIABLEDIALOGRADIOBUTTON2)
307
308         self.radioButton3 = wx.RadioButton(id=ID_MAPVARIABLEDIALOGRADIOBUTTON3,
309               label='REC', name='radioButton3', parent=self,
310               pos=wx.Point(0, 0), size=wx.Size(80, 24), style=wx.RB_SINGLE)
311         self.radioButton3.SetValue(False)
312         self.radioButton3.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton3Click,
313               id=ID_MAPVARIABLEDIALOGRADIOBUTTON3)
314
315         self.Index = wx.TextCtrl(id=ID_MAPVARIABLEDIALOGINDEX, name='Index',
316               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 25), 
317               style=0, value='0x2000')
318         
319         self.IndexName = wx.TextCtrl(id=ID_MAPVARIABLEDIALOGINDEXNAME,
320               name='IndexName', parent=self, pos=wx.Point(0, 0),
321               size=wx.Size(0, 24), style=0, value='Undefined')
322         
323         self.Number = wx.TextCtrl(id=ID_MAPVARIABLEDIALOGNUMBER,
324               name='Number', parent=self, pos=wx.Point(0, 0),
325               size=wx.Size(0, 24), style=wx.TE_RIGHT, value='0')
326         
327         self.Spacer = wx.Panel(id=ID_MAPVARIABLEDIALOGSPACER,
328               name='Spacer', parent=self, pos=wx.Point(0, 0),
329               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
330         
331         self.Spacer2 = wx.Panel(id=ID_MAPVARIABLEDIALOGSPACER2,
332               name='Spacer2', parent=self, pos=wx.Point(0, 0),
333               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
334         
335         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
336         self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
337         
338         self._init_sizers()
339
340     def __init__(self, parent):
341         self._init_ctrls(parent)
342         self.staticText4.Enable(False)
343         self.Number.Enable(False)
344         
345     def SetIndex(self, index):
346         self.Index.SetValue("0x%04X"%index)
347
348     def OnOK(self, event):
349         error = []
350         try:
351             int(self.Index.GetValue(), 16)
352         except:
353             error.append("Index")
354         if self.radioButton2.GetValue() or self.radioButton3.GetValue():
355             try:
356                 int(self.Number.GetValue())
357             except:
358                 error.append("Number")
359         if len(error) > 0:
360             text = ""
361             if len(error) > 1:
362                 suffix = "s"
363             else:
364                 suffix = ""
365             for i, item in enumerate(error):
366                 if i == 0:
367                     text += item
368                 elif i == len(error) - 1:
369                     text += " and %s"%item
370                 else:
371                     text += ", %s"%item
372             message = wx.MessageDialog(self, "Form isn't valid. %s must be integer%s!"%(text,suffix), "Error", wx.OK|wx.ICON_ERROR)
373             message.ShowModal()
374             message.Destroy()
375         else:
376             self.EndModal(wx.ID_OK)
377
378     def GetValues(self):
379         name = self.IndexName.GetValue()
380         index = int(self.Index.GetValue(), 16)
381         if self.radioButton1.GetValue():
382             struct = 1
383             number = None
384         elif self.radioButton2.GetValue():
385             struct = 7
386             number = int(self.Number.GetValue())
387         elif self.radioButton3.GetValue():
388             struct = 3
389             number = int(self.Number.GetValue())
390         return index, name, struct, number
391
392     def OnRadioButton1Click(self, event):
393         self.EnableNumberTyping(False)
394         event.Skip()
395
396     def OnRadioButton2Click(self, event):
397         self.EnableNumberTyping(True)
398         event.Skip()
399
400     def OnRadioButton3Click(self, event):
401         self.EnableNumberTyping(True)
402         event.Skip()
403
404     def EnableNumberTyping(self, enable):
405         self.staticText4.Enable(enable)
406         self.Number.Enable(enable)
407
408
409 #-------------------------------------------------------------------------------
410 #                          Create User Type Dialog
411 #-------------------------------------------------------------------------------
412
413
414 [ID_USERTYPEDIALOG, ID_USERTYPEDIALOGSPACER, 
415  ID_USERTYPEDIALOGTYPE, ID_USERTYPEDIALOGMAX, 
416  ID_USERTYPEDIALOGMIN, ID_USERTYPEDIALOGLENGTH, 
417  ID_USERTYPEDIALOGSTATICBOX1, ID_USERTYPEDIALOGSTATICTEXT1, 
418  ID_USERTYPEDIALOGSTATICTEXT2, ID_USERTYPEDIALOGSTATICTEXT3, 
419  ID_USERTYPEDIALOGSTATICTEXT4,  
420 ] = [wx.NewId() for _init_ctrls in range(11)]
421
422 class UserTypeDialog(wx.Dialog):
423     def _init_coll_flexGridSizer1_Items(self, parent):
424         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
425         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
426
427     def _init_coll_flexGridSizer1_Growables(self, parent):
428         parent.AddGrowableCol(0)
429         parent.AddGrowableRow(0)
430
431     def _init_coll_MainSizer_Items(self, parent):
432         parent.AddSizer(self.LeftGridSizer, 2, border=5, flag=wx.GROW|wx.RIGHT)
433         parent.AddSizer(self.RightBoxSizer, 3, border=5, flag=wx.GROW|wx.LEFT)
434
435     def _init_coll_LeftGridSizer_Items(self, parent):
436         parent.AddWindow(self.staticText1, 0, border=0, flag=wx.GROW)
437         parent.AddWindow(self.Type, 0, border=0, flag=wx.GROW)
438         parent.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
439
440     def _init_coll_LeftGridSizer_Growables(self, parent):
441         parent.AddGrowableCol(0)
442         parent.AddGrowableRow(2)
443
444     def _init_coll_RightBoxSizer_Items(self, parent):
445         parent.AddSizer(self.RightBoxGridSizer, 0, border=10, flag=wx.GROW|wx.ALL)
446
447     def _init_coll_RightBoxGridSizer_Items(self, parent):
448         parent.AddWindow(self.staticText2, 0, border=0, flag=wx.GROW)
449         parent.AddWindow(self.Min, 0, border=0, flag=wx.GROW)
450         parent.AddWindow(self.staticText3, 0, border=0, flag=wx.GROW)
451         parent.AddWindow(self.Max, 0, border=0, flag=wx.GROW)
452         parent.AddWindow(self.staticText4, 0, border=0, flag=wx.GROW)
453         parent.AddWindow(self.Length, 0, border=0, flag=wx.GROW)
454         
455     def _init_coll_RightBoxGridSizer_Growables(self, parent):
456         parent.AddGrowableCol(1)
457         
458     def _init_sizers(self):
459         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
460         self.MainSizer = wx.BoxSizer(wx.HORIZONTAL)
461         self.LeftGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=5)
462         self.RightBoxSizer = wx.StaticBoxSizer(self.staticBox1, wx.VERTICAL)
463         self.RightBoxGridSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=3, vgap=10)
464         
465         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
466         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
467         self._init_coll_MainSizer_Items(self.MainSizer)
468         self._init_coll_LeftGridSizer_Items(self.LeftGridSizer)
469         self._init_coll_LeftGridSizer_Growables(self.LeftGridSizer)
470         self._init_coll_RightBoxSizer_Items(self.RightBoxSizer)
471         self._init_coll_RightBoxGridSizer_Items(self.RightBoxGridSizer)
472         self._init_coll_RightBoxGridSizer_Growables(self.RightBoxGridSizer)
473         
474         self.SetSizer(self.flexGridSizer1)
475
476     def _init_ctrls(self, prnt):
477         wx.Dialog.__init__(self, id=ID_USERTYPEDIALOG, name='UserTypeDialog',
478               parent=prnt, pos=wx.Point(376, 223), size=wx.Size(444, 210),
479               style=wx.DEFAULT_DIALOG_STYLE, title='Add User Type')
480         self.SetClientSize(wx.Size(444, 210))
481
482         self.staticText1 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT1,
483               label='Type:', name='staticText1', parent=self,
484               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
485
486         self.Type = wx.Choice(choices=[], id=ID_USERTYPEDIALOGTYPE,
487               name='Type', parent=self, pos=wx.Point(0, 0),
488               size=wx.Size(0, 24), style=0)
489         self.Type.Bind(wx.EVT_CHOICE, self.OnTypeChoice,
490               id=ID_USERTYPEDIALOGTYPE)
491
492         self.Spacer = wx.Panel(id=ID_MAPVARIABLEDIALOGSPACER,
493               name='Spacer', parent=self, pos=wx.Point(0, 0),
494               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
495
496         self.staticBox1 = wx.StaticBox(id=ID_USERTYPEDIALOGSTATICBOX1,
497               label='Values', name='staticBox1', parent=self,
498               pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0)
499
500         self.staticText2 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT2,
501               label='Minimum:', name='staticText2', parent=self,
502               pos=wx.Point(0, 0), size=wx.Size(80, 17), style=0)
503
504         self.Min = wx.TextCtrl(id=ID_USERTYPEDIALOGMIN, name='Min',
505               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), 
506               style=wx.TE_RIGHT, value='0')
507
508         self.staticText3 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT3,
509               label='Maximum:', name='staticText3', parent=self,
510               pos=wx.Point(0, 0), size=wx.Size(80, 17), style=0)
511
512         self.Max = wx.TextCtrl(id=ID_USERTYPEDIALOGMAX, name='Max',
513               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), 
514               style=wx.TE_RIGHT, value='0')
515
516         self.staticText4 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT4,
517               label='Length:', name='staticText4', parent=self,
518               pos=wx.Point(0, 0), size=wx.Size(80, 17), style=0)
519
520         self.Length = wx.TextCtrl(id=ID_USERTYPEDIALOGLENGTH, name='Length',
521               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), 
522               style=wx.TE_RIGHT, value='0')
523
524         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
525         self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
526         
527         self._init_sizers()
528
529     def __init__(self, parent):
530         self._init_ctrls(parent)
531         
532         self.TypeDictionary = {}
533
534     def OnOK(self, event):
535         error = []
536         good = True
537         firstmessage = ""
538         secondmessage = ""
539         name = self.Type.GetStringSelection()
540         if name != "":
541             valuetype = self.TypeDictionary[name][1]
542             if valuetype == 0:
543                 try:
544                     int(self.Min.GetValue(), 16)
545                 except:
546                     error.append("Minimum")
547                     good = False
548                 try:
549                     int(self.Max.GetValue(), 16)
550                 except:
551                     error.append("Maximum")
552                     good = False
553             elif valuetype == 1:
554                 try:
555                     int(self.Length.GetValue(), 16)
556                 except:
557                     error.append("Length")
558                     good = False
559             if len(error) > 0:
560                 secondmessage = ". "
561                 for i, item in enumerate(error):
562                     if i == 0:
563                         secondmessage += item
564                     elif i == len(error) - 1:
565                         secondmessage += " and %s"%item
566                     else:
567                         secondmessage += ", %s"%item
568                 secondmessage += " must be integer"
569                 if len(error) > 1:
570                     secondmessage += "s"
571         else:
572             firstmessage = ". A type must be selected"
573             good = False
574         if not good:
575             message = wx.MessageDialog(self, "Form isn't valid%s%s%s!"%(firstmessage,secondmessage), "Error", wx.OK|wx.ICON_ERROR)
576             message.ShowModal()
577             message.Destroy()
578         else:
579             self.EndModal(wx.ID_OK)
580
581     def SetValues(self, min = None, max = None, length = None):
582         if min != None:
583             self.Min.SetValue(str(min))
584         if max != None:
585             self.Max.SetValue(str(max))
586         if length != None:
587             self.Length.SetValue(str(length))
588
589     def SetTypeList(self, typedic, type = None):
590         self.Type.Clear()
591         list = []
592         for index, (name, valuetype) in typedic.iteritems():
593             self.TypeDictionary[name] = (index, valuetype)
594             list.append((index, name))
595         list.sort()
596         for index, name in list:
597             self.Type.Append(name)
598         if type != None:
599             self.Type.SetStringSelection(typedic[type][0])
600         self.RefreshValues()
601
602     def OnTypeChoice(self, event):
603         self.RefreshValues()
604         event.Skip()
605     
606     def RefreshValues(self):
607         name = self.Type.GetStringSelection()
608         if name != "":
609             valuetype = self.TypeDictionary[name][1]
610             if valuetype == 0:
611                 self.staticText2.Enable(True)
612                 self.staticText3.Enable(True)
613                 self.staticText4.Enable(False)
614                 self.Min.Enable(True)
615                 self.Max.Enable(True)
616                 self.Length.Enable(False)
617             elif valuetype == 1:
618                 self.staticText2.Enable(False)
619                 self.staticText3.Enable(False)
620                 self.staticText4.Enable(True)
621                 self.Min.Enable(False)
622                 self.Max.Enable(False)
623                 self.Length.Enable(True)
624         else:
625             self.staticText2.Enable(False)
626             self.staticText3.Enable(False)
627             self.staticText4.Enable(False)
628             self.Min.Enable(False)
629             self.Max.Enable(False)
630             self.Length.Enable(False)
631
632     def GetValues(self):
633         name = self.Type.GetStringSelection()
634         type = self.TypeDictionary[name][0]
635         min = int(self.Min.GetValue())
636         max = int(self.Max.GetValue())
637         length = int(self.Length.GetValue())
638         return type, min, max, length
639
640
641
642 #-------------------------------------------------------------------------------
643 #                          Editing Node Infos Dialog
644 #-------------------------------------------------------------------------------
645
646
647 [ID_NODEINFOSDIALOG, ID_NODEINFOSDIALOGNAME, 
648  ID_NODEINFOSDIALOGNODEID, ID_NODEINFOSDIALOGTYPE, 
649  ID_NODEINFOSDIALOGDEFAULTSTRINGSIZE, ID_NODEINFOSDIALOGDESCRIPTION, 
650  ID_NODEINFOSDIALOGSTATICTEXT1, ID_NODEINFOSDIALOGSTATICTEXT2, 
651  ID_NODEINFOSDIALOGSTATICTEXT3, ID_NODEINFOSDIALOGSTATICTEXT4, 
652  ID_NODEINFOSDIALOGSTATICTEXT5, 
653 ] = [wx.NewId() for _init_ctrls in range(11)]
654
655 class NodeInfosDialog(wx.Dialog):
656     def _init_coll_flexGridSizer1_Items(self, parent):
657         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
658         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
659
660     def _init_coll_flexGridSizer1_Growables(self, parent):
661         parent.AddGrowableCol(0)
662         parent.AddGrowableRow(0)
663
664     def _init_coll_MainSizer_Items(self, parent):
665         parent.AddWindow(self.staticText1, 0, border=0, flag=wx.GROW)
666         parent.AddWindow(self.NodeName, 0, border=0, flag=wx.GROW)
667         parent.AddWindow(self.staticText2, 0, border=0, flag=wx.GROW)
668         parent.AddWindow(self.NodeID, 0, border=0, flag=wx.GROW)
669         parent.AddWindow(self.staticText3, 0, border=0, flag=wx.GROW)
670         parent.AddWindow(self.Type, 0, border=0, flag=wx.GROW)
671         parent.AddWindow(self.staticText4, 0, border=0, flag=wx.GROW)
672         parent.AddWindow(self.DefaultStringSize, 0, border=0, flag=wx.GROW)
673         parent.AddWindow(self.staticText5, 0, border=0, flag=wx.GROW)
674         parent.AddWindow(self.Description, 0, border=0, flag=wx.GROW)
675
676     def _init_coll_MainSizer_Growables(self, parent):
677         parent.AddGrowableCol(0)
678
679     def _init_sizers(self):
680         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
681         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=8, vgap=5)
682         
683         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
684         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
685         self._init_coll_MainSizer_Items(self.MainSizer)
686         self._init_coll_MainSizer_Growables(self.MainSizer)
687         
688         self.SetSizer(self.flexGridSizer1)
689         
690     def _init_ctrls(self, prnt):
691         wx.Dialog.__init__(self, id=ID_NODEINFOSDIALOG,
692               name='NodeInfosDialog', parent=prnt, pos=wx.Point(376, 223),
693               size=wx.Size(300, 280), style=wx.DEFAULT_DIALOG_STYLE,
694               title='Node Infos')
695         self.SetClientSize(wx.Size(300, 280))
696
697         self.staticText1 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT1,
698               label='Name:', name='staticText1', parent=self,
699               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
700
701         self.NodeName = wx.TextCtrl(id=ID_NODEINFOSDIALOGNAME, name='NodeName',
702               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), 
703               style=0, value='')
704
705         self.staticText2 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT2,
706               label='Node ID:', name='staticText2', parent=self,
707               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
708
709         self.NodeID = wx.TextCtrl(id=ID_NODEINFOSDIALOGNODEID, name='NodeID',
710               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 25), 
711               style=wx.TE_RIGHT, value='')
712
713         self.staticText3 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT3,
714               label='Type:', name='staticText3', parent=self,
715               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
716
717         self.Type = wx.Choice(choices=[], id=ID_NODEINFOSDIALOGTYPE,
718               name='Type', parent=self, pos=wx.Point(0, 0),
719               size=wx.Size(0, 25), style=0)
720
721         self.staticText4 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT4,
722               label='Default String Size:', name='staticText4', parent=self,
723               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
724
725         self.DefaultStringSize = wx.SpinCtrl(id=ID_NODEINFOSDIALOGDEFAULTSTRINGSIZE, 
726               name='DefaultStringSize', parent=self, pos=wx.Point(0, 0), 
727               size=wx.Size(0, 25), style=wx.TE_RIGHT)
728         
729         self.staticText5 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT5,
730               label='Description:', name='staticText5', parent=self,
731               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
732
733         self.Description = wx.TextCtrl(id=ID_NODEINFOSDIALOGDESCRIPTION, 
734               name='Description', parent=self, pos=wx.Point(0, 0), 
735               size=wx.Size(0, 24), style=0, value='')
736
737         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
738         self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
739         
740         self._init_sizers()
741
742     def __init__(self, parent):
743         self._init_ctrls(parent)
744         
745         self.staticText2.Hide()
746         self.NodeID.Hide()
747         
748         self.Type.Append("master")
749         self.Type.Append("slave")
750
751     def OnOK(self, event):
752         name = self.NodeName.GetValue()
753         message = ""
754         if name != "":
755             good = not name[0].isdigit()
756             for item in name.split("_"):
757                 good &= item.isalnum()
758             if not good:
759                 message = "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
760         if message != "":
761             try:
762                 nodeid = int(self.NodeID.GetValue(), 16)
763             except:
764                 message = "Node ID must be integer!"
765         if message != "":
766             message = wx.MessageDialog(self, message, "ERROR", wx.OK|wx.ICON_ERROR)
767             message.ShowModal()
768             message.Destroy()
769             self.NodeName.SetFocus()
770         else:
771             self.EndModal(wx.ID_OK)
772     
773     def SetValues(self, name, id, type, description, defaultstringsize):
774         self.NodeName.SetValue(name)
775         self.NodeID.SetValue("0x%02X"%id)
776         self.Type.SetStringSelection(type)
777         self.Description.SetValue(description)
778         self.DefaultStringSize.SetValue(defaultstringsize)
779
780     def GetValues(self):
781         name = self.NodeName.GetValue()
782         nodeid = int(self.NodeID.GetValue(), 16)
783         type = self.Type.GetStringSelection()
784         description = self.Description.GetValue()
785         defaultstringsize = self.DefaultStringSize.GetValue()
786         return name, nodeid, type, description, defaultstringsize
787
788
789
790 #-------------------------------------------------------------------------------
791 #                          Create New Node Dialog
792 #-------------------------------------------------------------------------------
793
794
795 [ID_CREATENODEDIALOG, ID_CREATENODEDIALOGEMERGENCY, 
796  ID_CREATENODEDIALOGGENSYNC, ID_CREATENODEDIALOGSPACER, 
797  ID_CREATENODEDIALOGNAME, ID_CREATENODEDIALOGNMT_HEARTBEAT, 
798  ID_CREATENODEDIALOGNMT_NODEGUARDING, ID_CREATENODEDIALOGNMT_NONE, 
799  ID_CREATENODEDIALOGNODEID, ID_CREATENODEDIALOGPROFILE, 
800  ID_CREATENODEDIALOGSAVECONFIG, ID_CREATENODEDIALOGSTATICTEXT1, 
801  ID_CREATENODEDIALOGSTATICTEXT2, ID_CREATENODEDIALOGSTATICTEXT3, 
802  ID_CREATENODEDIALOGSTATICTEXT4, ID_CREATENODEDIALOGSTATICTEXT5, 
803  ID_CREATENODEDIALOGSTATICTEXT6, ID_CREATENODEDIALOGSTATICTEXT7,
804  ID_CREATENODEDIALOGSTOREEDS, ID_CREATENODEDIALOGDESCRIPTION,
805  ID_CREATENODEDIALOGTYPE, 
806 ] = [wx.NewId() for _init_ctrls in range(21)]
807
808 class CreateNodeDialog(wx.Dialog):
809     def _init_coll_flexGridSizer1_Items(self, parent):
810         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
811         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
812
813     def _init_coll_flexGridSizer1_Growables(self, parent):
814         parent.AddGrowableCol(0)
815         parent.AddGrowableRow(0)
816
817     def _init_coll_MainSizer_Items(self, parent):
818         parent.AddSizer(self.TopBoxSizer, 0, border=0, flag=wx.GROW)
819         parent.AddWindow(self.staticText7, 0, border=0, flag=wx.GROW)
820         parent.AddWindow(self.Description, 0, border=0, flag=wx.GROW)
821
822     def _init_coll_MainSizer_Growables(self, parent):
823         parent.AddGrowableCol(0)
824         parent.AddGrowableCol(0)
825     
826     def _init_coll_TopBoxSizer_Items(self, parent):
827         parent.AddSizer(self.LeftBoxSizer, 1, border=10, flag=wx.GROW|wx.RIGHT)
828         parent.AddSizer(self.RightGridSizer, 1, border=10, flag=wx.GROW|wx.LEFT)
829     
830     def _init_coll_LeftBoxSizer_Items(self, parent):
831         parent.AddWindow(self.staticText1, 0, border=5, flag=wx.GROW|wx.BOTTOM)
832         parent.AddWindow(self.Type, 0, border=10, flag=wx.GROW|wx.BOTTOM)
833         parent.AddWindow(self.staticText2, 0, border=5, flag=wx.GROW|wx.BOTTOM)
834         parent.AddWindow(self.NodeName, 0, border=10, flag=wx.GROW|wx.BOTTOM)
835         parent.AddWindow(self.staticText3, 0, border=5, flag=wx.GROW|wx.BOTTOM)
836         parent.AddWindow(self.NodeID, 0, border=10, flag=wx.GROW|wx.BOTTOM)
837         parent.AddWindow(self.staticText4, 0, border=5, flag=wx.GROW|wx.BOTTOM)
838         parent.AddWindow(self.Profile, 0, border=20, flag=wx.GROW|wx.BOTTOM)
839
840     def _init_coll_RightGridSizer_Items(self, parent):
841         parent.AddSizer(self.RightTopGridSizer, 0, border=0, flag=wx.GROW)
842         parent.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
843         parent.AddSizer(self.RightBottomGridSizer, 0, border=0, flag=wx.GROW)
844
845     def _init_coll_RightGridSizer_Growables(self, parent):
846         parent.AddGrowableCol(0)
847         parent.AddGrowableRow(1)
848
849     def _init_coll_RightTopGridSizer_Items(self, parent):
850         parent.AddWindow(self.staticText5, 0, border=0, flag=wx.GROW)
851         parent.AddWindow(self.NMT_None, 0, border=0, flag=wx.GROW)
852         parent.AddWindow(self.NMT_NodeGuarding, 0, border=0, flag=wx.GROW)
853         parent.AddWindow(self.NMT_Heartbeat, 0, border=0, flag=wx.GROW)
854         
855     def _init_coll_RightTopGridSizer_Growables(self, parent):
856         parent.AddGrowableCol(0)
857         
858     def _init_coll_RightBottomGridSizer_Items(self, parent):
859         parent.AddWindow(self.staticText6, 0, border=0, flag=wx.GROW)
860         parent.AddWindow(self.DS302, 0, border=0, flag=wx.GROW)
861         parent.AddWindow(self.GenSYNC, 0, border=0, flag=wx.GROW)
862         parent.AddWindow(self.Emergency, 0, border=0, flag=wx.GROW)
863         parent.AddWindow(self.SaveConfig, 0, border=0, flag=wx.GROW)
864         parent.AddWindow(self.StoreEDS, 0, border=0, flag=wx.GROW)
865         
866     def _init_coll_RightBottomGridSizer_Growables(self, parent):
867         parent.AddGrowableCol(0)
868
869     def _init_sizers(self):
870         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
871         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=5, rows=3, vgap=0)
872         self.TopBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
873         self.LeftBoxSizer = wx.BoxSizer(wx.VERTICAL)
874         self.RightGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=5)
875         self.RightTopGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=4, vgap=0)
876         self.RightBottomGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0)
877         
878         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
879         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
880         self._init_coll_MainSizer_Items(self.MainSizer)
881         self._init_coll_MainSizer_Growables(self.MainSizer)
882         self._init_coll_TopBoxSizer_Items(self.TopBoxSizer)
883         self._init_coll_LeftBoxSizer_Items(self.LeftBoxSizer)
884         self._init_coll_RightGridSizer_Items(self.RightGridSizer)
885         self._init_coll_RightGridSizer_Growables(self.RightGridSizer)
886         self._init_coll_RightTopGridSizer_Items(self.RightTopGridSizer)
887         self._init_coll_RightTopGridSizer_Growables(self.RightTopGridSizer)
888         self._init_coll_RightBottomGridSizer_Items(self.RightBottomGridSizer)
889         self._init_coll_RightBottomGridSizer_Growables(self.RightBottomGridSizer)
890         
891         self.SetSizer(self.flexGridSizer1)
892
893     def _init_ctrls(self, prnt, buttons):
894         wx.Dialog.__init__(self, id=ID_CREATENODEDIALOG,
895               name='CreateNodeDialog', parent=prnt, pos=wx.Point(376, 223),
896               size=wx.Size(450, 350), style=wx.DEFAULT_DIALOG_STYLE,
897               title='Create a new Node')
898         self.SetClientSize(wx.Size(450, 350))
899
900         self.staticText1 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT1,
901               label='Type:', name='staticText1', parent=self,
902               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
903
904         self.staticText2 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT2,
905               label='Name:', name='staticText2', parent=self,
906               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
907
908         self.staticText3 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT3,
909               label='Node ID:', name='staticText3', parent=self,
910               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
911
912         self.staticText4 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT4,
913               label='Profile:', name='staticText4', parent=self,
914               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
915
916         self.Type = wx.Choice(choices=[], id=ID_CREATENODEDIALOGTYPE,
917               name='Type', parent=self, pos=wx.Point(0, 0),
918               size=wx.Size(0, 25), style=0)
919
920         self.NodeName = wx.TextCtrl(id=ID_CREATENODEDIALOGNAME, name='NodeName',
921               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), 
922               style=0, value='')
923
924         self.NodeID = wx.TextCtrl(id=ID_CREATENODEDIALOGNODEID, name='NodeID',
925               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), 
926               style=wx.TE_RIGHT, value='')
927
928         self.Profile = wx.Choice(choices=[], id=ID_CREATENODEDIALOGPROFILE,
929               name='Profile', parent=self, pos=wx.Point(0, 0),
930               size=wx.Size(0, 24), style=0)
931         self.Profile.Bind(wx.EVT_CHOICE, self.OnProfileChoice,
932               id=ID_CREATENODEDIALOGPROFILE)
933
934         self.staticText5 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT5,
935               label='Network Management:', name='staticText5',
936               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
937
938         self.NMT_None = wx.RadioButton(id=ID_CREATENODEDIALOGNMT_NONE,
939               label='None', name='NMT_None', parent=self,
940               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
941         self.NMT_None.SetValue(True)
942
943         self.NMT_NodeGuarding = wx.RadioButton(id=ID_CREATENODEDIALOGNMT_NODEGUARDING,
944               label='Node Guarding', name='NMT_NodeGuarding', parent=self, 
945               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
946         self.NMT_NodeGuarding.SetValue(False)
947
948         self.NMT_Heartbeat = wx.RadioButton(id=ID_CREATENODEDIALOGNMT_HEARTBEAT,
949               label='Heartbeat', name='NMT_Heartbeat', parent=self,
950               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
951         self.NMT_Heartbeat.SetValue(False)
952
953         self.staticText6 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT6,
954               label='Options:', name='staticText6', parent=self,
955               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
956
957         self.DS302 = wx.CheckBox(id=ID_CREATENODEDIALOGGENSYNC,
958               label='DS-302 Profile', name='DS302', parent=self,
959               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
960         self.DS302.SetValue(False)
961         #self.DS302.Enable(False)
962
963         self.GenSYNC = wx.CheckBox(id=ID_CREATENODEDIALOGGENSYNC,
964               label='Generate SYNC', name='GenSYNC', parent=self,
965               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
966         self.GenSYNC.SetValue(False)
967
968         self.Emergency = wx.CheckBox(id=ID_CREATENODEDIALOGEMERGENCY,
969               label='Emergency support', name='Emergency',
970               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
971         self.Emergency.SetValue(False)
972
973         self.SaveConfig = wx.CheckBox(id=ID_CREATENODEDIALOGSAVECONFIG,
974               label='Save Configuration', name='SaveConfig', parent=self, 
975               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
976         self.SaveConfig.SetValue(False)
977         self.SaveConfig.Enable(False)
978
979         self.StoreEDS = wx.CheckBox(id=ID_CREATENODEDIALOGSTOREEDS,
980               label='Store EDS', name='StoreEDS', parent=self,
981               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
982         self.StoreEDS.SetValue(False)
983         self.StoreEDS.Hide()
984
985         self.staticText7 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT7,
986               label='Description:', name='staticText7', parent=self,
987               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
988
989         self.Description = wx.TextCtrl(id=ID_CREATENODEDIALOGDESCRIPTION, 
990               name='Description', parent=self, pos=wx.Point(0, 0), 
991               size=wx.Size(0, 24), style=0, value='')
992
993         self.Spacer = wx.Panel(id=ID_CREATENODEDIALOGSPACER,
994               name='Spacer', parent=self, pos=wx.Point(0, 0),
995               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
996
997         self.ButtonSizer = self.CreateButtonSizer(buttons)
998         self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
999         
1000         self._init_sizers()
1001
1002     def __init__(self, parent,buttons=wx.OK|wx.CANCEL):
1003         self._init_ctrls(parent,buttons)
1004         
1005         self.staticText3.Hide()
1006         self.NodeID.Hide()
1007         
1008         self.NodeID.SetValue("0x00")
1009         self.Type.Append("master")
1010         self.Type.Append("slave")
1011         self.Type.SetStringSelection("slave")
1012         self.Description.SetValue("")
1013         self.ListProfile = {"None" : ""}
1014         self.Profile.Append("None")
1015         self.Directory = os.path.join(ScriptDirectory, "config")
1016         listfiles = os.listdir(self.Directory)
1017         listfiles.sort()
1018         for item in listfiles:
1019             name, extend = os.path.splitext(item)
1020             if os.path.isfile(os.path.join(self.Directory, item)) and extend == ".prf" and name != "DS-302":
1021                 self.ListProfile[name] = os.path.join(self.Directory, item)
1022                 self.Profile.Append(name)
1023         self.Profile.Append("Other")
1024         self.Profile.SetStringSelection("None")
1025         self.NodeName.SetFocus()
1026         
1027     def OnOK(self, event):
1028         name = self.NodeName.GetValue()
1029         message = ""
1030         if name != "":
1031             good = not name[0].isdigit()
1032             for item in name.split("_"):
1033                 good &= item.isalnum()
1034             if not good:
1035                 message = "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
1036         if message != "":
1037             try:
1038                 nodeid = int(self.NodeID.GetValue(), 16)
1039             except:
1040                 message = "Node ID must be an integer!"
1041         if message != "":
1042             message = wx.MessageDialog(self, message, "ERROR", wx.OK|wx.ICON_ERROR)
1043             message.ShowModal()
1044             message.Destroy()
1045             self.NodeName.SetFocus()
1046         else:
1047             self.EndModal(wx.ID_OK)
1048
1049     def GetValues(self):
1050         name = self.NodeName.GetValue()
1051         nodeid = 0
1052         if self.NodeID.GetValue() != "":
1053             nodeid = int(self.NodeID.GetValue(), 16)
1054         type = self.Type.GetStringSelection()
1055         description = self.Description.GetValue()
1056         return name, nodeid, type, description
1057
1058     def GetProfile(self):
1059         name = self.Profile.GetStringSelection()
1060         return name, self.ListProfile[name]
1061
1062     def GetNMTManagement(self):
1063         if self.NMT_None.GetValue():
1064             return "None"
1065         elif self.NMT_NodeGuarding.GetValue():
1066             return "NodeGuarding"
1067         elif self.NMT_Heartbeat.GetValue():
1068             return "Heartbeat"
1069         return None
1070     
1071     def GetOptions(self):
1072         options = []
1073         if self.DS302.GetValue():
1074             options.append("DS302")
1075         if self.GenSYNC.GetValue():
1076             options.append("GenSYNC")
1077         if self.Emergency.GetValue():
1078             options.append("Emergency")
1079         if self.SaveConfig.GetValue():
1080             options.append("SaveConfig")
1081         if self.StoreEDS.GetValue():
1082             options.append("StoreEDS")
1083         return options
1084
1085     def OnProfileChoice(self, event):
1086         if self.Profile.GetStringSelection() == "Other":
1087             dialog = wx.FileDialog(self, "Choose a file", self.Directory, "",  "OD Profile files (*.prf)|*.prf|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
1088             dialog.ShowModal()
1089             filepath = dialog.GetPath()
1090             dialog.Destroy()
1091             if os.path.isfile(filepath):
1092                 name = os.path.splitext(os.path.basename(filepath))[0]
1093                 self.ListProfile[name] = filepath
1094                 length = self.Profile.GetCount()
1095                 self.Profile.Insert(name, length - 2)
1096                 self.Profile.SetStringSelection(name)
1097             else:
1098                 self.Profile.SetStringSelection("None")
1099         event.Skip()
1100
1101
1102 #-------------------------------------------------------------------------------
1103 #                            ADD Slave to NodeList Dialog
1104 #-------------------------------------------------------------------------------
1105
1106 [ID_ADDSLAVEDIALOG, ID_ADDSLAVEDIALOGSLAVENAME, 
1107  ID_ADDSLAVEDIALOGSLAVENODEID, ID_ADDSLAVEDIALOGEDSFILE, 
1108  ID_ADDSLAVEDIALOGIMPORTEDS, ID_ADDSLAVEDIALOGSTATICTEXT1, 
1109  ID_ADDSLAVEDIALOGSTATICTEXT2, ID_ADDSLAVEDIALOGSTATICTEXT3, 
1110 ] = [wx.NewId() for _init_ctrls in range(8)]
1111
1112 class AddSlaveDialog(wx.Dialog):
1113     def _init_coll_flexGridSizer1_Items(self, parent):
1114         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
1115         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
1116
1117     def _init_coll_flexGridSizer1_Growables(self, parent):
1118         parent.AddGrowableCol(0)
1119         parent.AddGrowableRow(0)
1120
1121     def _init_coll_MainSizer_Items(self, parent):
1122         parent.AddWindow(self.staticText1, 0, border=5, flag=wx.GROW|wx.BOTTOM)
1123         parent.AddWindow(self.SlaveName, 0, border=10, flag=wx.GROW|wx.BOTTOM)
1124         parent.AddWindow(self.staticText2, 0, border=5, flag=wx.GROW|wx.BOTTOM)
1125         parent.AddWindow(self.SlaveNodeID, 0, border=10, flag=wx.GROW|wx.BOTTOM)
1126         parent.AddWindow(self.staticText3, 0, border=5, flag=wx.GROW|wx.BOTTOM)
1127         parent.AddSizer(self.BottomSizer, 0, border=0, flag=wx.GROW)
1128
1129     def _init_coll_BottomSizer_Items(self, parent):
1130         parent.AddWindow(self.EDSFile, 0, border=4, flag=wx.GROW|wx.TOP|wx.BOTTOM)
1131         parent.AddWindow(self.ImportEDS, 0, border=0, flag=0)
1132
1133     def _init_coll_BottomSizer_Growables(self, parent):
1134         parent.AddGrowableCol(0)
1135         parent.AddGrowableRow(0)
1136
1137     def _init_sizers(self):
1138         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
1139         self.MainSizer = wx.BoxSizer(wx.VERTICAL)
1140         self.BottomSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=0)
1141         
1142         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
1143         self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1)
1144         self._init_coll_MainSizer_Items(self.MainSizer)
1145         self._init_coll_BottomSizer_Items(self.BottomSizer)
1146         self._init_coll_BottomSizer_Growables(self.BottomSizer)
1147         
1148         self.SetSizer(self.flexGridSizer1)
1149
1150     def _init_ctrls(self, prnt):
1151         wx.Dialog.__init__(self, id=ID_ADDSLAVEDIALOG,
1152               name='AddSlaveDialog', parent=prnt, pos=wx.Point(376, 223),
1153               size=wx.Size(300, 250), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
1154               title='Add a slave to nodelist')
1155         self.SetClientSize(wx.Size(300, 250))
1156
1157         self.staticText1 = wx.StaticText(id=ID_ADDSLAVEDIALOGSTATICTEXT1,
1158               label='Slave Name:', name='staticText1', parent=self,
1159               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
1160
1161         self.SlaveName = wx.TextCtrl(id=ID_ADDSLAVEDIALOGSLAVENAME,
1162               name='SlaveName', parent=self, pos=wx.Point(0, 0), 
1163               size=wx.Size(0, 24), style=0)
1164
1165         self.staticText2 = wx.StaticText(id=ID_ADDSLAVEDIALOGSTATICTEXT2,
1166               label='Slave Node ID:', name='staticText2', parent=self,
1167               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
1168
1169         self.SlaveNodeID = wx.TextCtrl(id=ID_ADDSLAVEDIALOGSLAVENODEID,
1170               name='SlaveName', parent=self, pos=wx.Point(0, 0), 
1171               size=wx.Size(0, 24), style=wx.ALIGN_RIGHT)
1172
1173         self.staticText3 = wx.StaticText(id=ID_ADDSLAVEDIALOGSTATICTEXT3,
1174               label='EDS File:', name='staticText3', parent=self,
1175               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
1176
1177         self.EDSFile = wx.Choice(id=ID_ADDSLAVEDIALOGEDSFILE,
1178               name='EDSFile', parent=self, pos=wx.Point(0, 0),
1179               size=wx.Size(0, 24), style=0)
1180         
1181         self.ImportEDS = wx.Button(id=ID_ADDSLAVEDIALOGIMPORTEDS, label='Import EDS',
1182               name='ImportEDS', parent=self, pos=wx.Point(0, 0),
1183               size=wx.Size(100, 32), style=0)
1184         self.ImportEDS.Bind(wx.EVT_BUTTON, self.OnImportEDSButton,
1185               id=ID_ADDSLAVEDIALOGIMPORTEDS)
1186         
1187         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
1188         self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId())
1189     
1190         self._init_sizers()
1191
1192     def __init__(self, parent):
1193         self._init_ctrls(parent)
1194         
1195         self.SlaveNodeID.SetValue("0x00")
1196             
1197     def OnOK(self, event):
1198         error = []
1199         if self.SlaveName.GetValue() == "":
1200             error.append("Slave Name")
1201         if self.SlaveNodeID.GetValue() == "":
1202             error.append("Slave Node ID")
1203         if self.EDSFile.GetStringSelection() == "":
1204             error.append("EDS File")
1205         if len(error) > 0:
1206             text = ""
1207             for i, item in enumerate(error):
1208                 if i == 0:
1209                     text += item
1210                 elif i == len(error) - 1:
1211                     text += " and %s"%item
1212                 else:
1213                     text += ", %s"%item 
1214             message = wx.MessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wx.OK|wx.ICON_ERROR)
1215             message.ShowModal()
1216             message.Destroy()
1217         else:
1218             try:
1219                 nodeid = self.SlaveNodeID.GetValue()
1220                 if nodeid.find("x") != -1:
1221                     nodeid = int(nodeid, 16)
1222                 else:
1223                     nodeid = int(nodeid)
1224             except:
1225                 message = wx.MessageDialog(self, "Slave Node ID must be a value in decimal or hexadecimal!", "Error", wx.OK|wx.ICON_ERROR)
1226                 message.ShowModal()
1227                 message.Destroy()
1228                 return
1229             if not 0 <= nodeid <= 127:
1230                 message = wx.MessageDialog(self, "Slave Node ID must be between 0 and 127!", "Error", wx.OK|wx.ICON_ERROR)
1231                 message.ShowModal()
1232                 message.Destroy()
1233             elif nodeid == 0 or nodeid in self.NodeList.SlaveNodes.keys():
1234                 message = wx.MessageDialog(self, "A Node with this ID already exist in the network!", "Error", wx.OK|wx.ICON_ERROR)
1235                 message.ShowModal()
1236                 message.Destroy()
1237             else:
1238                 self.EndModal(wx.ID_OK)
1239
1240     def OnImportEDSButton(self, event):
1241         dialog = wx.FileDialog(self,
1242                                "Choose an EDS file",
1243                                os.getcwd(),
1244                                "",
1245                                "EDS files (*.eds)|*.eds|All files|*.*",
1246                                wx.OPEN)
1247         if dialog.ShowModal() == wx.ID_OK:
1248             filepath = dialog.GetPath()
1249             if os.path.isfile(filepath):
1250                 result = self.NodeList.ImportEDSFile(filepath)
1251                 if result:
1252                     message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
1253                     message.ShowModal()
1254                     message.Destroy()
1255         dialog.Destroy()
1256         self.RefreshEDSFile()
1257         event.Skip()
1258
1259     def RefreshEDSFile(self):
1260         selection = self.EDSFile.GetStringSelection()
1261         self.EDSFile.Clear()
1262         for option in self.NodeList.EDSNodes.keys():
1263             self.EDSFile.Append(option)
1264         if self.EDSFile.FindString(selection) != wx.NOT_FOUND:
1265             self.EDSFile.SetStringSelection(selection)
1266     
1267     def SetNodeList(self, nodelist):
1268         self.NodeList = nodelist
1269         self.RefreshEDSFile()
1270     
1271     def GetValues(self):
1272         values = {}
1273         values["slaveName"] = self.SlaveName.GetValue()
1274         nodeid = self.SlaveNodeID.GetValue()
1275         if nodeid.find("x") != -1:
1276             values["slaveNodeID"] = int(nodeid, 16)
1277         else:
1278             values["slaveNodeID"] = int(nodeid)
1279         values["edsFile"] = self.EDSFile.GetStringSelection()
1280         return values
1281
1282 #-------------------------------------------------------------------------------
1283 #                            Editing DCF Entry Dialog
1284 #-------------------------------------------------------------------------------
1285
1286 class DCFEntryValuesTable(wx.grid.PyGridTableBase):
1287     
1288     """
1289     A custom wxGrid Table using user supplied data
1290     """
1291     def __init__(self, parent, data, colnames):
1292         # The base class must be initialized *first*
1293         wx.grid.PyGridTableBase.__init__(self)
1294         self.data = data
1295         self.colnames = colnames
1296         self.Parent = parent
1297         # XXX
1298         # we need to store the row length and collength to
1299         # see if the table has changed size
1300         self._rows = self.GetNumberRows()
1301         self._cols = self.GetNumberCols()
1302     
1303     def GetNumberCols(self):
1304         return len(self.colnames)
1305         
1306     def GetNumberRows(self):
1307         return len(self.data)
1308
1309     def GetColLabelValue(self, col):
1310         if col < len(self.colnames):
1311             return self.colnames[col]
1312
1313     def GetRowLabelValues(self, row):
1314         return row
1315
1316     def GetValue(self, row, col):
1317         if row < self.GetNumberRows():
1318             return str(self.data[row].get(self.GetColLabelValue(col), ""))
1319             
1320     def GetEditor(self, row, col):
1321         if row < self.GetNumberRows():
1322             return self.editors[row].get(self.GetColLabelValue(col), "")
1323     
1324     def GetValueByName(self, row, colname):
1325         return self.data[row].get(colname)
1326
1327     def SetValue(self, row, col, value):
1328         if col < len(self.colnames):
1329             self.data[row][self.GetColLabelValue(col)] = value
1330         
1331     def ResetView(self, grid):
1332         """
1333         (wx.grid.Grid) -> Reset the grid view.   Call this to
1334         update the grid if rows and columns have been added or deleted
1335         """
1336         grid.BeginBatch()
1337         for current, new, delmsg, addmsg in [
1338             (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
1339             (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
1340         ]:
1341             if new < current:
1342                 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
1343                 grid.ProcessTableMessage(msg)
1344             elif new > current:
1345                 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
1346                 grid.ProcessTableMessage(msg)
1347                 self.UpdateValues(grid)
1348         grid.EndBatch()
1349
1350         self._rows = self.GetNumberRows()
1351         self._cols = self.GetNumberCols()
1352         # update the column rendering scheme
1353         self._updateColAttrs(grid)
1354
1355         # update the scrollbars and the displayed part of the grid
1356         grid.AdjustScrollbars()
1357         grid.ForceRefresh()
1358
1359
1360     def UpdateValues(self, grid):
1361         """Update all displayed values"""
1362         # This sends an event to the grid table to update all of the values
1363         msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
1364         grid.ProcessTableMessage(msg)
1365
1366     def _updateColAttrs(self, grid):
1367         """
1368         wx.grid.Grid -> update the column attributes to add the
1369         appropriate renderer given the column name.
1370
1371         Otherwise default to the default renderer.
1372         """
1373         
1374         for row in range(self.GetNumberRows()):
1375             for col in range(self.GetNumberCols()):
1376                 editor = wx.grid.GridCellTextEditor()
1377                 renderer = wx.grid.GridCellStringRenderer()
1378                     
1379                 grid.SetCellEditor(row, col, editor)
1380                 grid.SetCellRenderer(row, col, renderer)
1381                 
1382                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
1383     
1384     def SetData(self, data):
1385         self.data = data
1386     
1387     def AppendRow(self, row_content):
1388         self.data.append(row_content)
1389
1390     def Empty(self):
1391         self.data = []
1392         self.editors = []
1393
1394 [ID_DCFENTRYVALUESDIALOG, ID_DCFENTRYVALUESDIALOGVALUESGRID, 
1395  ID_DCFENTRYVALUESDIALOGADDBUTTON, ID_DCFENTRYVALUESDIALOGDELETEBUTTON, 
1396  ID_DCFENTRYVALUESDIALOGUPBUTTON, ID_DCFENTRYVALUESDIALOGDOWNBUTTON, 
1397  ID_VARIABLEEDITORPANELSTATICTEXT1, 
1398 ] = [wx.NewId() for _init_ctrls in range(7)]
1399
1400 class DCFEntryValuesDialog(wx.Dialog):
1401     
1402     if wx.VERSION < (2, 6, 0):
1403         def Bind(self, event, function, id = None):
1404             if id is not None:
1405                 event(self, id, function)
1406             else:
1407                 event(self, function)
1408     
1409     def _init_coll_MainSizer_Items(self, parent):
1410         parent.AddWindow(self.staticText1, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
1411         parent.AddWindow(self.ValuesGrid, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
1412         parent.AddSizer(self.ButtonPanelSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT)
1413         parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
1414     
1415     def _init_coll_MainSizer_Growables(self, parent):
1416         parent.AddGrowableCol(0)
1417         parent.AddGrowableRow(1)
1418     
1419     def _init_coll_ButtonPanelSizer_Items(self, parent):
1420         parent.AddWindow(self.UpButton, 0, border=5, flag=wx.ALL)
1421         parent.AddWindow(self.AddButton, 0, border=5, flag=wx.ALL)
1422         parent.AddWindow(self.DownButton, 0, border=5, flag=wx.ALL)
1423         parent.AddWindow(self.DeleteButton, 0, border=5, flag=wx.ALL)
1424         
1425     def _init_sizers(self):
1426         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=0)
1427         self.ButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
1428         
1429         self._init_coll_MainSizer_Items(self.MainSizer)
1430         self._init_coll_MainSizer_Growables(self.MainSizer)
1431         self._init_coll_ButtonPanelSizer_Items(self.ButtonPanelSizer)
1432         
1433         self.SetSizer(self.MainSizer)
1434
1435     def _init_ctrls(self, prnt):
1436         wx.Dialog.__init__(self, id=ID_DCFENTRYVALUESDIALOG,
1437               name='DCFEntryValuesDialog', parent=prnt, pos=wx.Point(376, 223),
1438               size=wx.Size(400, 300), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
1439               title='Edit DCF Entry Values')
1440         self.SetClientSize(wx.Size(400, 300))
1441
1442         self.staticText1 = wx.StaticText(id=ID_VARIABLEEDITORPANELSTATICTEXT1,
1443               label='Entry Values:', name='staticText1', parent=self,
1444               pos=wx.Point(0, 0), size=wx.Size(95, 17), style=0)
1445
1446         self.ValuesGrid = wx.grid.Grid(id=ID_DCFENTRYVALUESDIALOGVALUESGRID,
1447               name='ValuesGrid', parent=self, pos=wx.Point(0, 0), 
1448               size=wx.Size(0, 150), style=wx.VSCROLL)
1449         self.ValuesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
1450               'Sans'))
1451         self.ValuesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
1452               False, 'Sans'))
1453         self.ValuesGrid.SetRowLabelSize(0)
1454         self.ValuesGrid.SetSelectionBackground(wx.WHITE)
1455         self.ValuesGrid.SetSelectionForeground(wx.BLACK)
1456         if wx.VERSION >= (2, 6, 0):
1457             self.ValuesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnValuesGridCellChange)
1458             self.ValuesGrid.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnValuesGridSelectCell)
1459         else:
1460             wx.grid.EVT_GRID_CELL_CHANGE(self.ValuesGrid, self.OnValuesGridCellChange)
1461             wx.grid.EVT_GRID_SELECT_CELL(self.ValuesGrid, self.OnValuesGridSelectCell)
1462         
1463         self.AddButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGADDBUTTON, label='Add',
1464               name='AddButton', parent=self, pos=wx.Point(0, 0),
1465               size=wx.Size(72, 32), style=0)
1466         self.Bind(wx.EVT_BUTTON, self.OnAddButton, id=ID_DCFENTRYVALUESDIALOGADDBUTTON)
1467
1468         self.DeleteButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON, label='Delete',
1469               name='DeleteButton', parent=self, pos=wx.Point(0, 0),
1470               size=wx.Size(72, 32), style=0)
1471         self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON)
1472
1473         self.UpButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGUPBUTTON, label='^',
1474               name='UpButton', parent=self, pos=wx.Point(0, 0),
1475               size=wx.Size(32, 32), style=0)
1476         self.Bind(wx.EVT_BUTTON, self.OnUpButton, id=ID_DCFENTRYVALUESDIALOGUPBUTTON)
1477
1478         self.DownButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGDOWNBUTTON, label='v',
1479               name='DownButton', parent=self, pos=wx.Point(0, 0),
1480               size=wx.Size(32, 32), style=0)
1481         self.Bind(wx.EVT_BUTTON, self.OnDownButton, id=ID_DCFENTRYVALUESDIALOGDOWNBUTTON)
1482
1483         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
1484         
1485         self._init_sizers()
1486
1487     def __init__(self, parent):
1488         self._init_ctrls(parent)
1489         
1490         self.Values = []
1491         self.DefaultValue = {"Index" : 0, "Subindex" : 0, "Size" : 1, "Value" : 0}
1492         
1493         self.Table = DCFEntryValuesTable(self, [], ["Index", "Subindex", "Size", "Value"])
1494         self.ValuesGrid.SetTable(self.Table)
1495         
1496     def OnValuesGridCellChange(self, event):
1497         row, col = event.GetRow(), event.GetCol()
1498         colname = self.Table.GetColLabelValue(col)
1499         value = self.Table.GetValue(row, col)
1500         try:
1501             self.Values[row][colname] = int(value, 16)
1502         except:
1503             message = wx.MessageDialog(self, "\"%s\" is not a valid value!"%value, "Error", wx.OK|wx.ICON_ERROR)
1504             message.ShowModal()
1505             message.Destroy()
1506         wx.CallAfter(self.RefreshValues)
1507         event.Skip()
1508     
1509     def OnValuesGridSelectCell(self, event):
1510         wx.CallAfter(self.RefreshButtons)
1511         event.Skip()
1512     
1513     def RefreshButtons(self):
1514         row = self.ValuesGrid.GetGridCursorRow()
1515         length = len(self.Table.data)
1516         self.DeleteButton.Enable(length > 0)
1517         self.UpButton.Enable(row > 0)
1518         self.DownButton.Enable(row < length - 1)
1519     
1520     def OnAddButton(self, event):
1521         new_row = self.DefaultValue.copy()
1522         self.Values.append(new_row)
1523         self.RefreshValues()
1524         event.Skip()
1525
1526     def OnDeleteButton(self, event):
1527         row = self.ValuesGrid.GetGridCursorRow()
1528         self.Values.pop(row)
1529         self.RefreshValues()
1530         event.Skip()
1531
1532     def OnUpButton(self, event):
1533         self.MoveValue(self.ValuesGrid.GetGridCursorRow(), -1)
1534         event.Skip()
1535
1536     def OnDownButton(self, event):
1537         self.MoveValue(self.ValuesGrid.GetGridCursorRow(), 1)
1538         event.Skip()
1539
1540     def MoveValue(self, value_index, move):
1541         new_index = max(0, min(value_index + move, len(self.Values) - 1))
1542         if new_index != value_index:
1543             self.Values.insert(new_index, self.Values.pop(value_index))
1544             col = self.ValuesGrid.GetGridCursorCol()
1545             self.RefreshValues()
1546             self.ValuesGrid.SetGridCursor(new_index, col)
1547             self.RefreshButtons()
1548         else:
1549             self.RefreshValues()
1550
1551     def SetValues(self, values):
1552         self.Values = []
1553         if values != "":
1554             data = values[4:]
1555             current = 0
1556             for i in xrange(BE_to_LE(values[:4])):
1557                 value = {}
1558                 value["Index"] = BE_to_LE(data[current:current+2])
1559                 value["Subindex"] = BE_to_LE(data[current+2:current+3])
1560                 size = BE_to_LE(data[current+3:current+7])
1561                 value["Size"] = size
1562                 value["Value"] = BE_to_LE(data[current+7:current+7+size])
1563                 current += 7 + size
1564                 self.Values.append(value)
1565         self.RefreshValues()
1566     
1567     def GetValues(self):
1568         if len(self.Values) > 0:
1569             value = LE_to_BE(len(self.Values), 4)
1570             for row in self.Values:
1571                 value += LE_to_BE(row["Index"], 2)
1572                 value += LE_to_BE(row["Subindex"], 1)
1573                 value += LE_to_BE(row["Size"], 4)
1574                 value += LE_to_BE(row["Value"], row["Size"])
1575             return value
1576         return ""
1577     
1578     def RefreshValues(self):
1579         if len(self.Table.data) > 0:
1580             self.ValuesGrid.SetGridCursor(0, 0)
1581         data = []
1582         for value in self.Values:
1583             row = {}
1584             row["Index"] = "%04X"%value["Index"]
1585             row["Subindex"] = "%02X"%value["Subindex"]
1586             row["Size"] = "%08X"%value["Size"]
1587             row["Value"] = ("%0"+"%d"%(value["Size"] * 2)+"X")%value["Value"]
1588             data.append(row)
1589         self.Table.SetData(data)
1590         self.Table.ResetView(self.ValuesGrid)
1591         self.RefreshButtons()
1592