controls/VariablePanel.py
changeset 714 131ea7f237b9
parent 684 f10449b18dbe
child 716 2681a6da58d6
equal deleted inserted replaced
713:95a0a427f3ef 714:131ea7f237b9
    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")]
    85                        "Global": lambda x: {"Constant": "Constant", "Retain": "Retain"}.get(x, ""),
    87                        "Global": lambda x: {"Constant": "Constant", "Retain": "Retain"}.get(x, ""),
    86                        "External": lambda x: {"Constant": "Constant"}.get(x, "")
    88                        "External": lambda x: {"Constant": "Constant"}.get(x, "")
    87                       }
    89                       }
    88 
    90 
    89 LOCATION_MODEL = re.compile("((?:%[IQM](?:\*|(?:[XBWLD]?[0-9]+(?:\.[0-9]+)*)))?)$")
    91 LOCATION_MODEL = re.compile("((?:%[IQM](?:\*|(?:[XBWLD]?[0-9]+(?:\.[0-9]+)*)))?)$")
       
    92 
       
    93 #-------------------------------------------------------------------------------
       
    94 #                            Variables Panel Table
       
    95 #-------------------------------------------------------------------------------
    90 
    96 
    91 class VariableTable(CustomTable):
    97 class VariableTable(CustomTable):
    92     
    98     
    93     """
    99     """
    94     A custom wx.grid.Grid Table using user supplied data
   100     A custom wx.grid.Grid Table using user supplied data
   203                 else:
   209                 else:
   204                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
   210                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
   205                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
   211                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
   206                 grid.SetCellTextColour(row, col, highlight_colours[1])
   212                 grid.SetCellTextColour(row, col, highlight_colours[1])
   207             self.ResizeRow(grid, row)
   213             self.ResizeRow(grid, row)
   208                     
   214 
       
   215 #-------------------------------------------------------------------------------
       
   216 #                         Variable Panel Drop Target
       
   217 #-------------------------------------------------------------------------------   
   209 
   218 
   210 class VariableDropTarget(wx.TextDropTarget):
   219 class VariableDropTarget(wx.TextDropTarget):
   211     '''
   220     '''
   212     This allows dragging a variable location from somewhere to the Location
   221     This allows dragging a variable location from somewhere to the Location
   213     column of a variable row.
   222     column of a variable row.
   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"}
   634             self.DescriptionLabel.Hide()
   590             self.DescriptionLabel.Hide()
   635             self.Description.Hide()
   591             self.Description.Hide()
   636         
   592         
   637         self.RefreshValues()
   593         self.RefreshValues()
   638         self.VariablesGrid.RefreshButtons()
   594         self.VariablesGrid.RefreshButtons()
   639         self.ControlPanelSizer.Layout()
       
   640         self.MainSizer.Layout()
   595         self.MainSizer.Layout()
   641     
   596     
   642     def OnReturnTypeChanged(self, event):
   597     def OnReturnTypeChanged(self, event):
   643         words = self.TagName.split("::")
   598         words = self.TagName.split("::")
   644         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   599         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())