]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
Somehow, setting a tint color makes gauge work :/.
[wxWidgets.git] / src / generic / datavgen.cpp
index 631cfecd76b675b31af74c20bf828a14dc53d551..d36e86116ba9a59807babcc060547fed46631176 100644 (file)
@@ -3,7 +3,6 @@
 // Purpose:     wxDataViewCtrl generic implementation
 // Author:      Robert Roebling
 // Modified by: Francesco Montorsi, Guru Kathiresan, Bo Yang
 // Purpose:     wxDataViewCtrl generic implementation
 // Author:      Robert Roebling
 // Modified by: Francesco Montorsi, Guru Kathiresan, Bo Yang
-// Id:          $Id$
 // Copyright:   (c) 1998 Robert Roebling
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // Copyright:   (c) 1998 Robert Roebling
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
@@ -80,7 +79,22 @@ static const int EXPANDER_OFFSET = 1;
 // For the generic implementation, both the leaf nodes and the nodes are sorted for
 // fast search when needed
 static wxDataViewModel* g_model;
 // For the generic implementation, both the leaf nodes and the nodes are sorted for
 // fast search when needed
 static wxDataViewModel* g_model;
-static int g_column = -2;
+
+// The column is either the index of the column to be used for sorting or one
+// of the special values in this enum:
+enum
+{
+    // Sort when we're thawed later.
+    SortColumn_OnThaw = -3,
+
+    // Don't sort at all.
+    SortColumn_None = -2,
+
+    // Sort using the model default sort order.
+    SortColumn_Default = -1
+};
+
+static int g_column = SortColumn_None;
 static bool g_asending = true;
 
 // ----------------------------------------------------------------------------
 static bool g_asending = true;
 
 // ----------------------------------------------------------------------------
@@ -146,6 +160,16 @@ void wxDataViewColumn::UpdateDisplay()
     }
 }
 
     }
 }
 
+void wxDataViewColumn::UnsetAsSortKey()
+{
+    m_sort = false;
+
+    if ( m_owner )
+        m_owner->SetSortingColumnIndex(wxNOT_FOUND);
+
+    UpdateDisplay();
+}
+
 void wxDataViewColumn::SetSortOrder(bool ascending)
 {
     if ( !m_owner )
 void wxDataViewColumn::SetSortOrder(bool ascending)
 {
     if ( !m_owner )
@@ -224,7 +248,7 @@ private:
     {
         const unsigned idx = event.GetColumn();
 
     {
         const unsigned idx = event.GetColumn();
 
-        if ( SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, idx) )
+        if ( SendEvent(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, idx) )
             return;
 
         // default handling for the column click is to sort by this column or
             return;
 
         // default handling for the column click is to sort by this column or
@@ -254,12 +278,12 @@ private:
 
         owner->OnColumnChange(idx);
 
 
         owner->OnColumnChange(idx);
 
-        SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, idx);
+        SendEvent(wxEVT_DATAVIEW_COLUMN_SORTED, idx);
     }
 
     void OnRClick(wxHeaderCtrlEvent& event)
     {
     }
 
     void OnRClick(wxHeaderCtrlEvent& event)
     {
-        if ( !SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
+        if ( !SendEvent(wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
                         event.GetColumn()) )
             event.Skip();
     }
                         event.GetColumn()) )
             event.Skip();
     }
@@ -581,20 +605,50 @@ public:
         UpdateDisplay();
     }
 
         UpdateDisplay();
     }
 
+    // Override the base class method to resort if needed, i.e. if
+    // SortPrepare() was called -- and ignored -- while we were frozen.
+    virtual void DoThaw()
+    {
+        if ( g_column == SortColumn_OnThaw )
+        {
+            Resort();
+            g_column = SortColumn_None;
+        }
+
+        wxWindow::DoThaw();
+    }
+
     void SortPrepare()
     {
         g_model = GetModel();
     void SortPrepare()
     {
         g_model = GetModel();
+
         wxDataViewColumn* col = GetOwner()->GetSortingColumn();
         if( !col )
         {
             if (g_model->HasDefaultCompare())
         wxDataViewColumn* col = GetOwner()->GetSortingColumn();
         if( !col )
         {
             if (g_model->HasDefaultCompare())
-                g_column = -1;
+            {
+                // See below for the explanation of IsFrozen() test.
+                if ( IsFrozen() )
+                    g_column = SortColumn_OnThaw;
+                else
+                    g_column = SortColumn_Default;
+            }
             else
             else
-                g_column = -2;
+                g_column = SortColumn_None;
 
             g_asending = true;
             return;
         }
 
             g_asending = true;
             return;
         }
+
+        // Avoid sorting while the window is frozen, this allows to quickly add
+        // many items without resorting after each addition and only resort
+        // them all at once when the window is finally thawed, see above.
+        if ( IsFrozen() )
+        {
+            g_column = SortColumn_OnThaw;
+            return;
+        }
+
         g_column = col->GetModelColumn();
         g_asending = col->IsSortOrderAscending();
     }
         g_column = col->GetModelColumn();
         g_asending = col->IsSortOrderAscending();
     }
@@ -967,7 +1021,7 @@ bool wxDataViewBitmapRenderer::GetValue( wxVariant& WXUNUSED(value) ) const
 bool wxDataViewBitmapRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
 {
     if (m_bitmap.IsOk())
 bool wxDataViewBitmapRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
 {
     if (m_bitmap.IsOk())
-        dc->DrawBitmap( m_bitmap, cell.x, cell.y );
+        dc->DrawBitmap( m_bitmap, cell.x, cell.y, true /* use mask */ );
     else if (m_icon.IsOk())
         dc->DrawIcon( m_icon, cell.x, cell.y );
 
     else if (m_icon.IsOk())
         dc->DrawIcon( m_icon, cell.x, cell.y );
 
@@ -1035,7 +1089,7 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state
     return true;
 }
 
     return true;
 }
 
-bool wxDataViewToggleRenderer::WXActivateCell(const wxRect& WXUNUSED(cell),
+bool wxDataViewToggleRenderer::WXActivateCell(const wxRect& WXUNUSED(cellRect),
                                               wxDataViewModel *model,
                                               const wxDataViewItem& item,
                                               unsigned int col,
                                               wxDataViewModel *model,
                                               const wxDataViewItem& item,
                                               unsigned int col,
@@ -1043,7 +1097,8 @@ bool wxDataViewToggleRenderer::WXActivateCell(const wxRect& WXUNUSED(cell),
 {
     if ( mouseEvent )
     {
 {
     if ( mouseEvent )
     {
-        // only react to clicks directly on the checkbox, not elsewhere in the same cell:
+        // Only react to clicks directly on the checkbox, not elsewhere in the
+        // same cell.
         if ( !wxRect(GetSize()).Contains(mouseEvent->GetPosition()) )
             return false;
     }
         if ( !wxRect(GetSize()).Contains(mouseEvent->GetPosition()) )
             return false;
     }
@@ -1504,7 +1559,7 @@ wxDragResult wxDataViewMainWindow::OnDragOver( wxDataFormat format, wxCoord x,
 
     wxDataViewModel *model = GetModel();
 
 
     wxDataViewModel *model = GetModel();
 
-    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+    wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
     event.SetEventObject( m_owner );
     event.SetItem( item );
     event.SetModel( model );
     event.SetEventObject( m_owner );
     event.SetItem( item );
     event.SetModel( model );
@@ -1548,7 +1603,7 @@ bool wxDataViewMainWindow::OnDrop( wxDataFormat format, wxCoord x, wxCoord y )
 
     wxDataViewModel *model = GetModel();
 
 
     wxDataViewModel *model = GetModel();
 
-    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+    wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
     event.SetEventObject( m_owner );
     event.SetItem( item );
     event.SetModel( model );
     event.SetEventObject( m_owner );
     event.SetItem( item );
     event.SetModel( model );
@@ -1579,7 +1634,7 @@ wxDragResult wxDataViewMainWindow::OnData( wxDataFormat format, wxCoord x, wxCoo
 
     wxCustomDataObject *obj = (wxCustomDataObject *) GetDropTarget()->GetDataObject();
 
 
     wxCustomDataObject *obj = (wxCustomDataObject *) GetDropTarget()->GetDataObject();
 
-    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, m_owner->GetId() );
+    wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_DROP, m_owner->GetId() );
     event.SetEventObject( m_owner );
     event.SetItem( item );
     event.SetModel( model );
     event.SetEventObject( m_owner );
     event.SetItem( item );
     event.SetModel( model );
@@ -1738,7 +1793,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
     // Send the event to wxDataViewCtrl itself.
     wxWindow * const parent = GetParent();
 
     // Send the event to wxDataViewCtrl itself.
     wxWindow * const parent = GetParent();
-    wxDataViewEvent cache_event(wxEVT_COMMAND_DATAVIEW_CACHE_HINT, parent->GetId());
+    wxDataViewEvent cache_event(wxEVT_DATAVIEW_CACHE_HINT, parent->GetId());
     cache_event.SetEventObject(parent);
     cache_event.SetCache(item_start, item_last - 1);
     parent->ProcessWindowEvent(cache_event);
     cache_event.SetEventObject(parent);
     cache_event.SetCache(item_start, item_last - 1);
     parent->ProcessWindowEvent(cache_event);
@@ -2423,7 +2478,7 @@ bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item)
 
     // Send event
     wxWindow *parent = GetParent();
 
     // Send event
     wxWindow *parent = GetParent();
-    wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, parent->GetId());
+    wxDataViewEvent le(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, parent->GetId());
     le.SetEventObject(parent);
     le.SetModel(GetModel());
     le.SetItem(item);
     le.SetEventObject(parent);
     le.SetModel(GetModel());
     le.SetItem(item);
@@ -2434,18 +2489,8 @@ bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item)
 
 bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned int model_column )
 {
 
 bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned int model_column )
 {
-    int view_column = -1;
-    unsigned int n_col = m_owner->GetColumnCount();
-    for (unsigned i = 0; i < n_col; i++)
-    {
-        wxDataViewColumn *column = m_owner->GetColumn( i );
-        if (column->GetModelColumn() == model_column)
-        {
-            view_column = (int) i;
-            break;
-        }
-    }
-    if (view_column == -1)
+    int view_column = m_owner->GetModelColumnIndex(model_column);
+    if ( view_column == wxNOT_FOUND )
         return false;
 
     // NOTE: to be valid, we cannot use e.g. INT_MAX - 1
         return false;
 
     // NOTE: to be valid, we cannot use e.g. INT_MAX - 1
@@ -2464,7 +2509,7 @@ bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned i
 
     // Send event
     wxWindow *parent = GetParent();
 
     // Send event
     wxWindow *parent = GetParent();
-    wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, parent->GetId());
+    wxDataViewEvent le(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, parent->GetId());
     le.SetEventObject(parent);
     le.SetModel(GetModel());
     le.SetItem(item);
     le.SetEventObject(parent);
     le.SetModel(GetModel());
     le.SetItem(item);
@@ -2743,7 +2788,7 @@ bool wxDataViewMainWindow::IsRowSelected( unsigned int row )
 void wxDataViewMainWindow::SendSelectionChangedEvent( const wxDataViewItem& item)
 {
     wxWindow *parent = GetParent();
 void wxDataViewMainWindow::SendSelectionChangedEvent( const wxDataViewItem& item)
 {
     wxWindow *parent = GetParent();
-    wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, parent->GetId());
+    wxDataViewEvent le(wxEVT_DATAVIEW_SELECTION_CHANGED, parent->GetId());
 
     le.SetEventObject(parent);
     le.SetModel(GetModel());
 
     le.SetEventObject(parent);
     le.SetModel(GetModel());
@@ -3094,7 +3139,7 @@ void wxDataViewMainWindow::Expand( unsigned int row )
 
     if (!node->IsOpen())
     {
 
     if (!node->IsOpen())
     {
-        if ( !SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, node->GetItem()) )
+        if ( !SendExpanderEvent(wxEVT_DATAVIEW_ITEM_EXPANDING, node->GetItem()) )
         {
             // Vetoed by the event handler.
             return;
         {
             // Vetoed by the event handler.
             return;
@@ -3128,7 +3173,7 @@ void wxDataViewMainWindow::Expand( unsigned int row )
         m_count = -1;
         UpdateDisplay();
         // Send the expanded event
         m_count = -1;
         UpdateDisplay();
         // Send the expanded event
-        SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,node->GetItem());
+        SendExpanderEvent(wxEVT_DATAVIEW_ITEM_EXPANDED,node->GetItem());
     }
 }
 
     }
 }
 
@@ -3146,7 +3191,7 @@ void wxDataViewMainWindow::Collapse(unsigned int row)
 
         if (node->IsOpen())
         {
 
         if (node->IsOpen())
         {
-            if ( !SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,node->GetItem()) )
+            if ( !SendExpanderEvent(wxEVT_DATAVIEW_ITEM_COLLAPSING,node->GetItem()) )
             {
                 // Vetoed by the event handler.
                 return;
             {
                 // Vetoed by the event handler.
                 return;
@@ -3202,7 +3247,7 @@ void wxDataViewMainWindow::Collapse(unsigned int row)
 
             m_count = -1;
             UpdateDisplay();
 
             m_count = -1;
             UpdateDisplay();
-            SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,node->GetItem());
+            SendExpanderEvent(wxEVT_DATAVIEW_ITEM_COLLAPSED,node->GetItem());
         }
 }
 
         }
 }
 
@@ -3629,13 +3674,13 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
             }
             else
             {
             }
             else
             {
-                // Enter activates the item, i.e. sends wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED to
+                // Enter activates the item, i.e. sends wxEVT_DATAVIEW_ITEM_ACTIVATED to
                 // it. Only if that event is not handled do we activate column renderer (which
                 // is normally done by Space) or even inline editing.
 
                 const wxDataViewItem item = GetItemByRow(m_currentRow);
 
                 // it. Only if that event is not handled do we activate column renderer (which
                 // is normally done by Space) or even inline editing.
 
                 const wxDataViewItem item = GetItemByRow(m_currentRow);
 
-                wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,
+                wxDataViewEvent le(wxEVT_DATAVIEW_ITEM_ACTIVATED,
                                    parent->GetId());
                 le.SetItem(item);
                 le.SetEventObject(parent);
                                    parent->GetId());
                 le.SetItem(item);
                 le.SetEventObject(parent);
@@ -3991,7 +4036,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
     if (event.RightUp())
     {
         wxWindow *parent = GetParent();
     if (event.RightUp())
     {
         wxWindow *parent = GetParent();
-        wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, parent->GetId());
+        wxDataViewEvent le(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, parent->GetId());
         le.SetEventObject(parent);
         le.SetModel(model);
 
         le.SetEventObject(parent);
         le.SetModel(model);
 
@@ -4000,30 +4045,82 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
             le.SetItem( item );
             le.SetColumn( col->GetModelColumn() );
             le.SetDataViewColumn( col );
             le.SetItem( item );
             le.SetColumn( col->GetModelColumn() );
             le.SetDataViewColumn( col );
-
-            wxVariant value;
-            model->GetValue( value, item, col->GetModelColumn() );
-            le.SetValue(value);
         }
 
         parent->ProcessWindowEvent(le);
         return;
     }
 
         }
 
         parent->ProcessWindowEvent(le);
         return;
     }
 
-    if (!col)
+#if wxUSE_DRAG_AND_DROP
+    if (event.Dragging() || ((m_dragCount > 0) && event.Leaving()))
     {
     {
-        event.Skip();
+        if (m_dragCount == 0)
+        {
+            // we have to report the raw, physical coords as we want to be
+            // able to call HitTest(event.m_pointDrag) from the user code to
+            // get the item being dragged
+            m_dragStart = event.GetPosition();
+        }
+
+        m_dragCount++;
+        if ((m_dragCount < 3) && (event.Leaving()))
+            m_dragCount = 3;
+        else if (m_dragCount != 3)
+            return;
+
+        if (event.LeftIsDown())
+        {
+            m_owner->CalcUnscrolledPosition( m_dragStart.x, m_dragStart.y,
+                                             &m_dragStart.x, &m_dragStart.y );
+            unsigned int drag_item_row = GetLineAt( m_dragStart.y );
+            wxDataViewItem itemDragged = GetItemByRow( drag_item_row );
+
+            // Notify cell about drag
+            wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, m_owner->GetId() );
+            event.SetEventObject( m_owner );
+            event.SetItem( itemDragged );
+            event.SetModel( model );
+            if (!m_owner->HandleWindowEvent( event ))
+                return;
+
+            if (!event.IsAllowed())
+                return;
+
+            wxDataObject *obj = event.GetDataObject();
+            if (!obj)
+                return;
+
+            wxDataViewDropSource drag( this, drag_item_row );
+            drag.SetData( *obj );
+            /* wxDragResult res = */ drag.DoDragDrop(event.GetDragFlags());
+            delete obj;
+        }
         return;
     }
         return;
     }
+    else
+    {
+        m_dragCount = 0;
+    }
+#endif // wxUSE_DRAG_AND_DROP
 
 
-    wxDataViewRenderer *cell = col->GetRenderer();
-    if ((current >= GetRowCount()) || (x > GetEndOfLastCol()))
+    // Check if we clicked outside the item area.
+    if ((current >= GetRowCount()) || !col)
     {
     {
-        // Unselect all if below the last row ?
+        // Follow Windows convention here: clicking either left or right (but
+        // not middle) button clears the existing selection.
+        if (m_owner && (event.LeftDown() || event.RightDown()))
+        {
+            if (!GetSelections().empty())
+            {
+                m_owner->UnselectAll();
+                SendSelectionChangedEvent(wxDataViewItem());
+            }
+        }
         event.Skip();
         return;
     }
 
         event.Skip();
         return;
     }
 
+    wxDataViewRenderer *cell = col->GetRenderer();
     wxDataViewColumn* const
         expander = GetExpanderColumnOrFirstOne(GetOwner());
 
     wxDataViewColumn* const
         expander = GetExpanderColumnOrFirstOne(GetOwner());
 
@@ -4079,57 +4176,6 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         }
     }
 
         }
     }
 
-#if wxUSE_DRAG_AND_DROP
-    if (event.Dragging())
-    {
-        if (m_dragCount == 0)
-        {
-            // we have to report the raw, physical coords as we want to be
-            // able to call HitTest(event.m_pointDrag) from the user code to
-            // get the item being dragged
-            m_dragStart = event.GetPosition();
-        }
-
-        m_dragCount++;
-
-        if (m_dragCount != 3)
-            return;
-
-        if (event.LeftIsDown())
-        {
-            m_owner->CalcUnscrolledPosition( m_dragStart.x, m_dragStart.y,
-                                             &m_dragStart.x, &m_dragStart.y );
-            unsigned int drag_item_row = GetLineAt( m_dragStart.y );
-            wxDataViewItem itemDragged = GetItemByRow( drag_item_row );
-
-            // Notify cell about drag
-            wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, m_owner->GetId() );
-            event.SetEventObject( m_owner );
-            event.SetItem( itemDragged );
-            event.SetModel( model );
-            if (!m_owner->HandleWindowEvent( event ))
-                return;
-
-            if (!event.IsAllowed())
-                return;
-
-            wxDataObject *obj = event.GetDataObject();
-            if (!obj)
-                return;
-
-            wxDataViewDropSource drag( this, drag_item_row );
-            drag.SetData( *obj );
-            /* wxDragResult res = */ drag.DoDragDrop(event.GetDragFlags());
-            delete obj;
-        }
-        return;
-    }
-    else
-    {
-        m_dragCount = 0;
-    }
-#endif // wxUSE_DRAG_AND_DROP
-
     bool simulateClick = false;
 
     if (event.ButtonDClick())
     bool simulateClick = false;
 
     if (event.ButtonDClick())
@@ -4153,7 +4199,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         else if ( current == m_lineLastClicked )
         {
             wxWindow *parent = GetParent();
         else if ( current == m_lineLastClicked )
         {
             wxWindow *parent = GetParent();
-            wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, parent->GetId());
+            wxDataViewEvent le(wxEVT_DATAVIEW_ITEM_ACTIVATED, parent->GetId());
             le.SetItem( item );
             le.SetColumn( col->GetModelColumn() );
             le.SetDataViewColumn( col );
             le.SetItem( item );
             le.SetColumn( col->GetModelColumn() );
             le.SetDataViewColumn( col );
@@ -4323,33 +4369,38 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
                               GetLineHeight( current ) );
 
             // Report position relative to the cell's custom area, i.e.
                               GetLineHeight( current ) );
 
             // Report position relative to the cell's custom area, i.e.
-            // no the entire space as given by the control but the one
+            // not the entire space as given by the control but the one
             // used by the renderer after calculation of alignment etc.
             // used by the renderer after calculation of alignment etc.
+            //
+            // Notice that this results in negative coordinates when clicking
+            // in the upper left corner of a centre-aligned cell which doesn't
+            // fill its column entirely so this is somewhat surprising, but we
+            // do it like this for compatibility with the native GTK+ version,
+            // see #12270.
 
             // adjust the rectangle ourselves to account for the alignment
 
             // adjust the rectangle ourselves to account for the alignment
+            int align = cell->GetAlignment();
+            if ( align == wxDVR_DEFAULT_ALIGNMENT )
+                align = wxALIGN_CENTRE;
+
             wxRect rectItem = cell_rect;
             wxRect rectItem = cell_rect;
-            const int align = cell->GetAlignment();
-            if ( align != wxDVR_DEFAULT_ALIGNMENT )
+            const wxSize size = cell->GetSize();
+            if ( size.x >= 0 && size.x < cell_rect.width )
             {
             {
-                const wxSize size = cell->GetSize();
-
-                if ( size.x >= 0 && size.x < cell_rect.width )
-                {
-                    if ( align & wxALIGN_CENTER_HORIZONTAL )
-                        rectItem.x += (cell_rect.width - size.x)/2;
-                    else if ( align & wxALIGN_RIGHT )
-                        rectItem.x += cell_rect.width - size.x;
-                    // else: wxALIGN_LEFT is the default
-                }
+                if ( align & wxALIGN_CENTER_HORIZONTAL )
+                    rectItem.x += (cell_rect.width - size.x)/2;
+                else if ( align & wxALIGN_RIGHT )
+                    rectItem.x += cell_rect.width - size.x;
+                // else: wxALIGN_LEFT is the default
+            }
 
 
-                if ( size.y >= 0 && size.y < cell_rect.height )
-                {
-                    if ( align & wxALIGN_CENTER_VERTICAL )
-                        rectItem.y += (cell_rect.height - size.y)/2;
-                    else if ( align & wxALIGN_BOTTOM )
-                        rectItem.y += cell_rect.height - size.y;
-                    // else: wxALIGN_TOP is the default
-                }
+            if ( size.y >= 0 && size.y < cell_rect.height )
+            {
+                if ( align & wxALIGN_CENTER_VERTICAL )
+                    rectItem.y += (cell_rect.height - size.y)/2;
+                else if ( align & wxALIGN_BOTTOM )
+                    rectItem.y += cell_rect.height - size.y;
+                // else: wxALIGN_TOP is the default
             }
 
             wxMouseEvent event2(event);
             }
 
             wxMouseEvent event2(event);
@@ -4669,6 +4720,14 @@ void wxDataViewCtrl::OnColumnsCountChanged()
 
 void wxDataViewCtrl::DoSetExpanderColumn()
 {
 
 void wxDataViewCtrl::DoSetExpanderColumn()
 {
+    wxDataViewColumn* column = GetExpanderColumn();
+    if ( column )
+    {
+        int index = GetColumnIndex(column);
+        if ( index != wxNOT_FOUND )
+            InvalidateColBestWidth(index);
+    }
+
     m_clientArea->UpdateDisplay();
 }
 
     m_clientArea->UpdateDisplay();
 }
 
@@ -4719,6 +4778,18 @@ int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn *column) const
     return wxNOT_FOUND;
 }
 
     return wxNOT_FOUND;
 }
 
+int wxDataViewCtrl::GetModelColumnIndex( unsigned int model_column ) const
+{
+    const int count = GetColumnCount();
+    for ( int index = 0; index < count; index++ )
+    {
+        wxDataViewColumn* column = GetColumn(index);
+        if ( column->GetModelColumn() == model_column )
+            return index;
+    }
+    return wxNOT_FOUND;
+}
+
 unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
 {
     if ( m_colsBestWidths[idx].width != 0 )
 unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
 {
     if ( m_colsBestWidths[idx].width != 0 )
@@ -4736,21 +4807,23 @@ unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
                            wxDataViewMainWindow *clientArea,
                            wxDataViewRenderer *renderer,
                            const wxDataViewModel *model,
                            wxDataViewMainWindow *clientArea,
                            wxDataViewRenderer *renderer,
                            const wxDataViewModel *model,
-                           unsigned column,
+                           unsigned int model_column,
                            int expanderSize)
             : m_width(0),
               m_dvc(dvc),
               m_clientArea(clientArea),
               m_renderer(renderer),
               m_model(model),
                            int expanderSize)
             : m_width(0),
               m_dvc(dvc),
               m_clientArea(clientArea),
               m_renderer(renderer),
               m_model(model),
-              m_column(column),
+              m_model_column(model_column),
               m_expanderSize(expanderSize)
 
         {
               m_expanderSize(expanderSize)
 
         {
+            int index = dvc->GetModelColumnIndex( model_column );
+            wxDataViewColumn* column = index == wxNOT_FOUND ? NULL : dvc->GetColumn(index);
             m_isExpanderCol =
                 !clientArea->IsList() &&
                 (column == 0 ||
             m_isExpanderCol =
                 !clientArea->IsList() &&
                 (column == 0 ||
-                 GetExpanderColumnOrFirstOne(const_cast<wxDataViewCtrl*>(dvc)) == dvc->GetColumnAt(column));
+                 GetExpanderColumnOrFirstOne(const_cast<wxDataViewCtrl*>(dvc)) == column );
         }
 
         void UpdateWithWidth(int width)
         }
 
         void UpdateWithWidth(int width)
@@ -4774,7 +4847,7 @@ unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
                 item = m_clientArea->GetItemByRow(row);
             }
 
                 item = m_clientArea->GetItemByRow(row);
             }
 
-            m_renderer->PrepareForItem(m_model, item, m_column);
+            m_renderer->PrepareForItem(m_model, item, m_model_column);
             m_width = wxMax(m_width, m_renderer->GetSize().x + indent);
         }
 
             m_width = wxMax(m_width, m_renderer->GetSize().x + indent);
         }
 
@@ -4786,7 +4859,7 @@ unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
         wxDataViewMainWindow *m_clientArea;
         wxDataViewRenderer *m_renderer;
         const wxDataViewModel *m_model;
         wxDataViewMainWindow *m_clientArea;
         wxDataViewRenderer *m_renderer;
         const wxDataViewModel *m_model;
-        unsigned m_column;
+        unsigned m_model_column;
         bool m_isExpanderCol;
         int m_expanderSize;
     };
         bool m_isExpanderCol;
         int m_expanderSize;
     };