]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
no more _ftime instead of ftime
[wxWidgets.git] / src / generic / grid.cpp
index a03beb0823a5a32e44044794051a4daef28a3a31..889afc9226d65f708446588e6115df7515a71d22 100644 (file)
 
 #include "wx/textfile.h"
 #include "wx/spinctrl.h"
+#include "wx/tokenzr.h"
 
 #include "wx/grid.h"
+#include "wx/generic/gridsel.h"
 
 // ----------------------------------------------------------------------------
 // array classes
@@ -286,7 +288,19 @@ public:
     void RegisterDataType(const wxString& typeName,
                      wxGridCellRenderer* renderer,
                      wxGridCellEditor* editor);
+
+    // find one of already registered data types
+    int FindRegisteredDataType(const wxString& typeName);
+
+    // try to FindRegisteredDataType(), if this fails and typeName is one of
+    // standard typenames, register it and return its index
     int FindDataType(const wxString& typeName);
+
+    // try to FindDataType(), if it fails see if it is not one of already
+    // registered data types with some params in which case clone the
+    // registered data type and set params for it
+    int FindOrCloneDataType(const wxString& typeName);
+
     wxGridCellRenderer* GetRenderer(int index);
     wxGridCellEditor*   GetEditor(int index);
 
@@ -338,8 +352,6 @@ static const int GRID_HASH_SIZE = 100;
 wxGridCellEditor::wxGridCellEditor()
 {
     m_control = NULL;
-
-    m_nRef = 1;
 }
 
 
@@ -455,6 +467,7 @@ void wxGridCellEditor::StartingClick()
 
 wxGridCellTextEditor::wxGridCellTextEditor()
 {
+    m_maxChars = 0;
 }
 
 void wxGridCellTextEditor::Create(wxWindow* parent,
@@ -468,6 +481,8 @@ void wxGridCellTextEditor::Create(wxWindow* parent,
 #endif
                               );
 
+    // TODO: use m_maxChars
+
     wxGridCellEditor::Create(parent, id, evtHandler);
 }
 
@@ -604,6 +619,28 @@ void wxGridCellTextEditor::HandleReturn(wxKeyEvent& event)
 #endif
 }
 
+void wxGridCellTextEditor::SetParameters(const wxString& params)
+{
+    if ( !params )
+    {
+        // reset to default
+        m_maxChars = 0;
+    }
+    else
+    {
+        long tmp;
+        if ( !params.ToLong(&tmp) )
+        {
+            wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string "
+                          "'%s' ignored"), params.c_str());
+        }
+        else
+        {
+            m_maxChars = (size_t)tmp;
+        }
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellNumberEditor
 // ----------------------------------------------------------------------------
@@ -723,6 +760,35 @@ void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)
     event.Skip();
 }
 
+void wxGridCellNumberEditor::SetParameters(const wxString& params)
+{
+    if ( !params )
+    {
+        // reset to default
+        m_min =
+        m_max = -1;
+    }
+    else
+    {
+        long tmp;
+        if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
+        {
+            m_min = (int)tmp;
+
+            if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
+            {
+                m_max = (int)tmp;
+
+                // skip the error message below
+                return;
+            }
+        }
+
+        wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string "
+                      "'%s' ignored"), params.c_str());
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellFloatEditor
 // ----------------------------------------------------------------------------
@@ -849,8 +915,8 @@ void wxGridCellBoolEditor::SetSize(const wxRect& r)
     // so shift it to the right
     size.x -= 8;
 #elif defined(__WXMSW__)
-    // here too...
-    size.x -= 6;
+    // here too, but in other way
+    size.x += 1;
     size.y -= 2;
 #endif
 
@@ -925,13 +991,25 @@ wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,
                                                bool allowOthers)
                       : m_allowOthers(allowOthers)
 {
-    m_choices.Alloc(count);
-    for ( size_t n = 0; n < count; n++ )
+    if ( count )
     {
-        m_choices.Add(choices[n]);
+        m_choices.Alloc(count);
+        for ( size_t n = 0; n < count; n++ )
+        {
+            m_choices.Add(choices[n]);
+        }
     }
 }
 
+wxGridCellEditor *wxGridCellChoiceEditor::Clone() const
+{
+    wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;
+    editor->m_allowOthers = m_allowOthers;
+    editor->m_choices = m_choices;
+
+    return editor;
+}
+
 void wxGridCellChoiceEditor::Create(wxWindow* parent,
                                     wxWindowID id,
                                     wxEvtHandler* evtHandler)
@@ -1007,6 +1085,23 @@ void wxGridCellChoiceEditor::Reset()
     Combo()->SetInsertionPointEnd();
 }
 
+void wxGridCellChoiceEditor::SetParameters(const wxString& params)
+{
+    if ( !params )
+    {
+        // what can we do?
+        return;
+    }
+
+    m_choices.Empty();
+
+    wxStringTokenizer tk(params, _T(','));
+    while ( tk.HasMoreTokens() )
+    {
+        m_choices.Add(tk.GetNextToken());
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellEditorEvtHandler
 // ----------------------------------------------------------------------------
@@ -1049,6 +1144,20 @@ void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)
     }
 }
 
+// ----------------------------------------------------------------------------
+// wxGridCellWorker is an (almost) empty common base class for
+// wxGridCellRenderer and wxGridCellEditor managing ref counting
+// ----------------------------------------------------------------------------
+
+void wxGridCellWorker::SetParameters(const wxString& WXUNUSED(params))
+{
+    // nothing to do
+}
+
+wxGridCellWorker::~wxGridCellWorker()
+{
+}
+
 // ============================================================================
 // renderer classes
 // ============================================================================
@@ -1079,15 +1188,6 @@ void wxGridCellRenderer::Draw(wxGrid& grid,
     dc.DrawRectangle(rect);
 }
 
-void wxGridCellRenderer::SetParameters(const wxString& WXUNUSED(params))
-{
-    // nothing to do
-}
-
-wxGridCellRenderer::~wxGridCellRenderer()
-{
-}
-
 // ----------------------------------------------------------------------------
 // wxGridCellStringRenderer
 // ----------------------------------------------------------------------------
@@ -1358,11 +1458,7 @@ wxSize wxGridCellBoolRenderer::ms_sizeCheckMark;
 // FIXME these checkbox size calculations are really ugly...
 
 // between checkmark and box
-#ifdef __WXGTK__
-    static const wxCoord wxGRID_CHECKMARK_MARGIN = 4;
-#else
-    static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
-#endif
+static const wxCoord wxGRID_CHECKMARK_MARGIN = 2;
 
 wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
                                            wxGridCellAttr& WXUNUSED(attr),
@@ -1377,7 +1473,7 @@ wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
         wxCoord checkSize = 0;
         wxCheckBox *checkbox = new wxCheckBox(&grid, -1, wxEmptyString);
         wxSize size = checkbox->GetBestSize();
-        checkSize = size.y + wxGRID_CHECKMARK_MARGIN;
+        checkSize = size.y + 2*wxGRID_CHECKMARK_MARGIN;
 
         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result
 #if defined(__WXGTK__) || defined(__WXMOTIF__)
@@ -1413,22 +1509,11 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
     }
 
     // draw a border around checkmark
-    wxRect rectMark;
-    rectMark.x = rect.x + rect.width/2 - size.x/2;
-    rectMark.y = rect.y + rect.height/2 - size.y/2;
-    rectMark.width = size.x;
-    rectMark.height = size.y;
-
-    dc.SetBrush(*wxTRANSPARENT_BRUSH);
-    dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID));
-    dc.DrawRectangle(rectMark);
-
-    rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN);
-
-#ifdef __WXMSW__
-    // looks nicer under MSW
-    rectMark.x++;
-#endif // MSW
+    wxRect rectBorder;
+    rectBorder.x = rect.x + rect.width/2 - size.x/2;
+    rectBorder.y = rect.y + rect.height/2 - size.y/2;
+    rectBorder.width = size.x;
+    rectBorder.height = size.y;
 
     bool value;
     if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
@@ -1438,9 +1523,23 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
 
     if ( value )
     {
+        wxRect rectMark = rectBorder;
+#ifdef __WXMSW__
+        // MSW DrawCheckMark() is weird (and should probably be changed...)
+        rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN/2);
+        rectMark.x++;
+        rectMark.y++;
+#else // !MSW
+        rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN);
+#endif // MSW/!MSW
+
         dc.SetTextForeground(attr.GetTextColour());
         dc.DrawCheckMark(rectMark);
     }
+
+    dc.SetBrush(*wxTRANSPARENT_BRUSH);
+    dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID));
+    dc.DrawRectangle(rectBorder);
 }
 
 // ----------------------------------------------------------------------------
@@ -1590,8 +1689,8 @@ wxGridCellEditor* wxGridCellAttr::GetEditor(wxGrid* grid, int row, int col) cons
             editor->IncRef();
     }
 
-    if ( grid )                   // get renderer for the data type
-        editor =  grid->GetDefaultEditorForCell(row, col);
+    if ( !editor && grid )                   // get renderer for the data type
+        editor = grid->GetDefaultEditorForCell(row, col);
 
     if ( !editor )
         // if we still don't have one then use the grid default
@@ -1756,8 +1855,8 @@ wxGridCellAttr *wxGridRowOrColAttrData::GetAttr(int rowOrCol) const
 
 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr *attr, int rowOrCol)
 {
-    int n = m_rowsOrCols.Index(rowOrCol);
-    if ( n == wxNOT_FOUND )
+    int i = m_rowsOrCols.Index(rowOrCol);
+    if ( i == wxNOT_FOUND )
     {
         // add the attribute
         m_rowsOrCols.Add(rowOrCol);
@@ -1765,17 +1864,19 @@ void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr *attr, int rowOrCol)
     }
     else
     {
+        size_t n = (size_t)i;
         if ( attr )
         {
             // change the attribute
-            m_attrs[(size_t)n] = attr;
+            m_attrs[n]->DecRef();
+            m_attrs[n] = attr;
         }
         else
         {
             // remove this attribute
-            m_attrs[(size_t)n]->DecRef();
-            m_rowsOrCols.RemoveAt((size_t)n);
-            m_attrs.RemoveAt((size_t)n);
+            m_attrs[n]->DecRef();
+            m_rowsOrCols.RemoveAt(n);
+            m_attrs.RemoveAt(n);
         }
     }
 }
@@ -1917,7 +2018,7 @@ void wxGridTypeRegistry::RegisterDataType(const wxString& typeName,
     wxGridDataTypeInfo* info = new wxGridDataTypeInfo(typeName, renderer, editor);
 
     // is it already registered?
-    int loc = FindDataType(typeName);
+    int loc = FindRegisteredDataType(typeName);
     if ( loc != wxNOT_FOUND )
     {
         delete m_typeinfo[loc];
@@ -1929,18 +2030,106 @@ void wxGridTypeRegistry::RegisterDataType(const wxString& typeName,
     }
 }
 
+int wxGridTypeRegistry::FindRegisteredDataType(const wxString& typeName)
+{
+    size_t count = m_typeinfo.GetCount();
+    for ( size_t i = 0; i < count; i++ )
+    {
+        if ( typeName == m_typeinfo[i]->m_typeName )
+        {
+            return i;
+        }
+    }
+
+    return wxNOT_FOUND;
+}
+
 int wxGridTypeRegistry::FindDataType(const wxString& typeName)
 {
-    int found = -1;
+    int index = FindRegisteredDataType(typeName);
+    if ( index == wxNOT_FOUND )
+    {
+        // check whether this is one of the standard ones, in which case
+        // register it "on the fly"
+        if ( typeName == wxGRID_VALUE_STRING )
+        {
+            RegisterDataType(wxGRID_VALUE_STRING,
+                             new wxGridCellStringRenderer,
+                             new wxGridCellTextEditor);
+        }
+        else if ( typeName == wxGRID_VALUE_BOOL )
+        {
+            RegisterDataType(wxGRID_VALUE_BOOL,
+                             new wxGridCellBoolRenderer,
+                             new wxGridCellBoolEditor);
+        }
+        else if ( typeName == wxGRID_VALUE_NUMBER )
+        {
+            RegisterDataType(wxGRID_VALUE_NUMBER,
+                             new wxGridCellNumberRenderer,
+                             new wxGridCellNumberEditor);
+        }
+        else if ( typeName == wxGRID_VALUE_FLOAT )
+        {
+            RegisterDataType(wxGRID_VALUE_FLOAT,
+                             new wxGridCellFloatRenderer,
+                             new wxGridCellFloatEditor);
+        }
+        else if ( typeName == wxGRID_VALUE_CHOICE )
+        {
+            RegisterDataType(wxGRID_VALUE_CHOICE,
+                             new wxGridCellStringRenderer,
+                             new wxGridCellChoiceEditor);
+        }
+        else
+        {
+            return wxNOT_FOUND;
+        }
 
-    for (size_t i=0; i<m_typeinfo.Count(); i++) {
-        if (typeName == m_typeinfo[i]->m_typeName) {
-            found = i;
-            break;
+        // we get here only if just added the entry for this type, so return
+        // the last index
+        index = m_typeinfo.GetCount() - 1;
+    }
+
+    return index;
+}
+
+int wxGridTypeRegistry::FindOrCloneDataType(const wxString& typeName)
+{
+    int index = FindDataType(typeName);
+    if ( index == wxNOT_FOUND )
+    {
+        // the first part of the typename is the "real" type, anything after ':'
+        // are the parameters for the renderer
+        index = FindDataType(typeName.BeforeFirst(_T(':')));
+        if ( index == wxNOT_FOUND )
+        {
+            return wxNOT_FOUND;
         }
+
+        wxGridCellRenderer *renderer = GetRenderer(index);
+        wxGridCellRenderer *rendererOld = renderer;
+        renderer = renderer->Clone();
+        rendererOld->DecRef();
+
+        wxGridCellEditor *editor = GetEditor(index);
+        wxGridCellEditor *editorOld = editor;
+        editor = editor->Clone();
+        editorOld->DecRef();
+
+        // do it even if there are no parameters to reset them to defaults
+        wxString params = typeName.AfterFirst(_T(':'));
+        renderer->SetParameters(params);
+        editor->SetParameters(params);
+
+        // register the new typename
+        RegisterDataType(typeName, renderer, editor);
+
+        // we just registered it, it's the last one
+        index = m_typeinfo.GetCount() - 1;
     }
 
-    return found;
+    return index;
 }
 
 wxGridCellRenderer* wxGridTypeRegistry::GetRenderer(int index)
@@ -2279,7 +2468,7 @@ long wxGridStringTable::GetNumberCols()
 
 wxString wxGridStringTable::GetValue( int row, int col )
 {
-    wxASSERT_MSG( (row < GetNumberCols()) && (col < GetNumberCols()),
+    wxASSERT_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
                   _T("invalid row or column index in wxGridStringTable") );
 
     return m_data[row][col];
@@ -2287,7 +2476,7 @@ wxString wxGridStringTable::GetValue( int row, int col )
 
 void wxGridStringTable::SetValue( int row, int col, const wxString& value )
 {
-    wxASSERT_MSG( (row < GetNumberCols()) && (col < GetNumberCols()),
+    wxASSERT_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
                   _T("invalid row or column index in wxGridStringTable") );
 
     m_data[row][col] = value;
@@ -2295,7 +2484,7 @@ void wxGridStringTable::SetValue( int row, int col, const wxString& value )
 
 bool wxGridStringTable::IsEmptyCell( int row, int col )
 {
-    wxASSERT_MSG( (row < GetNumberCols()) && (col < GetNumberCols()),
+    wxASSERT_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
                   _T("invalid row or column index in wxGridStringTable") );
 
     return (m_data[row][col] == wxEmptyString);
@@ -2890,6 +3079,7 @@ wxGrid::~wxGrid()
         delete m_table;
 
     delete m_typeRegistry;
+    delete m_selection;
 }
 
 
@@ -2928,22 +3118,9 @@ void wxGrid::Create()
     m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
     m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
 
-    // data type registration: register all standard data types
-    // TODO: may be allow the app to selectively disable some of them?
+    // create the type registry
     m_typeRegistry = new wxGridTypeRegistry;
-    RegisterDataType(wxGRID_VALUE_STRING,
-                     new wxGridCellStringRenderer,
-                     new wxGridCellTextEditor);
-    RegisterDataType(wxGRID_VALUE_BOOL,
-                     new wxGridCellBoolRenderer,
-                     new wxGridCellBoolEditor);
-    RegisterDataType(wxGRID_VALUE_NUMBER,
-                     new wxGridCellNumberRenderer,
-                     new wxGridCellNumberEditor);
-    RegisterDataType(wxGRID_VALUE_FLOAT,
-                     new wxGridCellFloatRenderer,
-                     new wxGridCellFloatEditor);
-
+    m_selection = 0;
     // subwindow components that make up the wxGrid
     m_cornerLabelWin = new wxGridCornerLabelWindow( this,
                                                     -1,
@@ -2971,7 +3148,8 @@ void wxGrid::Create()
 }
 
 
-bool wxGrid::CreateGrid( int numRows, int numCols )
+bool wxGrid::CreateGrid( int numRows, int numCols,
+                         wxGrid::wxGridSelectionModes selmode )
 {
     if ( m_created )
     {
@@ -2989,7 +3167,7 @@ bool wxGrid::CreateGrid( int numRows, int numCols )
         Init();
         m_created = TRUE;
     }
-
+    m_selection = new wxGridSelection( this, selmode );
     return m_created;
 }
 
@@ -3087,8 +3265,8 @@ void wxGrid::Init()
 
     m_currentCellCoords = wxGridNoCellCoords;
 
-    m_selectedTopLeft = wxGridNoCellCoords;
-    m_selectedBottomRight = wxGridNoCellCoords;
+    m_selectingTopLeft = wxGridNoCellCoords;
+    m_selectingBottomRight = wxGridNoCellCoords;
     m_selectionBackground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT);
     m_selectionForeground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
 
@@ -4078,7 +4256,8 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
 
             wxClientDC dc( m_gridWin );
             PrepareDC( dc );
-            y = wxMax( y, GetRowTop(m_dragRowOrCol) + WXGRID_MIN_ROW_HEIGHT );
+            y = wxMax( y, GetRowTop(m_dragRowOrCol) +
+                          GetRowMinimalHeight(m_dragRowOrCol) );
             dc.SetLogicalFunction(wxINVERT);
             if ( m_dragLastPos >= 0 )
             {
@@ -4128,6 +4307,8 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
     //
     if ( event.LeftDown() && coords != wxGridNoCellCoords )
     {
+        if ( !event.ShiftDown() && !event.ControlDown() )
+            ClearSelection();
         if ( event.ShiftDown() )
         {
             SelectBlock( m_currentCellCoords, coords );
@@ -4163,6 +4344,10 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
                 }
                 else
                 {
+                    m_selection->ToggleCellSelection( coords.GetRow(),
+                                                      coords.GetCol() );
+                    m_selectingTopLeft = wxGridNoCellCoords;
+                    m_selectingBottomRight = wxGridNoCellCoords;
                     SetCurrentCell( coords );
                     m_waitForSlowClick = TRUE;
                 }
@@ -4193,8 +4378,13 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
     {
         if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
         {
-            if ( IsSelection() )
+            if ( m_selectingTopLeft != wxGridNoCellCoords &&
+                 m_selectingBottomRight != wxGridNoCellCoords )
             {
+                m_selection->SelectBlock( m_selectingTopLeft.GetRow(),
+                                          m_selectingTopLeft.GetCol(),
+                                          m_selectingBottomRight.GetRow(),
+                                          m_selectingBottomRight.GetCol() );
                 if (m_winCapture)
                 {
                     m_winCapture->ReleaseMouse();
@@ -4483,7 +4673,7 @@ bool wxGrid::InsertRows( int pos, int numRows, bool WXUNUSED(updateLabels) )
                 SetCurrentCell( 0, 0 );
             }
 
-            ClearSelection();
+            m_selection->UpdateRows( pos, numRows );
             if ( !GetBatchCount() ) Refresh();
         }
 
@@ -4519,7 +4709,6 @@ bool wxGrid::AppendRows( int numRows, bool WXUNUSED(updateLabels) )
         // the table will have sent the results of the append row
         // operation to this view object as a grid table message
         //
-        ClearSelection();
         if ( !GetBatchCount() ) Refresh();
         return TRUE;
     }
@@ -4551,7 +4740,7 @@ bool wxGrid::DeleteRows( int pos, int numRows, bool WXUNUSED(updateLabels) )
             // the table will have sent the results of the delete row
             // operation to this view object as a grid table message
             //
-            ClearSelection();
+            m_selection->UpdateRows( pos, -((int)numRows) );
             if ( !GetBatchCount() ) Refresh();
             return TRUE;
         }
@@ -4590,7 +4779,7 @@ bool wxGrid::InsertCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
                 SetCurrentCell( 0, 0 );
             }
 
-            ClearSelection();
+            m_selection->UpdateCols( pos, numCols );
             if ( !GetBatchCount() ) Refresh();
         }
 
@@ -4626,7 +4815,6 @@ bool wxGrid::AppendCols( int numCols, bool WXUNUSED(updateLabels) )
             SetCurrentCell( 0, 0 );
         }
 
-        ClearSelection();
         if ( !GetBatchCount() ) Refresh();
         return TRUE;
     }
@@ -4657,7 +4845,7 @@ bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
             // the table will have sent the results of the delete col
             // operation to this view object as a grid table message
             //
-            ClearSelection();
+            m_selection->UpdateCols( pos, -((int)numCols) );
             if ( !GetBatchCount() ) Refresh();
             return TRUE;
         }
@@ -4699,8 +4887,8 @@ bool wxGrid::SendEvent( const wxEventType type,
         wxGridRangeSelectEvent gridEvt( GetId(),
                                         type,
                                         this,
-                                        m_selectedTopLeft,
-                                        m_selectedBottomRight,
+                                        m_selectingTopLeft,
+                                        m_selectingBottomRight,
                                         mouseEv.ControlDown(),
                                         mouseEv.ShiftDown(),
                                         mouseEv.AltDown(),
@@ -4981,13 +5169,16 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
         wxGridCellAttr* attr = GetCellAttr(coords);
         DrawCellHighlight(dc, attr);
         attr->DecRef();
-
+#if 0
+        // SN: For my extended selection code, automatic
+        //     deselection is definitely not a good idea.
         if ( IsSelection() )
         {
             wxRect r( SelectionToDeviceRect() );
             ClearSelection();
             if ( !GetBatchCount() ) m_gridWin->Refresh( FALSE, &r );
         }
+#endif
     }
 }
 
@@ -6933,7 +7124,7 @@ wxGridCellRenderer* wxGrid::GetDefaultRendererForCell(int row, int col) const
 wxGridCellEditor*
 wxGrid::GetDefaultEditorForType(const wxString& typeName) const
 {
-    int index = m_typeRegistry->FindDataType(typeName);
+    int index = m_typeRegistry->FindOrCloneDataType(typeName);
     if ( index == wxNOT_FOUND )
     {
         wxFAIL_MSG(wxT("Unknown data type name"));
@@ -6947,41 +7138,15 @@ wxGrid::GetDefaultEditorForType(const wxString& typeName) const
 wxGridCellRenderer*
 wxGrid::GetDefaultRendererForType(const wxString& typeName) const
 {
-    // first try to find an exact match
-    wxGridCellRenderer *renderer;
-    int index = m_typeRegistry->FindDataType(typeName);
+    int index = m_typeRegistry->FindOrCloneDataType(typeName);
     if ( index == wxNOT_FOUND )
     {
-        // then try to construct a renderer from the base name and parameters
-        // following it
-
-        // the first part of the typename is the "real" type, anything after ':'
-        // are the parameters for the renderer
-        index = m_typeRegistry->FindDataType(typeName.BeforeFirst(_T(':')));
-        if ( index == wxNOT_FOUND )
-        {
-            wxFAIL_MSG(wxT("Unknown data type name"));
-
-            return NULL;
-        }
-
-        renderer = m_typeRegistry->GetRenderer(index);
-        wxGridCellRenderer *rendererOld = renderer;
-        renderer = renderer->Clone();
-        rendererOld->DecRef();
-
-        // do it even if there are no parameters to reset them to defaults
-        renderer->SetParameters(typeName.AfterFirst(_T(':')));
+        wxFAIL_MSG(wxT("Unknown data type name"));
 
-        // register the new typename
-        m_typeRegistry->RegisterDataType(typeName, renderer, NULL);
-    }
-    else
-    {
-        renderer = m_typeRegistry->GetRenderer(index);
+        return NULL;
     }
 
-    return renderer;
+    return m_typeRegistry->GetRenderer(index);
 }
 
 
@@ -7107,7 +7272,9 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column )
 {
     wxClientDC dc(m_gridWin);
 
-    int row, col;
+    // init both of them to avoid compiler warnings, even if weo nly need one
+    int row = -1,
+        col = -1;
     if ( column )
         col = colOrRow;
     else
@@ -7162,8 +7329,11 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column )
     }
     else
     {
-        // leave some space around text
-        extentMax += 10;
+        if ( column )
+        {
+            // leave some space around text
+            extentMax += 10;
+        }
     }
 
     if ( column )
@@ -7267,83 +7437,16 @@ void wxGrid::SetCellValue( int row, int col, const wxString& s )
 
 void wxGrid::SelectRow( int row, bool addToSelected )
 {
-    wxRect r;
-
-    if ( IsSelection() && addToSelected )
-    {
-        wxRect  rect[4];
-        bool    need_refresh[4];
-        need_refresh[0] =
-        need_refresh[1] =
-        need_refresh[2] =
-        need_refresh[3] = FALSE;
-
-        int     i;
-
-        wxCoord oldLeft   = m_selectedTopLeft.GetCol();
-        wxCoord oldTop    = m_selectedTopLeft.GetRow();
-        wxCoord oldRight  = m_selectedBottomRight.GetCol();
-        wxCoord oldBottom = m_selectedBottomRight.GetRow();
+    if ( IsSelection() && !addToSelected )
+        m_selection->ClearSelection();
 
-        if ( oldTop > row )
-        {
-            need_refresh[0] = TRUE;
-            rect[0] = BlockToDeviceRect( wxGridCellCoords ( row, 0 ),
-                                         wxGridCellCoords ( oldTop - 1,
-                                                            m_numCols - 1 ) );
-            m_selectedTopLeft.SetRow( row );
-        }
-
-        if ( oldLeft > 0 )
-        {
-            need_refresh[1] = TRUE;
-            rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop, 0 ),
-                                         wxGridCellCoords ( oldBottom,
-                                                            oldLeft - 1 ) );
-
-            m_selectedTopLeft.SetCol( 0 );
-        }
-
-        if ( oldBottom < row )
-        {
-            need_refresh[2] = TRUE;
-            rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1, 0 ),
-                                         wxGridCellCoords ( row,
-                                                            m_numCols - 1 ) );
-            m_selectedBottomRight.SetRow( row );
-        }
-
-        if ( oldRight < m_numCols - 1 )
-        {
-            need_refresh[3] = TRUE;
-            rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop ,
-                                                            oldRight + 1 ),
-                                         wxGridCellCoords ( oldBottom,
-                                                            m_numCols - 1 ) );
-            m_selectedBottomRight.SetCol( m_numCols - 1 );
-        }
-
-        for (i = 0; i < 4; i++ )
-            if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
-                m_gridWin->Refresh( FALSE, &(rect[i]) );
-    }
-    else
-    {
-        r = SelectionToDeviceRect();
-        ClearSelection();
-        if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r );
-
-        m_selectedTopLeft.Set( row, 0 );
-        m_selectedBottomRight.Set( row, m_numCols-1 );
-        r = SelectionToDeviceRect();
-        m_gridWin->Refresh( FALSE, &r );
-    }
+    m_selection->SelectRow( row );
 
     wxGridRangeSelectEvent gridEvt( GetId(),
                                     wxEVT_GRID_RANGE_SELECT,
                                     this,
-                                    m_selectedTopLeft,
-                                    m_selectedBottomRight );
+                                    wxGridCellCoords( row, 0 ),
+                                    wxGridCellCoords( row, m_numCols - 1 ) );
 
     GetEventHandler()->ProcessEvent(gridEvt);
 }
@@ -7351,81 +7454,16 @@ void wxGrid::SelectRow( int row, bool addToSelected )
 
 void wxGrid::SelectCol( int col, bool addToSelected )
 {
-    if ( IsSelection() && addToSelected )
-    {
-        wxRect  rect[4];
-        bool    need_refresh[4];
-        need_refresh[0] =
-        need_refresh[1] =
-        need_refresh[2] =
-        need_refresh[3] = FALSE;
-        int     i;
+    if ( IsSelection() && !addToSelected )
+        m_selection->ClearSelection();
 
-        wxCoord oldLeft   = m_selectedTopLeft.GetCol();
-        wxCoord oldTop    = m_selectedTopLeft.GetRow();
-        wxCoord oldRight  = m_selectedBottomRight.GetCol();
-        wxCoord oldBottom = m_selectedBottomRight.GetRow();
-
-        if ( oldLeft > col )
-        {
-            need_refresh[0] = TRUE;
-            rect[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col ),
-                                         wxGridCellCoords ( m_numRows - 1,
-                                                            oldLeft - 1 ) );
-            m_selectedTopLeft.SetCol( col );
-        }
-
-        if ( oldTop  > 0 )
-        {
-            need_refresh[1] = TRUE;
-            rect[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft ),
-                                         wxGridCellCoords ( oldTop - 1,
-                                                            oldRight ) );
-            m_selectedTopLeft.SetRow( 0 );
-        }
-
-        if ( oldRight < col )
-        {
-            need_refresh[2] = TRUE;
-            rect[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight + 1 ),
-                                         wxGridCellCoords ( m_numRows - 1,
-                                                            col            ) );
-            m_selectedBottomRight.SetCol( col );
-        }
-
-        if ( oldBottom < m_numRows - 1 )
-        {
-            need_refresh[3] = TRUE;
-            rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1,
-                                                            oldLeft ),
-                                         wxGridCellCoords ( m_numRows - 1,
-                                                            oldRight ) );
-            m_selectedBottomRight.SetRow( m_numRows - 1 );
-        }
-
-        for (i = 0; i < 4; i++ )
-            if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
-                m_gridWin->Refresh( FALSE, &(rect[i]) );
-    }
-    else
-    {
-        wxRect r;
-
-        r = SelectionToDeviceRect();
-        ClearSelection();
-        if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r );
-
-        m_selectedTopLeft.Set( 0, col );
-        m_selectedBottomRight.Set( m_numRows-1, col );
-        r = SelectionToDeviceRect();
-        m_gridWin->Refresh( FALSE, &r );
-    }
+    m_selection->SelectCol( col );
 
     wxGridRangeSelectEvent gridEvt( GetId(),
                                     wxEVT_GRID_RANGE_SELECT,
                                     this,
-                                    m_selectedTopLeft,
-                                    m_selectedBottomRight );
+                                    wxGridCellCoords( 0, col ),
+                                    wxGridCellCoords( m_numRows - 1, col ) );
 
     GetEventHandler()->ProcessEvent(gridEvt);
 }
@@ -7453,8 +7491,8 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
     updateTopLeft = wxGridCellCoords( topRow, leftCol );
     updateBottomRight = wxGridCellCoords( bottomRow, rightCol );
 
-    if ( m_selectedTopLeft != updateTopLeft ||
-         m_selectedBottomRight != updateBottomRight )
+    if ( m_selectingTopLeft != updateTopLeft ||
+         m_selectingBottomRight != updateBottomRight )
     {
         // Compute two optimal update rectangles:
         // Either one rectangle is a real subset of the
@@ -7468,10 +7506,10 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
         int     i;
 
         // Store intermediate values
-        wxCoord oldLeft   = m_selectedTopLeft.GetCol();
-        wxCoord oldTop    = m_selectedTopLeft.GetRow();
-        wxCoord oldRight  = m_selectedBottomRight.GetCol();
-        wxCoord oldBottom = m_selectedBottomRight.GetRow();
+        wxCoord oldLeft   = m_selectingTopLeft.GetCol();
+        wxCoord oldTop    = m_selectingTopLeft.GetRow();
+        wxCoord oldRight  = m_selectingBottomRight.GetCol();
+        wxCoord oldBottom = m_selectingBottomRight.GetRow();
 
         // Determine the outer/inner coordinates.
         if (oldLeft > leftCol)
@@ -7541,8 +7579,8 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
 
 
         // Change Selection
-        m_selectedTopLeft = updateTopLeft;
-        m_selectedBottomRight = updateBottomRight;
+        m_selectingTopLeft = updateTopLeft;
+        m_selectingBottomRight = updateBottomRight;
 
         // various Refresh() calls
         for (i = 0; i < 4; i++ )
@@ -7558,8 +7596,8 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
         wxGridRangeSelectEvent gridEvt( GetId(),
                                         wxEVT_GRID_RANGE_SELECT,
                                         this,
-                                        m_selectedTopLeft,
-                                        m_selectedBottomRight );
+                                        m_selectingTopLeft,
+                                        m_selectingBottomRight );
 
         GetEventHandler()->ProcessEvent(gridEvt);
     }
@@ -7567,17 +7605,30 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
 
 void wxGrid::SelectAll()
 {
-    m_selectedTopLeft.Set( 0, 0 );
-    m_selectedBottomRight.Set( m_numRows-1, m_numCols-1 );
+    m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 );
+}
 
-    m_gridWin->Refresh();
+bool wxGrid::IsSelection()
+{
+    return ( m_selection->IsSelection() ||
+             ( m_selectingTopLeft != wxGridNoCellCoords &&
+               m_selectingBottomRight != wxGridNoCellCoords ) );
 }
 
+bool wxGrid::IsInSelection( int row, int col )
+{
+    return ( m_selection->IsInSelection( row, col ) ||
+             ( row >= m_selectingTopLeft.GetRow() &&
+               col >= m_selectingTopLeft.GetCol() &&
+               row <= m_selectingBottomRight.GetRow() &&
+               col <= m_selectingBottomRight.GetCol() ) );
+}
 
 void wxGrid::ClearSelection()
 {
-    m_selectedTopLeft = wxGridNoCellCoords;
-    m_selectedBottomRight = wxGridNoCellCoords;
+    m_selectingTopLeft = wxGridNoCellCoords;
+    m_selectingBottomRight = wxGridNoCellCoords;
+    m_selection->ClearSelection();
 }
 
 
@@ -7692,4 +7743,3 @@ wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id, wxEventType type, wxObjec
 
 
 #endif // ifndef wxUSE_NEW_GRID
-