21 #You should have received a copy of the GNU General Public |
21 #You should have received a copy of the GNU General Public |
22 #License along with this library; if not, write to the Free Software |
22 #License along with this library; if not, write to the Free Software |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
24 |
24 |
25 import os |
25 import os |
26 import wx, wx.grid |
|
27 import re |
26 import re |
28 |
|
29 from types import TupleType, StringType, UnicodeType |
27 from types import TupleType, StringType, UnicodeType |
|
28 |
|
29 import wx |
|
30 import wx.grid |
|
31 import wx.lib.buttons |
30 |
32 |
31 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS |
33 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS |
32 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT |
34 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT |
33 from dialogs.ArrayTypeDialog import ArrayTypeDialog |
35 from dialogs.ArrayTypeDialog import ArrayTypeDialog |
34 from CustomGrid import CustomGrid |
36 from CustomGrid import CustomGrid |
35 from CustomTable import CustomTable |
37 from CustomTable import CustomTable |
36 from LocationCellEditor import LocationCellEditor |
38 from LocationCellEditor import LocationCellEditor |
37 |
39 from utils.BitmapLibrary import GetBitmap |
38 # Compatibility function for wx versions < 2.6 |
40 |
|
41 #------------------------------------------------------------------------------- |
|
42 # Helpers |
|
43 #------------------------------------------------------------------------------- |
|
44 |
39 def AppendMenu(parent, help, id, kind, text): |
45 def AppendMenu(parent, help, id, kind, text): |
40 if wx.VERSION >= (2, 6, 0): |
46 if wx.VERSION >= (2, 6, 0): |
41 parent.Append(help=help, id=id, kind=kind, text=text) |
47 parent.Append(help=help, id=id, kind=kind, text=text) |
42 else: |
48 else: |
43 parent.Append(helpString=help, id=id, kind=kind, item=text) |
49 parent.Append(helpString=help, id=id, kind=kind, item=text) |
44 |
50 |
45 [TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, |
51 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, |
46 POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING |
52 POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES |
47 ] = range(9) |
53 ] = range(10) |
48 |
|
49 #------------------------------------------------------------------------------- |
|
50 # Variables Editor Panel |
|
51 #------------------------------------------------------------------------------- |
|
52 |
54 |
53 def GetVariableTableColnames(location): |
55 def GetVariableTableColnames(location): |
54 _ = lambda x : x |
56 _ = lambda x : x |
55 if location: |
57 if location: |
56 return ["#", _("Name"), _("Class"), _("Type"), _("Location"), _("Initial Value"), _("Option"), _("Documentation")] |
58 return ["#", _("Name"), _("Class"), _("Type"), _("Location"), _("Initial Value"), _("Option"), _("Documentation")] |
299 self.ParentWindow.SaveValues() |
308 self.ParentWindow.SaveValues() |
300 self.ParentWindow.RefreshValues() |
309 self.ParentWindow.RefreshValues() |
301 |
310 |
302 if message is not None: |
311 if message is not None: |
303 wx.CallAfter(self.ShowMessage, message) |
312 wx.CallAfter(self.ShowMessage, message) |
304 |
313 |
305 |
|
306 def ShowMessage(self, message): |
314 def ShowMessage(self, message): |
307 message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
315 message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
308 message.ShowModal() |
316 message.ShowModal() |
309 message.Destroy() |
317 message.Destroy() |
310 |
318 |
311 [ID_VARIABLEEDITORPANEL, ID_VARIABLEEDITORPANELVARIABLESGRID, |
319 #------------------------------------------------------------------------------- |
312 ID_VARIABLEEDITORCONTROLPANEL, ID_VARIABLEEDITORPANELRETURNTYPELABEL, |
320 # Variable Panel |
313 ID_VARIABLEEDITORPANELRETURNTYPE, ID_VARIABLEEDITORPANELDESCRIPTIONLABEL, |
321 #------------------------------------------------------------------------------- |
314 ID_VARIABLEEDITORPANELDESCRIPTION, ID_VARIABLEEDITORPANELCLASSFILTERLABEL, |
|
315 ID_VARIABLEEDITORPANELCLASSFILTER, ID_VARIABLEEDITORPANELADDBUTTON, |
|
316 ID_VARIABLEEDITORPANELDELETEBUTTON, ID_VARIABLEEDITORPANELUPBUTTON, |
|
317 ID_VARIABLEEDITORPANELDOWNBUTTON, |
|
318 ] = [wx.NewId() for _init_ctrls in range(13)] |
|
319 |
322 |
320 class VariablePanel(wx.Panel): |
323 class VariablePanel(wx.Panel): |
321 |
324 |
322 if wx.VERSION < (2, 6, 0): |
325 def __init__(self, parent, window, controler, element_type, debug=False): |
323 def Bind(self, event, function, id = None): |
326 wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL) |
324 if id is not None: |
327 |
325 event(self, id, function) |
|
326 else: |
|
327 event(self, function) |
|
328 |
|
329 def _init_coll_MainSizer_Items(self, parent): |
|
330 parent.AddWindow(self.ControlPanel, 0, border=5, flag=wx.GROW|wx.ALL) |
|
331 parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW) |
|
332 |
|
333 def _init_coll_MainSizer_Growables(self, parent): |
|
334 parent.AddGrowableCol(0) |
|
335 parent.AddGrowableRow(1) |
|
336 |
|
337 def _init_coll_ControlPanelSizer_Items(self, parent): |
|
338 parent.AddWindow(self.ReturnTypeLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) |
|
339 parent.AddWindow(self.ReturnType, 0, border=0, flag=0) |
|
340 parent.AddWindow(self.DescriptionLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) |
|
341 parent.AddWindow(self.Description, 0, border=0, flag=0) |
|
342 parent.AddWindow(self.ClassFilterLabel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) |
|
343 parent.AddWindow(self.ClassFilter, 0, border=0, flag=0) |
|
344 parent.AddWindow(self.AddButton, 0, border=0, flag=0) |
|
345 parent.AddWindow(self.DeleteButton, 0, border=0, flag=0) |
|
346 parent.AddWindow(self.UpButton, 0, border=0, flag=0) |
|
347 parent.AddWindow(self.DownButton, 0, border=0, flag=0) |
|
348 |
|
349 def _init_coll_ControlPanelSizer_Growables(self, parent): |
|
350 parent.AddGrowableCol(5) |
|
351 parent.AddGrowableRow(0) |
|
352 |
|
353 def _init_sizers(self): |
|
354 self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0) |
328 self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0) |
355 self.ControlPanelSizer = wx.FlexGridSizer(cols=10, hgap=5, rows=1, vgap=5) |
329 self.MainSizer.AddGrowableCol(0) |
356 |
330 self.MainSizer.AddGrowableRow(1) |
357 self._init_coll_MainSizer_Items(self.MainSizer) |
331 |
358 self._init_coll_MainSizer_Growables(self.MainSizer) |
332 controls_sizer = wx.FlexGridSizer(cols=10, hgap=5, rows=1, vgap=5) |
359 self._init_coll_ControlPanelSizer_Items(self.ControlPanelSizer) |
333 controls_sizer.AddGrowableCol(5) |
360 self._init_coll_ControlPanelSizer_Growables(self.ControlPanelSizer) |
334 controls_sizer.AddGrowableRow(0) |
361 |
335 self.MainSizer.AddSizer(controls_sizer, border=5, flag=wx.GROW|wx.ALL) |
362 self.ControlPanel.SetSizer(self.ControlPanelSizer) |
336 |
|
337 self.ReturnTypeLabel = wx.StaticText(self, label=_('Return Type:')) |
|
338 controls_sizer.AddWindow(self.ReturnTypeLabel, flag=wx.ALIGN_CENTER_VERTICAL) |
|
339 |
|
340 self.ReturnType = wx.ComboBox(self, |
|
341 size=wx.Size(145, -1), style=wx.CB_READONLY) |
|
342 self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, self.ReturnType) |
|
343 controls_sizer.AddWindow(self.ReturnType) |
|
344 |
|
345 self.DescriptionLabel = wx.StaticText(self, label=_('Description:')) |
|
346 controls_sizer.AddWindow(self.DescriptionLabel, flag=wx.ALIGN_CENTER_VERTICAL) |
|
347 |
|
348 self.Description = wx.TextCtrl(self, |
|
349 size=wx.Size(250, -1), style=wx.TE_PROCESS_ENTER) |
|
350 self.Bind(wx.EVT_TEXT_ENTER, self.OnDescriptionChanged, self.Description) |
|
351 self.Description.Bind(wx.EVT_KILL_FOCUS, self.OnDescriptionChanged) |
|
352 controls_sizer.AddWindow(self.Description) |
|
353 |
|
354 class_filter_label = wx.StaticText(self, label=_('Class Filter:')) |
|
355 controls_sizer.AddWindow(class_filter_label, flag=wx.ALIGN_CENTER_VERTICAL) |
|
356 |
|
357 self.ClassFilter = wx.ComboBox(self, |
|
358 size=wx.Size(145, -1), style=wx.CB_READONLY) |
|
359 self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, self.ClassFilter) |
|
360 controls_sizer.AddWindow(self.ClassFilter) |
|
361 |
|
362 for name, bitmap, help in [ |
|
363 ("AddButton", "add_element", _("Add variable")), |
|
364 ("DeleteButton", "remove_element", _("Remove variable")), |
|
365 ("UpButton", "up", _("Move variable up")), |
|
366 ("DownButton", "down", _("Move variable down"))]: |
|
367 button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), |
|
368 size=wx.Size(28, 28), style=wx.NO_BORDER) |
|
369 button.SetToolTipString(help) |
|
370 setattr(self, name, button) |
|
371 controls_sizer.AddWindow(button) |
|
372 |
|
373 self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL) |
|
374 self.VariablesGrid.SetDropTarget(VariableDropTarget(self)) |
|
375 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, |
|
376 self.OnVariablesGridCellChange) |
|
377 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, |
|
378 self.OnVariablesGridCellLeftClick) |
|
379 self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, |
|
380 self.OnVariablesGridEditorShown) |
|
381 self.MainSizer.AddWindow(self.VariablesGrid, flag=wx.GROW) |
|
382 |
363 self.SetSizer(self.MainSizer) |
383 self.SetSizer(self.MainSizer) |
364 |
384 |
365 def _init_ctrls(self, prnt): |
|
366 wx.Panel.__init__(self, id=ID_VARIABLEEDITORPANEL, |
|
367 name='VariableEditorPanel', parent=prnt, pos=wx.Point(0, 0), |
|
368 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
369 |
|
370 self.VariablesGrid = CustomGrid(id=ID_VARIABLEEDITORPANELVARIABLESGRID, |
|
371 name='VariablesGrid', parent=self, pos=wx.Point(0, 0), |
|
372 size=wx.Size(0, 0), style=wx.VSCROLL) |
|
373 self.VariablesGrid.SetDropTarget(VariableDropTarget(self)) |
|
374 if wx.VERSION >= (2, 6, 0): |
|
375 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange) |
|
376 self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick) |
|
377 self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown) |
|
378 else: |
|
379 wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange) |
|
380 wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick) |
|
381 wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown) |
|
382 |
|
383 self.ControlPanel = wx.ScrolledWindow(id=ID_VARIABLEEDITORCONTROLPANEL, |
|
384 name='ControlPanel', parent=self, pos=wx.Point(0, 0), |
|
385 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
386 self.ControlPanel.SetScrollRate(10, 0) |
|
387 |
|
388 self.ReturnTypeLabel = wx.StaticText(id=ID_VARIABLEEDITORPANELRETURNTYPELABEL, |
|
389 label=_('Return Type:'), name='ReturnTypeLabel', parent=self.ControlPanel, |
|
390 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
391 |
|
392 self.ReturnType = wx.ComboBox(id=ID_VARIABLEEDITORPANELRETURNTYPE, |
|
393 name='ReturnType', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
394 size=wx.Size(145, -1), style=wx.CB_READONLY) |
|
395 self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, id=ID_VARIABLEEDITORPANELRETURNTYPE) |
|
396 |
|
397 self.DescriptionLabel = wx.StaticText(id=ID_VARIABLEEDITORPANELDESCRIPTIONLABEL, |
|
398 label=_('Description:'), name='DescriptionLabel', parent=self.ControlPanel, |
|
399 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
400 |
|
401 self.Description = wx.TextCtrl(id=ID_VARIABLEEDITORPANELDESCRIPTION, |
|
402 name='Description', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
403 size=wx.Size(250, -1), style=wx.TE_PROCESS_ENTER) |
|
404 self.Bind(wx.EVT_TEXT_ENTER, self.OnDescriptionChanged, id=ID_VARIABLEEDITORPANELDESCRIPTION) |
|
405 self.Description.Bind(wx.EVT_KILL_FOCUS, self.OnDescriptionChanged) |
|
406 |
|
407 self.ClassFilterLabel = wx.StaticText(id=ID_VARIABLEEDITORPANELCLASSFILTERLABEL, |
|
408 label=_('Class Filter:'), name='ClassFilterLabel', parent=self.ControlPanel, |
|
409 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
410 |
|
411 self.ClassFilter = wx.ComboBox(id=ID_VARIABLEEDITORPANELCLASSFILTER, |
|
412 name='ClassFilter', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
413 size=wx.Size(145, -1), style=wx.CB_READONLY) |
|
414 self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, id=ID_VARIABLEEDITORPANELCLASSFILTER) |
|
415 |
|
416 self.AddButton = wx.Button(id=ID_VARIABLEEDITORPANELADDBUTTON, label=_('Add'), |
|
417 name='AddButton', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
418 size=wx.DefaultSize, style=0) |
|
419 |
|
420 self.DeleteButton = wx.Button(id=ID_VARIABLEEDITORPANELDELETEBUTTON, label=_('Delete'), |
|
421 name='DeleteButton', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
422 size=wx.DefaultSize, style=0) |
|
423 |
|
424 self.UpButton = wx.Button(id=ID_VARIABLEEDITORPANELUPBUTTON, label='^', |
|
425 name='UpButton', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
426 size=wx.Size(28, -1), style=0) |
|
427 |
|
428 self.DownButton = wx.Button(id=ID_VARIABLEEDITORPANELDOWNBUTTON, label='v', |
|
429 name='DownButton', parent=self.ControlPanel, pos=wx.Point(0, 0), |
|
430 size=wx.Size(28, -1), style=0) |
|
431 |
|
432 self._init_sizers() |
|
433 |
|
434 def __init__(self, parent, window, controler, element_type, debug=False): |
|
435 self._init_ctrls(parent) |
|
436 self.ParentWindow = window |
385 self.ParentWindow = window |
437 self.Controler = controler |
386 self.Controler = controler |
438 self.ElementType = element_type |
387 self.ElementType = element_type |
439 self.Debug = debug |
388 self.Debug = debug |
440 |
389 |
441 self.RefreshHighlightsTimer = wx.Timer(self, -1) |
390 self.RefreshHighlightsTimer = wx.Timer(self, -1) |
442 self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer) |
391 self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, |
|
392 self.RefreshHighlightsTimer) |
443 |
393 |
444 self.Filter = "All" |
394 self.Filter = "All" |
445 self.FilterChoices = [] |
395 self.FilterChoices = [] |
446 self.FilterChoiceTransfer = GetFilterChoiceTransfer() |
396 self.FilterChoiceTransfer = GetFilterChoiceTransfer() |
447 |
397 |
448 self.DefaultValue = { "Name" : "", "Class" : "", "Type" : "INT", "Location" : "", |
398 self.DefaultValue = { |
449 "Initial Value" : "", "Option" : "", |
399 "Name" : "", |
450 "Documentation" : "", "Edit" : True |
400 "Class" : "", |
451 } |
401 "Type" : "INT", |
|
402 "Location" : "", |
|
403 "Initial Value" : "", |
|
404 "Option" : "", |
|
405 "Documentation" : "", |
|
406 "Edit" : True |
|
407 } |
452 |
408 |
453 if element_type in ["config", "resource"]: |
409 if element_type in ["config", "resource"]: |
454 self.DefaultTypes = {"All" : "Global"} |
410 self.DefaultTypes = {"All" : "Global"} |
455 else: |
411 else: |
456 self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"} |
412 self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"} |