DataTypeEditor.py
changeset 295 c6ef6d92ce16
parent 235 7b58a3b5b6ec
child 304 2df3d31d8059
equal deleted inserted replaced
294:4a36f2ec8967 295:c6ef6d92ce16
    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 wx
    25 import wx
    26 import wx.grid
    26 import wx.grid
    27 import wx.gizmos
    27 import wx.gizmos
    28 from plcopen.structures import IEC_KEYWORDS
    28 from plcopen.structures import IEC_KEYWORDS, TestIdentifier
    29 
    29 
    30 import re
    30 import re
    31 
    31 
    32 DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$")
    32 DIMENSION_MODEL = re.compile("([0-9]+)\.\.([0-9]+)$")
    33 
    33 
       
    34 def AppendMenu(parent, help, id, kind, text):
       
    35     if wx.VERSION >= (2, 6, 0):
       
    36         parent.Append(help=help, id=id, kind=kind, text=text)
       
    37     else:
       
    38         parent.Append(helpString=help, id=id, kind=kind, item=text)
       
    39 
       
    40 #-------------------------------------------------------------------------------
       
    41 #                            Structure Elements Table
       
    42 #-------------------------------------------------------------------------------
       
    43 
       
    44 class ElementsTable(wx.grid.PyGridTableBase):
       
    45     
       
    46     """
       
    47     A custom wx.grid.Grid Table using user supplied data
       
    48     """
       
    49     def __init__(self, parent, data, colnames):
       
    50         # The base class must be initialized *first*
       
    51         wx.grid.PyGridTableBase.__init__(self)
       
    52         self.data = data
       
    53         self.old_value = None
       
    54         self.colnames = colnames
       
    55         self.Errors = {}
       
    56         self.Parent = parent
       
    57         # XXX
       
    58         # we need to store the row length and collength to
       
    59         # see if the table has changed size
       
    60         self._rows = self.GetNumberRows()
       
    61         self._cols = self.GetNumberCols()
       
    62     
       
    63     def GetNumberCols(self):
       
    64         return len(self.colnames)
       
    65         
       
    66     def GetNumberRows(self):
       
    67         return len(self.data)
       
    68 
       
    69     def GetColLabelValue(self, col):
       
    70         if col < len(self.colnames):
       
    71             return self.colnames[col]
       
    72 
       
    73     def GetRowLabelValues(self, row):
       
    74         return row
       
    75 
       
    76     def GetValue(self, row, col):
       
    77         if row < self.GetNumberRows():
       
    78             if col == 0:
       
    79                 return row + 1
       
    80             name = str(self.data[row].get(self.GetColLabelValue(col), ""))
       
    81             return name
       
    82     
       
    83     def SetValue(self, row, col, value):
       
    84         if col < len(self.colnames):
       
    85             colname = self.GetColLabelValue(col)
       
    86             if colname == "Name":
       
    87                 self.old_value = self.data[row][colname]
       
    88             self.data[row][colname] = value
       
    89     
       
    90     def GetValueByName(self, row, colname):
       
    91         if row < self.GetNumberRows():
       
    92             return self.data[row].get(colname)
       
    93 
       
    94     def SetValueByName(self, row, colname, value):
       
    95         if row < self.GetNumberRows():
       
    96             self.data[row][colname] = value
       
    97 
       
    98     def GetOldValue(self):
       
    99         return self.old_value
       
   100     
       
   101     def ResetView(self, grid):
       
   102         """
       
   103         (wx.grid.Grid) -> Reset the grid view.   Call this to
       
   104         update the grid if rows and columns have been added or deleted
       
   105         """
       
   106         grid.BeginBatch()
       
   107         for current, new, delmsg, addmsg in [
       
   108             (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
       
   109             (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
       
   110         ]:
       
   111             if new < current:
       
   112                 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
       
   113                 grid.ProcessTableMessage(msg)
       
   114             elif new > current:
       
   115                 msg = wx.grid.GridTableMessage(self,addmsg,new-current)
       
   116                 grid.ProcessTableMessage(msg)
       
   117                 self.UpdateValues(grid)
       
   118         grid.EndBatch()
       
   119 
       
   120         self._rows = self.GetNumberRows()
       
   121         self._cols = self.GetNumberCols()
       
   122         # update the column rendering scheme
       
   123         self._updateColAttrs(grid)
       
   124 
       
   125         # update the scrollbars and the displayed part of the grid
       
   126         grid.AdjustScrollbars()
       
   127         grid.ForceRefresh()
       
   128 
       
   129     def UpdateValues(self, grid):
       
   130         """Update all displayed values"""
       
   131         # This sends an event to the grid table to update all of the values
       
   132         msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
       
   133         grid.ProcessTableMessage(msg)
       
   134 
       
   135     def _updateColAttrs(self, grid):
       
   136         """
       
   137         wx.grid.Grid -> update the column attributes to add the
       
   138         appropriate renderer given the column name.
       
   139 
       
   140         Otherwise default to the default renderer.
       
   141         """
       
   142         
       
   143         typelist = None
       
   144         accesslist = None
       
   145         for row in range(self.GetNumberRows()):
       
   146             for col in range(self.GetNumberCols()):
       
   147                 editor = None
       
   148                 renderer = None
       
   149                 colname = self.GetColLabelValue(col)
       
   150                 if col != 0:
       
   151                     grid.SetReadOnly(row, col, False)
       
   152                     if colname == "Name":
       
   153                         editor = wx.grid.GridCellTextEditor()
       
   154                         renderer = wx.grid.GridCellStringRenderer()
       
   155                     elif colname == "Initial Value":
       
   156                         editor = wx.grid.GridCellTextEditor()
       
   157                         renderer = wx.grid.GridCellStringRenderer()
       
   158                     elif colname == "Type":
       
   159                         editor = wx.grid.GridCellTextEditor()
       
   160                 else:
       
   161                     grid.SetReadOnly(row, col, True)
       
   162                 
       
   163                 grid.SetCellEditor(row, col, editor)
       
   164                 grid.SetCellRenderer(row, col, renderer)
       
   165                 
       
   166                 if row in self.Errors and self.Errors[row][0] == colname.lower():
       
   167                     grid.SetCellBackgroundColour(row, col, wx.Colour(255, 255, 0))
       
   168                     grid.SetCellTextColour(row, col, wx.RED)
       
   169                     grid.MakeCellVisible(row, col)
       
   170                 else:
       
   171                     grid.SetCellTextColour(row, col, wx.BLACK)
       
   172                     grid.SetCellBackgroundColour(row, col, wx.WHITE)
       
   173     
       
   174     def SetData(self, data):
       
   175         self.data = data
       
   176     
       
   177     def GetData(self):
       
   178         return self.data
       
   179     
       
   180     def AppendRow(self, row_content):
       
   181         self.data.append(row_content)
       
   182 
       
   183     def RemoveRow(self, row_index):
       
   184         self.data.pop(row_index)
       
   185 
       
   186     def MoveRow(self, idx, move):
       
   187         new_idx = max(0, min(idx + move, len(self.data) - 1))
       
   188         if new_idx != idx:
       
   189             self.data.insert(new_idx, self.data.pop(idx))
       
   190             return new_idx
       
   191         return None
       
   192     
       
   193     def GetRow(self, row_index):
       
   194         return self.data[row_index]
       
   195 
       
   196     def Empty(self):
       
   197         self.data = []
       
   198         self.editors = []
       
   199 
       
   200     def AddError(self, infos):
       
   201         self.Errors[infos[0]] = infos[1:]
       
   202 
       
   203     def ClearErrors(self):
       
   204         self.Errors = {}
    34 
   205 
    35 #-------------------------------------------------------------------------------
   206 #-------------------------------------------------------------------------------
    36 #                          Configuration Editor class
   207 #                          Configuration Editor class
    37 #-------------------------------------------------------------------------------
   208 #-------------------------------------------------------------------------------
    38 
   209 
    43  ID_DATATYPEEDITORSUBRANGEMAXIMUM, ID_DATATYPEEDITORDIRECTLYINITIALVALUE, 
   214  ID_DATATYPEEDITORSUBRANGEMAXIMUM, ID_DATATYPEEDITORDIRECTLYINITIALVALUE, 
    44  ID_DATATYPEEDITORSUBRANGEINITIALVALUE, ID_DATATYPEEDITORENUMERATEDPANEL,
   215  ID_DATATYPEEDITORSUBRANGEINITIALVALUE, ID_DATATYPEEDITORENUMERATEDPANEL,
    45  ID_DATATYPEEDITORENUMERATEDVALUES, ID_DATATYPEEDITORENUMERATEDINITIALVALUE,
   216  ID_DATATYPEEDITORENUMERATEDVALUES, ID_DATATYPEEDITORENUMERATEDINITIALVALUE,
    46  ID_DATATYPEEDITORARRAYPANEL, ID_DATATYPEEDITORARRAYBASETYPE, 
   217  ID_DATATYPEEDITORARRAYPANEL, ID_DATATYPEEDITORARRAYBASETYPE, 
    47  ID_DATATYPEEDITORARRAYDIMENSIONS, ID_DATATYPEEDITORARRAYINITIALVALUE, 
   218  ID_DATATYPEEDITORARRAYDIMENSIONS, ID_DATATYPEEDITORARRAYINITIALVALUE, 
       
   219  ID_DATATYPEEDITORSTRUCTUREPANEL, ID_DATATYPEEDITORSTRUCTUREELEMENTSGRID,
       
   220  ID_DATATYPEEDITORSTRUCTUREADDBUTTON, ID_DATATYPEEDITORSTRUCTUREDELETEBUTTON,
       
   221  ID_DATATYPEEDITORSTRUCTUREUPBUTTON, ID_DATATYPEEDITORSTRUCTUREDOWNBUTTON,
    48  ID_DATATYPEEDITORSTATICTEXT1, ID_DATATYPEEDITORSTATICTEXT2, 
   222  ID_DATATYPEEDITORSTATICTEXT1, ID_DATATYPEEDITORSTATICTEXT2, 
    49  ID_DATATYPEEDITORSTATICTEXT3, ID_DATATYPEEDITORSTATICTEXT4, 
   223  ID_DATATYPEEDITORSTATICTEXT3, ID_DATATYPEEDITORSTATICTEXT4, 
    50  ID_DATATYPEEDITORSTATICTEXT5, ID_DATATYPEEDITORSTATICTEXT6, 
   224  ID_DATATYPEEDITORSTATICTEXT5, ID_DATATYPEEDITORSTATICTEXT6, 
    51  ID_DATATYPEEDITORSTATICTEXT7, ID_DATATYPEEDITORSTATICTEXT8,
   225  ID_DATATYPEEDITORSTATICTEXT7, ID_DATATYPEEDITORSTATICTEXT8,
    52  ID_DATATYPEEDITORSTATICTEXT9, ID_DATATYPEEDITORSTATICTEXT10, 
   226  ID_DATATYPEEDITORSTATICTEXT9, ID_DATATYPEEDITORSTATICTEXT10, 
    53 ] = [wx.NewId() for _init_ctrls in range(28)]
   227  ID_DATATYPEEDITORSTATICTEXT11, 
       
   228 ] = [wx.NewId() for _init_ctrls in range(35)]
    54 
   229 
    55 class DataTypeEditor(wx.Panel):
   230 class DataTypeEditor(wx.Panel):
    56     
   231     
    57     def _init_coll_MainSizer_Items(self, parent):
   232     def _init_coll_MainSizer_Items(self, parent):
    58         parent.AddSizer(self.TopSizer, 0, border=5, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
   233         parent.AddSizer(self.TopSizer, 0, border=5, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
    69     def _init_coll_TypeInfosSizer_Items(self, parent):
   244     def _init_coll_TypeInfosSizer_Items(self, parent):
    70         parent.AddWindow(self.DirectlyPanel, 1, border=0, flag=wx.ALL)
   245         parent.AddWindow(self.DirectlyPanel, 1, border=0, flag=wx.ALL)
    71         parent.AddWindow(self.SubrangePanel, 1, border=0, flag=wx.ALL)
   246         parent.AddWindow(self.SubrangePanel, 1, border=0, flag=wx.ALL)
    72         parent.AddWindow(self.EnumeratedPanel, 1, border=0, flag=wx.GROW|wx.ALL)
   247         parent.AddWindow(self.EnumeratedPanel, 1, border=0, flag=wx.GROW|wx.ALL)
    73         parent.AddWindow(self.ArrayPanel, 1, border=0, flag=wx.ALL)
   248         parent.AddWindow(self.ArrayPanel, 1, border=0, flag=wx.ALL)
       
   249         parent.AddWindow(self.StructurePanel, 1, border=0, flag=wx.GROW|wx.ALL)
    74 
   250 
    75     def _init_coll_DirectlyPanelSizer_Items(self, parent):
   251     def _init_coll_DirectlyPanelSizer_Items(self, parent):
    76         parent.AddWindow(self.staticText2, 1, border=5, flag=wx.GROW|wx.ALL)
   252         parent.AddWindow(self.staticText2, 1, border=5, flag=wx.GROW|wx.ALL)
    77         parent.AddWindow(self.DirectlyBaseType, 1, border=5, flag=wx.GROW|wx.ALL)
   253         parent.AddWindow(self.DirectlyBaseType, 1, border=5, flag=wx.GROW|wx.ALL)
    78         parent.AddWindow(self.staticText3, 1, border=5, flag=wx.GROW|wx.ALL)
   254         parent.AddWindow(self.staticText3, 1, border=5, flag=wx.GROW|wx.ALL)
   111     
   287     
   112     def _init_coll_ArrayPanelRightSizer_Items(self, parent):
   288     def _init_coll_ArrayPanelRightSizer_Items(self, parent):
   113         parent.AddWindow(self.staticText10, 1, border=5, flag=wx.GROW|wx.ALL)
   289         parent.AddWindow(self.staticText10, 1, border=5, flag=wx.GROW|wx.ALL)
   114         parent.AddWindow(self.ArrayInitialValue, 1, border=5, flag=wx.GROW|wx.ALL)    
   290         parent.AddWindow(self.ArrayInitialValue, 1, border=5, flag=wx.GROW|wx.ALL)    
   115 
   291 
       
   292     def _init_coll_StructurePanelSizer_Items(self, parent):
       
   293         parent.AddWindow(self.staticText11, 0, border=5, flag=wx.GROW|wx.ALL)
       
   294         parent.AddWindow(self.StructureElementsGrid, 0, border=0, flag=wx.GROW)
       
   295         parent.AddSizer(self.StructurePanelButtonSizer, 0, border=0, flag=wx.ALIGN_RIGHT)
       
   296         
       
   297     def _init_coll_StructurePanelSizer_Growables(self, parent):
       
   298         parent.AddGrowableCol(0)
       
   299         parent.AddGrowableRow(1)
       
   300 
       
   301     def _init_coll_StructurePanelButtonSizer_Items(self, parent):
       
   302         parent.AddWindow(self.StructureAddButton, 1, border=5, flag=wx.GROW|wx.ALL)
       
   303         parent.AddWindow(self.StructureDeleteButton, 1, border=5, flag=wx.GROW|wx.ALL)
       
   304         parent.AddWindow(self.StructureUpButton, 1, border=5, flag=wx.GROW|wx.ALL)
       
   305         parent.AddWindow(self.StructureDownButton, 1, border=5, flag=wx.GROW|wx.ALL)
       
   306     
   116     def _init_sizers(self):
   307     def _init_sizers(self):
   117         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
   308         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
   118         self.TopSizer = wx.BoxSizer(wx.HORIZONTAL)
   309         self.TopSizer = wx.BoxSizer(wx.HORIZONTAL)
   119         self.TypeInfosSizer = wx.StaticBoxSizer(self.staticbox, wx.HORIZONTAL)
   310         self.TypeInfosSizer = wx.StaticBoxSizer(self.staticbox, wx.HORIZONTAL)
   120         self.DirectlyPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
   311         self.DirectlyPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
   121         self.SubrangePanelSizer = wx.GridSizer(cols=4, hgap=0, rows=3, vgap=0)
   312         self.SubrangePanelSizer = wx.GridSizer(cols=4, hgap=0, rows=3, vgap=0)
   122         self.EnumeratedPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
   313         self.EnumeratedPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
   123         self.ArrayPanelSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=2, vgap=0)
   314         self.ArrayPanelSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=2, vgap=0)
   124         self.ArrayPanelLeftSizer = wx.BoxSizer(wx.HORIZONTAL)
   315         self.ArrayPanelLeftSizer = wx.BoxSizer(wx.HORIZONTAL)
   125         self.ArrayPanelRightSizer = wx.BoxSizer(wx.HORIZONTAL)
   316         self.ArrayPanelRightSizer = wx.BoxSizer(wx.HORIZONTAL)
   126         
   317         self.StructurePanelSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=0)
       
   318         self.StructurePanelButtonSizer = wx.BoxSizer(wx.HORIZONTAL)
   127         self._init_coll_MainSizer_Items(self.MainSizer)
   319         self._init_coll_MainSizer_Items(self.MainSizer)
   128         self._init_coll_MainSizer_Growables(self.MainSizer)
   320         self._init_coll_MainSizer_Growables(self.MainSizer)
   129         self._init_coll_TopSizer_Items(self.TopSizer)
   321         self._init_coll_TopSizer_Items(self.TopSizer)
   130         self._init_coll_TypeInfosSizer_Items(self.TypeInfosSizer)
   322         self._init_coll_TypeInfosSizer_Items(self.TypeInfosSizer)
   131         self._init_coll_DirectlyPanelSizer_Items(self.DirectlyPanelSizer)
   323         self._init_coll_DirectlyPanelSizer_Items(self.DirectlyPanelSizer)
   133         self._init_coll_EnumeratedPanelSizer_Items(self.EnumeratedPanelSizer)
   325         self._init_coll_EnumeratedPanelSizer_Items(self.EnumeratedPanelSizer)
   134         self._init_coll_ArrayPanelSizer_Items(self.ArrayPanelSizer)
   326         self._init_coll_ArrayPanelSizer_Items(self.ArrayPanelSizer)
   135         self._init_coll_ArrayPanelSizer_Growables(self.ArrayPanelSizer)
   327         self._init_coll_ArrayPanelSizer_Growables(self.ArrayPanelSizer)
   136         self._init_coll_ArrayPanelLeftSizer_Items(self.ArrayPanelLeftSizer)
   328         self._init_coll_ArrayPanelLeftSizer_Items(self.ArrayPanelLeftSizer)
   137         self._init_coll_ArrayPanelRightSizer_Items(self.ArrayPanelRightSizer)
   329         self._init_coll_ArrayPanelRightSizer_Items(self.ArrayPanelRightSizer)
       
   330         self._init_coll_StructurePanelSizer_Items(self.StructurePanelSizer)
       
   331         self._init_coll_StructurePanelSizer_Growables(self.StructurePanelSizer)
       
   332         self._init_coll_StructurePanelButtonSizer_Items(self.StructurePanelButtonSizer)
   138         
   333         
   139         self.SetSizer(self.MainSizer)
   334         self.SetSizer(self.MainSizer)
   140         self.DirectlyPanel.SetSizer(self.DirectlyPanelSizer)
   335         self.DirectlyPanel.SetSizer(self.DirectlyPanelSizer)
   141         self.SubrangePanel.SetSizer(self.SubrangePanelSizer)
   336         self.SubrangePanel.SetSizer(self.SubrangePanelSizer)
   142         self.EnumeratedPanel.SetSizer(self.EnumeratedPanelSizer)
   337         self.EnumeratedPanel.SetSizer(self.EnumeratedPanelSizer)
   143         self.ArrayPanel.SetSizer(self.ArrayPanelSizer)
   338         self.ArrayPanel.SetSizer(self.ArrayPanelSizer)
       
   339         self.StructurePanel.SetSizer(self.StructurePanelSizer)
   144     
   340     
   145     def _init_ctrls(self, prnt):
   341     def _init_ctrls(self, prnt):
   146         wx.Panel.__init__(self, id=ID_DATATYPEEDITOR, name='', parent=prnt,
   342         wx.Panel.__init__(self, id=ID_DATATYPEEDITOR, name='', parent=prnt,
   147               size=wx.Size(0, 0), style=wx.SUNKEN_BORDER)
   343               size=wx.Size(0, 0), style=wx.SUNKEN_BORDER)
   148 
   344 
   280         self.ArrayInitialValue = wx.TextCtrl(id=ID_DATATYPEEDITORARRAYINITIALVALUE, 
   476         self.ArrayInitialValue = wx.TextCtrl(id=ID_DATATYPEEDITORARRAYINITIALVALUE, 
   281               name='ArrayInitialValue', parent=self.ArrayPanel, pos=wx.Point(0, 0),
   477               name='ArrayInitialValue', parent=self.ArrayPanel, pos=wx.Point(0, 0),
   282               size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.TE_MULTILINE|wx.TE_RICH)
   478               size=wx.Size(0, 24), style=wx.TAB_TRAVERSAL|wx.TE_PROCESS_ENTER|wx.TE_MULTILINE|wx.TE_RICH)
   283         self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, id=ID_DATATYPEEDITORARRAYINITIALVALUE)
   479         self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, id=ID_DATATYPEEDITORARRAYINITIALVALUE)
   284         
   480         
       
   481         # Panel for Structure data types
       
   482         
       
   483         self.StructurePanel = wx.Panel(id=ID_DATATYPEEDITORSTRUCTUREPANEL,
       
   484               name='StructurePanel', parent=self, pos=wx.Point(0, 0),
       
   485               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
       
   486         
       
   487         self.staticText11 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT11,
       
   488               label='Elements :', name='staticText11', parent=self.StructurePanel,
       
   489               pos=wx.Point(0, 0), size=wx.Size(150, 17), style=0)
       
   490 
       
   491         self.StructureElementsGrid = wx.grid.Grid(id=ID_DATATYPEEDITORSTRUCTUREELEMENTSGRID,
       
   492               name='StructureElementsGrid', parent=self.StructurePanel, pos=wx.Point(0, 0), 
       
   493               size=wx.Size(0, 150), style=wx.VSCROLL)
       
   494         self.StructureElementsGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
       
   495               'Sans'))
       
   496         self.StructureElementsGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
       
   497               False, 'Sans'))
       
   498         self.StructureElementsGrid.SetSelectionBackground(wx.WHITE)
       
   499         self.StructureElementsGrid.SetSelectionForeground(wx.BLACK)
       
   500         if wx.VERSION >= (2, 6, 0):
       
   501             self.StructureElementsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnStructureElementsGridCellChange)
       
   502             self.StructureElementsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnStructureElementsGridEditorShown)
       
   503         else:
       
   504             wx.grid.EVT_GRID_CELL_CHANGE(self.StructureElementsGrid, self.OnStructureElementsGridCellChange)
       
   505             wx.grid.EVT_GRID_EDITOR_SHOWN(self.StructureElementsGrid, self.OnStructureElementsGridEditorShown)
       
   506 
       
   507         self.StructureAddButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREADDBUTTON, label='Add',
       
   508               name='StructureAddButton', parent=self.StructurePanel, pos=wx.Point(0, 0),
       
   509               size=wx.Size(72, 32), style=0)
       
   510         self.Bind(wx.EVT_BUTTON, self.OnStructureAddButton, id=ID_DATATYPEEDITORSTRUCTUREADDBUTTON)
       
   511 
       
   512         self.StructureDeleteButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREDELETEBUTTON, label='Delete',
       
   513               name='StructureDeleteButton', parent=self.StructurePanel, pos=wx.Point(0, 0),
       
   514               size=wx.Size(72, 32), style=0)
       
   515         self.Bind(wx.EVT_BUTTON, self.OnStructureDeleteButton, id=ID_DATATYPEEDITORSTRUCTUREDELETEBUTTON)
       
   516 
       
   517         self.StructureUpButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREUPBUTTON, label='^',
       
   518               name='StructureUpButton', parent=self.StructurePanel, pos=wx.Point(0, 0),
       
   519               size=wx.Size(32, 32), style=0)
       
   520         self.Bind(wx.EVT_BUTTON, self.OnStructureUpButton, id=ID_DATATYPEEDITORSTRUCTUREUPBUTTON)
       
   521 
       
   522         self.StructureDownButton = wx.Button(id=ID_DATATYPEEDITORSTRUCTUREDOWNBUTTON, label='v',
       
   523               name='StructureDownButton', parent=self.StructurePanel, pos=wx.Point(0, 0),
       
   524               size=wx.Size(32, 32), style=0)
       
   525         self.Bind(wx.EVT_BUTTON, self.OnStructureDownButton, id=ID_DATATYPEEDITORSTRUCTUREDOWNBUTTON)
       
   526 
   285         self._init_sizers()
   527         self._init_sizers()
   286 
   528 
   287     def __init__(self, parent, tagname, window, controler):
   529     def __init__(self, parent, tagname, window, controler):
   288         self._init_ctrls(parent)
   530         self._init_ctrls(parent)
       
   531         
       
   532         self.StructureElementDefaultValue = {"Name" : "", "Type" : "INT", "Initial Value" : ""}
       
   533         self.StructureElementsTable = ElementsTable(self, [], ["#", "Name", "Type", "Initial Value"])
       
   534         self.StructureColSizes = [40, 150, 100, 250]
       
   535         self.StructureColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
       
   536         
       
   537         self.StructureElementsGrid.SetTable(self.StructureElementsTable)
       
   538         self.StructureElementsGrid.SetRowLabelSize(0)
       
   539         for col in range(self.StructureElementsTable.GetNumberCols()):
       
   540             attr = wx.grid.GridCellAttr()
       
   541             attr.SetAlignment(self.StructureColAlignements[col], wx.ALIGN_CENTRE)
       
   542             self.StructureElementsGrid.SetColAttr(col, attr)
       
   543             self.StructureElementsGrid.SetColSize(col, self.StructureColSizes[col])
   289         
   544         
   290         self.DerivationType.Append("Directly")
   545         self.DerivationType.Append("Directly")
   291         self.DerivationType.Append("Subrange")
   546         self.DerivationType.Append("Subrange")
   292         self.DerivationType.Append("Enumerated")
   547         self.DerivationType.Append("Enumerated")
   293         self.DerivationType.Append("Array")
   548         self.DerivationType.Append("Array")
       
   549         self.DerivationType.Append("Structure")
   294         self.SubrangePanel.Hide()
   550         self.SubrangePanel.Hide()
   295         self.EnumeratedPanel.Hide()
   551         self.EnumeratedPanel.Hide()
   296         self.ArrayPanel.Hide()
   552         self.ArrayPanel.Hide()
       
   553         self.StructurePanel.Hide()
   297         self.CurrentPanel = "Directly"
   554         self.CurrentPanel = "Directly"
   298         self.Errors = []
   555         self.Errors = []
   299         self.Initializing = False
   556         self.Initializing = False
   300         
   557         
   301         self.ParentWindow = window
   558         self.ParentWindow = window
   302         self.Controler = controler
   559         self.Controler = controler
   303         self.TagName = tagname
   560         self.TagName = tagname
   304     
       
   305     def OnEnumeratedValueEndEdit(self, event):
       
   306         text = event.GetText()
       
   307         values = self.EnumeratedValues.GetStrings()
       
   308         index = event.GetIndex()
       
   309         if index >= len(values) or values[index].upper() != text.upper():
       
   310             if text.upper() in [value.upper() for value in values]:
       
   311                 message = wx.MessageDialog(self, "\"%s\" value already defined!"%text, "Error", wx.OK|wx.ICON_ERROR)
       
   312                 message.ShowModal()
       
   313                 message.Destroy()
       
   314                 event.Veto()
       
   315             elif text.upper() in IEC_KEYWORDS:
       
   316                 message = wx.MessageDialog(self, "\"%s\" is a keyword. It can't be used!"%text, "Error", wx.OK|wx.ICON_ERROR)
       
   317                 message.ShowModal()
       
   318                 message.Destroy()
       
   319             else:
       
   320                 wx.CallAfter(self.RefreshEnumeratedValues)
       
   321                 wx.CallAfter(self.RefreshTypeInfos)
       
   322                 event.Skip()
       
   323         else:
       
   324             wx.CallAfter(self.RefreshEnumeratedValues)
       
   325             wx.CallAfter(self.RefreshTypeInfos)
       
   326             event.Skip()
       
   327     
       
   328     def OnEnumeratedValuesChanged(self, event):
       
   329         wx.CallAfter(self.RefreshEnumeratedValues)
       
   330         wx.CallAfter(self.RefreshTypeInfos)
       
   331         event.Skip()
       
   332     
   561     
   333     def SetTagName(self, tagname):
   562     def SetTagName(self, tagname):
   334         self.TagName = tagname
   563         self.TagName = tagname
   335         
   564         
   336     def GetTagName(self):
   565     def GetTagName(self):
   381                 self.EnumeratedInitialValue.SetStringSelection(type_infos["initial"])
   610                 self.EnumeratedInitialValue.SetStringSelection(type_infos["initial"])
   382             elif type_infos["type"] == "Array":
   611             elif type_infos["type"] == "Array":
   383                 self.ArrayBaseType.SetStringSelection(type_infos["base_type"])
   612                 self.ArrayBaseType.SetStringSelection(type_infos["base_type"])
   384                 self.ArrayDimensions.SetStrings(map(lambda x : "..".join(map(str, x)), type_infos["dimensions"]))
   613                 self.ArrayDimensions.SetStrings(map(lambda x : "..".join(map(str, x)), type_infos["dimensions"]))
   385                 self.ArrayInitialValue.SetValue(type_infos["initial"])
   614                 self.ArrayInitialValue.SetValue(type_infos["initial"])
       
   615             elif type_infos["type"] == "Structure":
       
   616                 self.StructureElementsTable.SetData(type_infos["elements"])
       
   617                 self.StructureElementsTable.ResetView(self.StructureElementsGrid)
   386             self.RefreshDisplayedInfos()
   618             self.RefreshDisplayedInfos()
   387         self.ShowErrors()
   619         self.ShowErrors()
   388         self.Initializing = False
   620         self.Initializing = False
   389 
   621 
   390     def RefreshScaling(self, refresh=True):
   622     def RefreshScaling(self, refresh=True):
   422         event.Skip()
   654         event.Skip()
   423 
   655 
   424     def OnDimensionsChanged(self, event):
   656     def OnDimensionsChanged(self, event):
   425         wx.CallAfter(self.RefreshTypeInfos)
   657         wx.CallAfter(self.RefreshTypeInfos)
   426         event.Skip()
   658         event.Skip()
       
   659 
       
   660     def OnEnumeratedValueEndEdit(self, event):
       
   661         text = event.GetText()
       
   662         values = self.EnumeratedValues.GetStrings()
       
   663         index = event.GetIndex()
       
   664         if index >= len(values) or values[index].upper() != text.upper():
       
   665             if text.upper() in [value.upper() for value in values]:
       
   666                 message = wx.MessageDialog(self, "\"%s\" value already defined!"%text, "Error", wx.OK|wx.ICON_ERROR)
       
   667                 message.ShowModal()
       
   668                 message.Destroy()
       
   669                 event.Veto()
       
   670             elif text.upper() in IEC_KEYWORDS:
       
   671                 message = wx.MessageDialog(self, "\"%s\" is a keyword. It can't be used!"%text, "Error", wx.OK|wx.ICON_ERROR)
       
   672                 message.ShowModal()
       
   673                 message.Destroy()
       
   674             else:
       
   675                 wx.CallAfter(self.RefreshEnumeratedValues)
       
   676                 wx.CallAfter(self.RefreshTypeInfos)
       
   677                 event.Skip()
       
   678         else:
       
   679             wx.CallAfter(self.RefreshEnumeratedValues)
       
   680             wx.CallAfter(self.RefreshTypeInfos)
       
   681             event.Skip()
       
   682     
       
   683     def OnEnumeratedValuesChanged(self, event):
       
   684         wx.CallAfter(self.RefreshEnumeratedValues)
       
   685         wx.CallAfter(self.RefreshTypeInfos)
       
   686         event.Skip()
       
   687     
       
   688     def OnStructureAddButton(self, event):
       
   689         new_row = self.StructureElementDefaultValue.copy()
       
   690         self.StructureElementsTable.AppendRow(new_row)
       
   691         self.RefreshTypeInfos()
       
   692         self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   693         event.Skip()
       
   694     
       
   695     def OnStructureDeleteButton(self, event):
       
   696         row = self.StructureElementsGrid.GetGridCursorRow()
       
   697         self.StructureElementsTable.RemoveRow(row)
       
   698         self.RefreshTypeInfos()
       
   699         self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   700         event.Skip()
       
   701     
       
   702     def OnStructureUpButton(self, event):
       
   703         row = self.StructureElementsGrid.GetGridCursorRow()
       
   704         new_index = self.StructureElementsTable.MoveRow(row, -1)
       
   705         if new_index is not None:
       
   706             self.RefreshTypeInfos()
       
   707             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   708             self.StructureElementsGrid.SetGridCursor(new_index, self.StructureElementsGrid.GetGridCursorCol())
       
   709         event.Skip()
       
   710     
       
   711     def OnStructureDownButton(self, event):
       
   712         row = self.StructureElementsGrid.GetGridCursorRow()
       
   713         new_index = self.StructureElementsTable.MoveRow(row, 1)
       
   714         if new_index is not None:
       
   715             self.RefreshTypeInfos()
       
   716             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   717             self.StructureElementsGrid.SetGridCursor(new_index, self.StructureElementsGrid.GetGridCursorCol())
       
   718         event.Skip()
       
   719 
       
   720     def OnStructureElementsGridCellChange(self, event):
       
   721         row, col = event.GetRow(), event.GetCol()
       
   722         colname = self.StructureElementsTable.GetColLabelValue(col)
       
   723         value = self.StructureElementsTable.GetValue(row, col)
       
   724         if colname == "Name":
       
   725             if not TestIdentifier(value):
       
   726                 message = wx.MessageDialog(self, "\"%s\" is not a valid identifier!"%value, "Error", wx.OK|wx.ICON_ERROR)
       
   727                 message.ShowModal()
       
   728                 message.Destroy()
       
   729                 event.Veto()
       
   730             elif value.upper() in IEC_KEYWORDS:
       
   731                 message = wx.MessageDialog(self, "\"%s\" is a keyword. It can't be used!"%value, "Error", wx.OK|wx.ICON_ERROR)
       
   732                 message.ShowModal()
       
   733                 message.Destroy()
       
   734                 event.Veto()
       
   735 ##            elif value.upper() in self.PouNames:
       
   736 ##                message = wx.MessageDialog(self, "A pou with \"%s\" as name exists!"%value, "Error", wx.OK|wx.ICON_ERROR)
       
   737 ##                message.ShowModal()
       
   738 ##                message.Destroy()
       
   739 ##                event.Veto()
       
   740             elif value.upper() in [var["Name"].upper() for idx, var in enumerate(self.StructureElementsTable.GetData()) if idx != row]:
       
   741                 message = wx.MessageDialog(self, "A element with \"%s\" as name exists in this structure!"%value, "Error", wx.OK|wx.ICON_ERROR)
       
   742                 message.ShowModal()
       
   743                 message.Destroy()
       
   744                 event.Veto()
       
   745             else:
       
   746                 self.RefreshTypeInfos()
       
   747                 self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   748 ##                old_value = self.Table.GetOldValue()
       
   749 ##                if old_value != "":
       
   750 ##                    self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_value, value)
       
   751 ##                self.Controler.BufferProject()
       
   752                 event.Skip()
       
   753         else:
       
   754             self.RefreshTypeInfos()
       
   755             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   756             event.Skip()
       
   757     
       
   758     def OnStructureElementsGridEditorShown(self, event):
       
   759         row, col = event.GetRow(), event.GetCol() 
       
   760         if self.StructureElementsTable.GetColLabelValue(col) == "Type":
       
   761             type_menu = wx.Menu(title='')
       
   762             base_menu = wx.Menu(title='')
       
   763             for base_type in self.Controler.GetBaseTypes():
       
   764                 new_id = wx.NewId()
       
   765                 AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
       
   766                 self.Bind(wx.EVT_MENU, self.GetElementTypeFunction(base_type), id=new_id)
       
   767             type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
       
   768             datatype_menu = wx.Menu(title='')
       
   769             for datatype in self.Controler.GetDataTypes(self.TagName, False, self.ParentWindow.Debug):
       
   770                 new_id = wx.NewId()
       
   771                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
       
   772                 self.Bind(wx.EVT_MENU, self.GetElementTypeFunction(datatype), id=new_id)
       
   773             type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
       
   774 ##            functionblock_menu = wx.Menu(title='')
       
   775 ##            bodytype = self.Controler.GetEditedElementBodyType(self.TagName, self.ParentWindow.Debug)
       
   776 ##            pouname, poutype = self.Controler.GetEditedElementType(self.TagName, self.ParentWindow.Debug)
       
   777 ##            if classtype in ["Input","Output","InOut","External","Global"] or poutype != "function" and bodytype in ["ST", "IL"]:
       
   778 ##                for functionblock_type in self.Controler.GetFunctionBlockTypes(self.TagName, self.ParentWindow.Debug):
       
   779 ##                    new_id = wx.NewId()
       
   780 ##                    AppendMenu(functionblock_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=functionblock_type)
       
   781 ##                    self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(functionblock_type), id=new_id)
       
   782 ##                type_menu.AppendMenu(wx.NewId(), "Function Block Types", functionblock_menu)
       
   783             rect = self.StructureElementsGrid.BlockToDeviceRect((row, col), (row, col))
       
   784             self.StructureElementsGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.StructureElementsGrid.GetColLabelSize())
       
   785             event.Veto()
       
   786         else:
       
   787             event.Skip()
       
   788 
       
   789     def GetElementTypeFunction(self, base_type):
       
   790         def ElementTypeFunction(event):
       
   791             row = self.StructureElementsGrid.GetGridCursorRow()
       
   792             self.StructureElementsTable.SetValueByName(row, "Type", base_type)
       
   793             self.RefreshTypeInfos()
       
   794             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
       
   795             event.Skip()
       
   796         return ElementTypeFunction
   427 
   797 
   428     def RefreshDisplayedInfos(self):
   798     def RefreshDisplayedInfos(self):
   429         selected = self.DerivationType.GetStringSelection()
   799         selected = self.DerivationType.GetStringSelection()
   430         if selected != self.CurrentPanel:
   800         if selected != self.CurrentPanel:
   431             if self.CurrentPanel == "Directly":
   801             if self.CurrentPanel == "Directly":
   434                 self.SubrangePanel.Hide()
   804                 self.SubrangePanel.Hide()
   435             elif self.CurrentPanel == "Enumerated":
   805             elif self.CurrentPanel == "Enumerated":
   436                 self.EnumeratedPanel.Hide()
   806                 self.EnumeratedPanel.Hide()
   437             elif self.CurrentPanel == "Array":
   807             elif self.CurrentPanel == "Array":
   438                 self.ArrayPanel.Hide()
   808                 self.ArrayPanel.Hide()
       
   809             elif self.CurrentPanel == "Structure":
       
   810                 self.StructurePanel.Hide()
   439             self.CurrentPanel = selected
   811             self.CurrentPanel = selected
   440             if selected == "Directly":
   812             if selected == "Directly":
   441                 self.DirectlyPanel.Show()
   813                 self.DirectlyPanel.Show()
   442             elif selected == "Subrange":
   814             elif selected == "Subrange":
   443                 self.SubrangePanel.Show()
   815                 self.SubrangePanel.Show()
   444             elif selected == "Enumerated":
   816             elif selected == "Enumerated":
   445                 self.EnumeratedPanel.Show()
   817                 self.EnumeratedPanel.Show()
   446             elif selected == "Array":
   818             elif selected == "Array":
   447                 self.ArrayPanel.Show()
   819                 self.ArrayPanel.Show()
       
   820             elif selected == "Structure":
       
   821                 self.StructurePanel.Show()
   448             self.MainSizer.Layout()
   822             self.MainSizer.Layout()
   449 
   823 
   450     def RefreshEnumeratedValues(self):
   824     def RefreshEnumeratedValues(self):
   451         selected = self.EnumeratedInitialValue.GetStringSelection()
   825         selected = self.EnumeratedInitialValue.GetStringSelection()
   452         self.EnumeratedInitialValue.Clear()
   826         self.EnumeratedInitialValue.Clear()
   503                     message.Destroy()
   877                     message.Destroy()
   504                     self.RefreshView()
   878                     self.RefreshView()
   505                     return
   879                     return
   506                 infos["dimensions"].append(map(int, bounds))
   880                 infos["dimensions"].append(map(int, bounds))
   507             infos["initial"] = self.ArrayInitialValue.GetValue()
   881             infos["initial"] = self.ArrayInitialValue.GetValue()
       
   882         elif selected == "Structure":
       
   883             infos["elements"] = self.StructureElementsTable.GetData()
       
   884             infos["initial"] = ""
   508         self.Controler.SetDataTypeInfos(self.TagName, infos)
   885         self.Controler.SetDataTypeInfos(self.TagName, infos)
   509         self.ParentWindow.RefreshTitle()
   886         self.ParentWindow.RefreshTitle()
   510         self.ParentWindow.RefreshEditMenu()
   887         self.ParentWindow.RefreshEditMenu()
   511 
   888 
   512 #-------------------------------------------------------------------------------
   889 #-------------------------------------------------------------------------------