Adding support for unifying grid table control elements
authorlaurent
Wed, 14 Dec 2011 15:17:22 +0100
changeset 604 5b42b4401e6b
parent 603 25c92309cdae
child 605 279c16d017f3
Adding support for unifying grid table control elements
DataTypeEditor.py
PLCOpenEditor.py
RessourceEditor.py
controls/CustomTable.py
controls/VariablePanel.py
controls/__init__.py
dialogs/ActionBlockDialog.py
--- a/DataTypeEditor.py	Wed Dec 14 15:13:36 2011 +0100
+++ b/DataTypeEditor.py	Wed Dec 14 15:17:22 2011 +0100
@@ -27,7 +27,7 @@
 
 from plcopen.structures import IEC_KEYWORDS, TestIdentifier
 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD
-from controls import CustomEditableListBox, CustomGrid, EditorPanel
+from controls import CustomEditableListBox, CustomGrid, CustomTable, EditorPanel
 
 import re
 
@@ -47,40 +47,16 @@
     _ = lambda x : x
     return ["#", _("Name"), _("Type"), _("Initial Value")]
 
-class ElementsTable(wx.grid.PyGridTableBase):
+class ElementsTable(CustomTable):
     
     """
     A custom wx.grid.Grid Table using user supplied data
     """
     def __init__(self, parent, data, colnames):
         # The base class must be initialized *first*
-        wx.grid.PyGridTableBase.__init__(self)
-        self.data = data
+        CustomTable.__init__(self, parent, data, colnames)
         self.old_value = None
-        self.colnames = colnames
-        self.Highlights = {}
-        self.Parent = parent
-        # XXX
-        # we need to store the row length and collength to
-        # see if the table has changed size
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-    
-    def GetNumberCols(self):
-        return len(self.colnames)
-        
-    def GetNumberRows(self):
-        return len(self.data)
-
-    def GetColLabelValue(self, col, translate=True):
-        if col < len(self.colnames):
-            if translate:
-                return _(self.colnames[col])
-            return self.colnames[col]
-
-    def GetRowLabelValues(self, row, translate=True):
-        return row
-
+        
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             if col == 0:
@@ -95,51 +71,9 @@
                 self.old_value = self.data[row][colname]
             self.data[row][colname] = value
     
-    def GetValueByName(self, row, colname):
-        if row < self.GetNumberRows():
-            return self.data[row].get(colname)
-
-    def SetValueByName(self, row, colname, value):
-        if row < self.GetNumberRows():
-            self.data[row][colname] = value
-
     def GetOldValue(self):
         return self.old_value
     
-    def ResetView(self, grid):
-        """
-        (wx.grid.Grid) -> Reset the grid view.   Call this to
-        update the grid if rows and columns have been added or deleted
-        """
-        grid.BeginBatch()
-        for current, new, delmsg, addmsg in [
-            (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
-            (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
-        ]:
-            if new < current:
-                msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
-                grid.ProcessTableMessage(msg)
-            elif new > current:
-                msg = wx.grid.GridTableMessage(self,addmsg,new-current)
-                grid.ProcessTableMessage(msg)
-                self.UpdateValues(grid)
-        grid.EndBatch()
-
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-        # update the column rendering scheme
-        self._updateColAttrs(grid)
-
-        # update the scrollbars and the displayed part of the grid
-        grid.AdjustScrollbars()
-        grid.ForceRefresh()
-
-    def UpdateValues(self, grid):
-        """Update all displayed values"""
-        # This sends an event to the grid table to update all of the values
-        msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
-        grid.ProcessTableMessage(msg)
-
     def _updateColAttrs(self, grid):
         """
         wx.grid.Grid -> update the column attributes to add the
@@ -173,40 +107,8 @@
                 highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
                 grid.SetCellTextColour(row, col, highlight_colours[1])
-            if wx.Platform == '__WXMSW__':
-                grid.SetRowMinimalHeight(row, 20)
-            else:
-                grid.SetRowMinimalHeight(row, 28)
-            grid.AutoSizeRow(row, False)
-    
-    def SetData(self, data):
-        self.data = data
-    
-    def GetData(self):
-        return self.data
-    
-    def AppendRow(self, row_content):
-        self.data.append(row_content)
-
-    def InsertRow(self, row_index, row_content):
-        self.data.insert(row_index, row_content)
-
-    def RemoveRow(self, row_index):
-        self.data.pop(row_index)
-
-    def MoveRow(self, idx, move):
-        new_idx = max(0, min(idx + move, len(self.data) - 1))
-        if new_idx != idx:
-            self.data.insert(new_idx, self.data.pop(idx))
-        return new_idx
-        
-    def GetRow(self, row_index):
-        return self.data[row_index]
-
-    def Empty(self):
-        self.data = []
-        self.editors = []
-
+            self.ResizeRow(grid, row)
+    
     def AddHighlight(self, infos, highlight_type):
         row_highlights = self.Highlights.setdefault(infos[0], {})
         if infos[1] == "initial":
@@ -215,18 +117,6 @@
             col_highlights = row_highlights.setdefault(infos[1], [])
         col_highlights.append(highlight_type)
 
-    def ClearHighlights(self, highlight_type=None):
-        if highlight_type is None:
-            self.Highlights = {}
-        else:
-            for row, row_highlights in self.Highlights.iteritems():
-                row_items = row_highlights.items()
-                for col, col_highlights in row_items:
-                    if highlight_type in col_highlights:
-                        col_highlights.remove(highlight_type)
-                    if len(col_highlights) == 0:
-                        row_highlights.pop(col)
-
 #-------------------------------------------------------------------------------
 #                          Datatype Editor class
 #-------------------------------------------------------------------------------
--- a/PLCOpenEditor.py	Wed Dec 14 15:13:36 2011 +0100
+++ b/PLCOpenEditor.py	Wed Dec 14 15:17:22 2011 +0100
@@ -113,9 +113,8 @@
 from RessourceEditor import *
 from DataTypeEditor import *
 from PLCControler import *
-from controls.VariablePanel import VariablePanel
 from SearchResultPanel import SearchResultPanel
-from controls import CustomGrid
+from controls import CustomGrid, CustomTable
 
 # Define PLCOpenEditor controls id
 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, 
@@ -3845,38 +3844,8 @@
     def GetValue(self):
         return self.Value
 
-class DebugVariableTable(wx.grid.PyGridTableBase):
-    
-    """
-    A custom wx.grid.Grid Table using user supplied data
-    """
-    def __init__(self, parent, data, colnames):
-        # The base class must be initialized *first*
-        wx.grid.PyGridTableBase.__init__(self)
-        self.data = data
-        self.colnames = colnames
-        self.Parent = parent
-        # XXX
-        # we need to store the row length and collength to
-        # see if the table has changed size
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-    
-    def GetNumberCols(self):
-        return len(self.colnames)
-        
-    def GetNumberRows(self):
-        return len(self.data)
-
-    def GetColLabelValue(self, col, translate=True):
-        if col < len(self.colnames):
-            if translate:
-                return _(self.colnames[col])
-            return self.colnames[col]
-
-    def GetRowLabelValues(self, row, translate=True):
-        return row
-
+class DebugVariableTable(CustomTable):
+    
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             return self.GetValueByName(row, self.GetColLabelValue(col, False))
@@ -3906,40 +3875,6 @@
             return self.data[row].IsForced()
         return False
     
-    def ResetView(self, grid):
-        """
-        (wx.grid.Grid) -> Reset the grid view.   Call this to
-        update the grid if rows and columns have been added or deleted
-        """
-        grid.BeginBatch()
-        for current, new, delmsg, addmsg in [
-            (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
-            (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
-        ]:
-            if new < current:
-                msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
-                grid.ProcessTableMessage(msg)
-            elif new > current:
-                msg = wx.grid.GridTableMessage(self,addmsg,new-current)
-                grid.ProcessTableMessage(msg)
-                self.UpdateValues(grid)
-        grid.EndBatch()
-
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-        # update the column rendering scheme
-        self._updateColAttrs(grid)
-
-        # update the scrollbars and the displayed part of the grid
-        grid.AdjustScrollbars()
-        grid.ForceRefresh()
-
-    def UpdateValues(self, grid):
-        """Update all displayed values"""
-        # This sends an event to the grid table to update all of the values
-        msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
-        grid.ProcessTableMessage(msg)
-
     def _updateColAttrs(self, grid):
         """
         wx.grid.Grid -> update the column attributes to add the
@@ -3956,13 +3891,8 @@
                     else:
                         grid.SetCellTextColour(row, col, wx.BLACK)
                 grid.SetReadOnly(row, col, True)
+            self.ResizeRow(grid, row)
                 
-    def SetData(self, data):
-        self.data = data
-    
-    def GetData(self):
-        return self.data
-    
     def AppendItem(self, data):
         self.data.append(data)
     
@@ -3978,9 +3908,7 @@
     def GetItem(self, idx):
         return self.data[idx]
 
-    def Empty(self):
-        self.data = []
-    
+
 class DebugVariableDropTarget(wx.TextDropTarget):
     
     def __init__(self, parent):
--- a/RessourceEditor.py	Wed Dec 14 15:13:36 2011 +0100
+++ b/RessourceEditor.py	Wed Dec 14 15:17:22 2011 +0100
@@ -26,7 +26,7 @@
 import wx.grid
 
 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD
-from controls import CustomGrid, EditorPanel, DurationCellEditor
+from controls import CustomGrid, CustomTable, EditorPanel, DurationCellEditor
 
 #-------------------------------------------------------------------------------
 #                          Configuration Editor class
@@ -74,27 +74,17 @@
     _ = lambda x : x
     return [_("Name"), _("Type"), _("Task")]
 
-class ResourceTable(wx.grid.PyGridTableBase):
+class ResourceTable(CustomTable):
     
     """
     A custom wx.grid.Grid Table using user supplied data
     """
     def __init__(self, parent, data, colnames):
         # The base class must be initialized *first*
-        wx.grid.PyGridTableBase.__init__(self)
-        self.data = data
-        self.colnames = colnames
-        self.Highlights = {}
-        self.Parent = parent
-        
+        CustomTable.__init__(self, parent, data, colnames)
         self.ColAlignements = []
         self.ColSizes = []
-        # XXX
-        # we need to store the row length and collength to
-        # see if the table has changed size
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-    
+        
     def GetColAlignements(self):
         return self.ColAlignements
     
@@ -107,21 +97,6 @@
     def SetColSizes(self, list):
         self.ColSizes = list
 
-    def GetNumberCols(self):
-        return len(self.colnames)
-        
-    def GetNumberRows(self):
-        return len(self.data)
-
-    def GetColLabelValue(self, col, translate=True):
-        if col < len(self.colnames):
-            if translate:
-                return _(self.colnames[col])
-            return self.colnames[col]
-
-    def GetRowLabelValues(self, row, translate=True):
-        return row
-
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             colname = self.GetColLabelValue(col, False)
@@ -130,9 +105,6 @@
                 return _(value)
             return value
         
-    def GetValueByName(self, row, colname):
-        return self.data[row].get(colname)
-
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
             colname = self.GetColLabelValue(col, False)
@@ -140,44 +112,6 @@
                 value = TASKTRIGGERINGOPTIONS_DICT[value]
             self.data[row][colname] = value
     
-    def SetValueByName(self, row, colname, value):
-        if colname in self.colnames:
-            self.data[row][colname] = value
-    
-    def ResetView(self, grid):
-        """
-        (wx.grid.Grid) -> Reset the grid view.   Call this to
-        update the grid if rows and columns have been added or deleted
-        """
-        grid.BeginBatch()
-        for current, new, delmsg, addmsg in [
-            (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
-            (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
-        ]:
-            if new < current:
-                msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
-                grid.ProcessTableMessage(msg)
-            elif new > current:
-                msg = wx.grid.GridTableMessage(self,addmsg,new-current)
-                grid.ProcessTableMessage(msg)
-                self.UpdateValues(grid)
-        grid.EndBatch()
-
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-        # update the column rendering scheme
-        self._updateColAttrs(grid)
-
-        # update the scrollbars and the displayed part of the grid
-        grid.AdjustScrollbars()
-        grid.ForceRefresh()
-
-    def UpdateValues(self, grid):
-        """Update all displayed values"""
-        # This sends an event to the grid table to update all of the values
-        msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
-        grid.ProcessTableMessage(msg)
-
     def _updateColAttrs(self, grid):
         """
         wx.grid.Grid -> update the column attributes to add the
@@ -231,41 +165,8 @@
                 highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
                 grid.SetCellTextColour(row, col, highlight_colours[1])
-            if wx.Platform == '__WXMSW__':
-                grid.SetRowMinimalHeight(row, 20)
-            else:
-                grid.SetRowMinimalHeight(row, 28)
-            grid.AutoSizeRow(row, False)
-    
-    def SetData(self, data):
-        self.data = data
-    
-    def GetData(self):
-        return self.data
-    
-    def GetCurrentIndex(self):
-        return self.CurrentIndex
-    
-    def SetCurrentIndex(self, index):
-        self.CurrentIndex = index
-    
-    def AppendRow(self, row_content):
-        self.data.append(row_content)
-
-    def InsertRow(self, index, row_content):
-        self.data.insert(index, row_content)
-
-    def RemoveRow(self, row_index):
-        self.data.pop(row_index)
-        
-    def MoveRow(self, row_index, move):
-        new_index = max(0, min(row_index + move, len(self.data) - 1))
-        if new_index != row_index:
-            self.data.insert(new_index, self.data.pop(row_index))
-        return new_index
-        
-    def Empty(self):
-        self.data = []
+            self.ResizeRow(grid, row)
+
     
 #-------------------------------------------------------------------------------
 #                        Highlights showing functions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/controls/CustomTable.py	Wed Dec 14 15:17:22 2011 +0100
@@ -0,0 +1,175 @@
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx
+import wx.grid
+
+class CustomTable(wx.grid.PyGridTableBase):
+    
+    """
+    A custom wx.grid.Grid Table using user supplied data
+    """
+    def __init__(self, parent, data, colnames):
+        # The base class must be initialized *first*
+        wx.grid.PyGridTableBase.__init__(self)
+        self.data = data
+        self.colnames = colnames
+        self.Highlights = {}
+        self.Parent = parent
+        # XXX
+        # we need to store the row length and collength to
+        # see if the table has changed size
+        self._rows = self.GetNumberRows()
+        self._cols = self.GetNumberCols()
+    
+    def GetNumberCols(self):
+        return len(self.colnames)
+        
+    def GetNumberRows(self):
+        return len(self.data)
+
+    def GetColLabelValue(self, col, translate=True):
+        if col < len(self.colnames):
+            if translate:
+                return _(self.colnames[col])
+            return self.colnames[col]
+
+    def GetRowLabelValue(self, row, translate=True):
+        return row
+
+    def GetValue(self, row, col):
+        if row < self.GetNumberRows():
+            return self.data[row].get(self.GetColLabelValue(col, False), "")
+    
+    def SetValue(self, row, col, value):
+        if col < len(self.colnames):
+            self.data[row][self.GetColLabelValue(col, False)] = value
+    
+    def GetValueByName(self, row, colname):
+        if row < self.GetNumberRows():
+            return self.data[row].get(colname)
+
+    def SetValueByName(self, row, colname, value):
+        if row < self.GetNumberRows():
+            self.data[row][colname] = value
+
+    def ResetView(self, grid):
+        """
+        (wx.grid.Grid) -> Reset the grid view.   Call this to
+        update the grid if rows and columns have been added or deleted
+        """
+        grid.BeginBatch()
+        for current, new, delmsg, addmsg in [
+            (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
+            (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
+        ]:
+            if new < current:
+                msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
+                grid.ProcessTableMessage(msg)
+            elif new > current:
+                msg = wx.grid.GridTableMessage(self,addmsg,new-current)
+                grid.ProcessTableMessage(msg)
+                self.UpdateValues(grid)
+        grid.EndBatch()
+
+        self._rows = self.GetNumberRows()
+        self._cols = self.GetNumberCols()
+        # update the column rendering scheme
+        self._updateColAttrs(grid)
+
+        # update the scrollbars and the displayed part of the grid
+        grid.AdjustScrollbars()
+        grid.ForceRefresh()
+
+    def UpdateValues(self, grid):
+        """Update all displayed values"""
+        # This sends an event to the grid table to update all of the values
+        msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
+        grid.ProcessTableMessage(msg)
+
+    def _updateColAttrs(self, grid):
+        """
+        wx.grid.Grid -> update the column attributes to add the
+        appropriate renderer given the column name.
+
+        Otherwise default to the default renderer.
+        """
+        for row in range(self.GetNumberRows()):
+            row_highlights = self.Highlights.get(row, {})
+            for col in range(self.GetNumberCols()):
+                grid.SetReadOnly(row, col, True)
+                grid.SetCellEditor(row, col, None)
+                grid.SetCellRenderer(row, col, None)
+                
+                highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
+                grid.SetCellBackgroundColour(row, col, highlight_colours[0])
+                grid.SetCellTextColour(row, col, highlight_colours[1])
+            self.ResizeRow(grid, row)
+    
+    def ResizeRow(self, grid, row):
+        if wx.Platform == '__WXMSW__':
+            grid.SetRowMinimalHeight(row, 20)
+        else:
+            grid.SetRowMinimalHeight(row, 28)
+        grid.AutoSizeRow(row, False)
+    
+    def SetData(self, data):
+        self.data = data
+    
+    def GetData(self):
+        return self.data
+    
+    def GetCurrentIndex(self):
+        return self.CurrentIndex
+    
+    def SetCurrentIndex(self, index):
+        self.CurrentIndex = index
+    
+    def AppendRow(self, row_content):
+        self.data.append(row_content)
+
+    def InsertRow(self, index, row_content):
+        self.data.insert(index, row_content)
+
+    def MoveRow(self, row_index, move):
+        new_index = max(0, min(row_index + move, len(self.data) - 1))
+        if new_index != row_index:
+            self.data.insert(new_index, self.data.pop(row_index))
+        return new_index
+
+    def RemoveRow(self, row_index):
+        self.data.pop(row_index)
+
+    def GetRow(self, row_index):
+        return self.data[row_index]
+
+    def Empty(self):
+        self.data = []
+
+    def AddHighlight(self, infos, highlight_type):
+        row_highlights = self.Highlights.setdefault(infos[0], {})
+        col_highlights = row_highlights.setdefault(infos[1], [])
+        col_highlights.append(highlight_type)
+
+    def ClearHighlights(self, highlight_type=None):
+        if highlight_type is None:
+            self.Highlights = {}
+        else:
+            for row, row_highlights in self.Highlights.iteritems():
+                row_items = row_highlights.items()
+                for col, col_highlights in row_items:
+                    if highlight_type in col_highlights:
+                        col_highlights.remove(highlight_type)
+                    if len(col_highlights) == 0:
+                        row_highlights.pop(col)
--- a/controls/VariablePanel.py	Wed Dec 14 15:13:36 2011 +0100
+++ b/controls/VariablePanel.py	Wed Dec 14 15:17:22 2011 +0100
@@ -31,6 +31,7 @@
 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD
 from dialogs.ArrayTypeDialog import ArrayTypeDialog
 from CustomGrid import CustomGrid
+from CustomTable import CustomTable
 from LocationCellEditor import LocationCellEditor
 
 # Compatibility function for wx versions < 2.6
@@ -84,40 +85,16 @@
                        "External": lambda x: {"Constant": "Constant"}.get(x, "")
                       }
 
-class VariableTable(wx.grid.PyGridTableBase):
+class VariableTable(CustomTable):
     
     """
     A custom wx.grid.Grid Table using user supplied data
     """
     def __init__(self, parent, data, colnames):
         # The base class must be initialized *first*
-        wx.grid.PyGridTableBase.__init__(self)
-        self.data = data
+        CustomTable.__init__(self, parent, data, colnames)
         self.old_value = None
-        self.colnames = colnames
-        self.Highlights = {}
-        self.Parent = parent
-        # XXX
-        # we need to store the row length and collength to
-        # see if the table has changed size
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-    
-    def GetNumberCols(self):
-        return len(self.colnames)
-        
-    def GetNumberRows(self):
-        return len(self.data)
-
-    def GetColLabelValue(self, col, translate=True):
-        if col < len(self.colnames):
-            if translate:
-                return _(self.colnames[col])
-            return self.colnames[col]
-
-    def GetRowLabelValues(self, row, translate=True):
-        return row
-
+    
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             if col == 0:
@@ -146,51 +123,9 @@
             elif colname == "Option":
                 value = OPTIONS_DICT[value]
             self.data[row][colname] = value
-    
-    def GetValueByName(self, row, colname):
-        if row < self.GetNumberRows():
-            return self.data[row].get(colname)
-
-    def SetValueByName(self, row, colname, value):
-        if row < self.GetNumberRows():
-            self.data[row][colname] = value
 
     def GetOldValue(self):
         return self.old_value
-    
-    def ResetView(self, grid):
-        """
-        (wx.grid.Grid) -> Reset the grid view.   Call this to
-        update the grid if rows and columns have been added or deleted
-        """
-        grid.BeginBatch()
-        for current, new, delmsg, addmsg in [
-            (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
-            (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
-        ]:
-            if new < current:
-                msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
-                grid.ProcessTableMessage(msg)
-            elif new > current:
-                msg = wx.grid.GridTableMessage(self,addmsg,new-current)
-                grid.ProcessTableMessage(msg)
-                self.UpdateValues(grid)
-        grid.EndBatch()
-
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-        # update the column rendering scheme
-        self._updateColAttrs(grid)
-
-        # update the scrollbars and the displayed part of the grid
-        grid.AdjustScrollbars()
-        grid.ForceRefresh()
-
-    def UpdateValues(self, grid):
-        """Update all displayed values"""
-        # This sends an event to the grid table to update all of the values
-        msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
-        grid.ProcessTableMessage(msg)
 
     def _updateColAttrs(self, grid):
         """
@@ -263,53 +198,7 @@
                 highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
                 grid.SetCellTextColour(row, col, highlight_colours[1])
-            if wx.Platform == '__WXMSW__':
-                grid.SetRowMinimalHeight(row, 20)
-            else:
-                grid.SetRowMinimalHeight(row, 28)
-            grid.AutoSizeRow(row, False)
-    
-    def SetData(self, data):
-        self.data = data
-    
-    def GetData(self):
-        return self.data
-    
-    def GetCurrentIndex(self):
-        return self.CurrentIndex
-    
-    def SetCurrentIndex(self, index):
-        self.CurrentIndex = index
-    
-    def AppendRow(self, row_content):
-        self.data.append(row_content)
-
-    def RemoveRow(self, row_index):
-        self.data.pop(row_index)
-
-    def GetRow(self, row_index):
-        return self.data[row_index]
-
-    def Empty(self):
-        self.data = []
-        self.editors = []
-
-    def AddHighlight(self, infos, highlight_type):
-        row_highlights = self.Highlights.setdefault(infos[0], {})
-        col_highlights = row_highlights.setdefault(infos[1], [])
-        col_highlights.append(highlight_type)
-
-    def ClearHighlights(self, highlight_type=None):
-        if highlight_type is None:
-            self.Highlights = {}
-        else:
-            for row, row_highlights in self.Highlights.iteritems():
-                row_items = row_highlights.items()
-                for col, col_highlights in row_items:
-                    if highlight_type in col_highlights:
-                        col_highlights.remove(highlight_type)
-                    if len(col_highlights) == 0:
-                        row_highlights.pop(col)
+            self.ResizeRow(grid, row)
                     
 
 class VariableDropTarget(wx.TextDropTarget):
--- a/controls/__init__.py	Wed Dec 14 15:13:36 2011 +0100
+++ b/controls/__init__.py	Wed Dec 14 15:17:22 2011 +0100
@@ -26,7 +26,8 @@
 
 from CustomEditableListBox import CustomEditableListBox
 from CustomGrid import CustomGrid
+from CustomTable import CustomTable
 from EditorPanel import EditorPanel
 from DurationCellEditor import DurationCellEditor
 from LocationCellEditor import LocationCellEditor
-from VariablePanel import VariablePanel
\ No newline at end of file
+from VariablePanel import VariablePanel
--- a/dialogs/ActionBlockDialog.py	Wed Dec 14 15:13:36 2011 +0100
+++ b/dialogs/ActionBlockDialog.py	Wed Dec 14 15:17:22 2011 +0100
@@ -24,7 +24,7 @@
 import wx
 import wx.grid
 
-from controls import CustomGrid
+from controls import CustomGrid, CustomTable
 
 #-------------------------------------------------------------------------------
 #                            Action Block Dialog
@@ -38,39 +38,8 @@
     _ = lambda x: x
     return [_("Action"), _("Variable"), _("Inline")]
 
-class ActionTable(wx.grid.PyGridTableBase):
-    
-    """
-    A custom wx.Grid Table using user supplied data
-    """
-    def __init__(self, parent, data, colnames):
-        # The base class must be initialized *first*
-        wx.grid.PyGridTableBase.__init__(self)
-        self.data = data
-        self.colnames = colnames
-        self.Parent = parent
-        # XXX
-        # we need to store the row length and collength to
-        # see if the table has changed size
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-    
-    def GetNumberCols(self):
-        return len(self.colnames)
-        
-    def GetNumberRows(self):
-        return len(self.data)
-
-    def GetColLabelValue(self, col, translate=True):
-        if col < len(self.colnames):
-            colname = self.colnames[col]
-            if translate:
-                return _(colname)
-        return colname
-
-    def GetRowLabelValues(self, row, translate=True):
-        return row
-
+class ActionTable(CustomTable):
+    
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
             colname = self.GetColLabelValue(col, False)
@@ -79,9 +48,6 @@
                 return _(name)
             return name
     
-    def GetValueByName(self, row, colname):
-        return self.data[row].get(colname)
-
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
             colname = self.GetColLabelValue(col, False)
@@ -89,40 +55,6 @@
                 value = self.Parent.TranslateType[value]
             self.data[row][colname] = value
         
-    def ResetView(self, grid):
-        """
-        (wx.Grid) -> Reset the grid view.   Call this to
-        update the grid if rows and columns have been added or deleted
-        """
-        grid.BeginBatch()
-        for current, new, delmsg, addmsg in [
-            (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED),
-            (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED),
-        ]:
-            if new < current:
-                msg = wx.grid.GridTableMessage(self,delmsg,new,current-new)
-                grid.ProcessTableMessage(msg)
-            elif new > current:
-                msg = wx.grid.GridTableMessage(self,addmsg,new-current)
-                grid.ProcessTableMessage(msg)
-                self.UpdateValues(grid)
-        grid.EndBatch()
-
-        self._rows = self.GetNumberRows()
-        self._cols = self.GetNumberCols()
-        # update the column rendering scheme
-        self._updateColAttrs(grid)
-
-        # update the scrollbars and the displayed part of the grid
-        grid.AdjustScrollbars()
-        grid.ForceRefresh()
-
-    def UpdateValues(self, grid):
-        """Update all displayed values"""
-        # This sends an event to the grid table to update all of the values
-        msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
-        grid.ProcessTableMessage(msg)
-
     def _updateColAttrs(self, grid):
         """
         wx.Grid -> update the column attributes to add the
@@ -171,41 +103,8 @@
                 grid.SetReadOnly(row, col, readonly)
                 
                 grid.SetCellBackgroundColour(row, col, wx.WHITE)
-            if wx.Platform == '__WXMSW__':
-                grid.SetRowMinimalHeight(row, 20)
-            else:
-                grid.SetRowMinimalHeight(row, 28)
-            grid.AutoSizeRow(row, False)
-    
-    def SetData(self, data):
-        self.data = data
-    
-    def GetData(self):
-        return self.data
-    
-    def GetCurrentIndex(self):
-        return self.CurrentIndex
-    
-    def SetCurrentIndex(self, index):
-        self.CurrentIndex = index
-    
-    def AppendRow(self, row_content):
-        self.data.append(row_content)
-    
-    def InsertRow(self, row_index, row_content):
-        self.data.insert(row_index, row_content)
-
-    def RemoveRow(self, row_index):
-        self.data.pop(row_index)
-        
-    def MoveRow(self, row_index, move):
-        new_index = max(0, min(row_index + move, len(self.data) - 1))
-        if new_index != row_index:
-            self.data.insert(new_index, self.data.pop(row_index))
-        return new_index
-
-    def Empty(self):
-        self.data = []
+            self.ResizeRow(grid, row)
+
 
 [ID_ACTIONBLOCKDIALOG, ID_ACTIONBLOCKDIALOGVARIABLESGRID, 
  ID_ACTIONBLOCKDIALOGSTATICTEXT1, ID_ACTIONBLOCKDIALOGADDBUTTON,