]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
Don't use wxRendererNative::DrawFocusRect() under Mac.
[wxWidgets.git] / src / generic / datavgen.cpp
index 04924b89dd768188e34d234c48c71ee703d739e2..dd7813621d9f095ad2afcc6792ee110a06fa9d55 100644 (file)
 // classes
 //-----------------------------------------------------------------------------
 
+class wxDataViewColumn;
+class wxDataViewHeaderWindow;
 class wxDataViewCtrl;
 
+//-----------------------------------------------------------------------------
+// classes
+//-----------------------------------------------------------------------------
+
 static const int SCROLL_UNIT_X = 15;
 
 // the cell padding on the left/right
@@ -76,6 +82,29 @@ static wxDataViewModel* g_model;
 static int g_column = -2;
 static bool g_asending = true;
 
+//-----------------------------------------------------------------------------
+// wxDataViewColumn
+//-----------------------------------------------------------------------------
+
+void wxDataViewColumn::Init(int width, wxAlignment align, int flags)
+{
+    m_width = width == wxCOL_WIDTH_DEFAULT ? wxDVC_DEFAULT_WIDTH : width;
+    m_minWidth = 0;
+    m_align = align;
+    m_flags = flags;
+    m_sort = false;
+    m_sortAscending = true;
+}
+    
+void wxDataViewColumn::UpdateDisplay()
+{
+    if (m_owner)
+    {
+        int idx = m_owner->GetColumnIndex( this );
+        m_owner->OnColumnChange( idx );
+    }
+}
+
 //-----------------------------------------------------------------------------
 // wxDataViewHeaderWindow
 //-----------------------------------------------------------------------------
@@ -607,66 +636,17 @@ IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase)
 wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype,
                                         wxDataViewCellMode mode,
                                         int align) :
-    wxDataViewRendererBase( varianttype, mode, align )
+    wxDataViewCustomRendererBase( varianttype, mode, align )
 {
-    m_dc = NULL;
     m_align = align;
     m_mode = mode;
     m_ellipsizeMode = wxELLIPSIZE_MIDDLE;
+    m_dc = NULL;
 }
 
 wxDataViewRenderer::~wxDataViewRenderer()
 {
-    if (m_dc)
-        delete m_dc;
-}
-
-bool
-wxDataViewRenderer::RenderWithAttr(wxDC& dc,
-                                   const wxRect& cell_rect,
-                                   int align,
-                                   const wxDataViewItemAttr *WXUNUSED(attr),
-                                   int state)
-{
-    // adjust the rectangle ourselves to account for the alignment
-
-    wxRect item_rect = cell_rect;
-    if ( align )
-    {
-        const wxSize size = GetSize();
-
-        // take alignment into account only if there is enough space, otherwise
-        // show as much contents as possible
-        //
-        // notice that many existing renderers (e.g. wxDataViewSpinRenderer)
-        // return hard-coded size which can be more than they need and if we
-        // trusted their GetSize() we'd draw the text out of cell bounds
-        // entirely
-
-        if ( size.x < cell_rect.width )
-        {
-            if (align & wxALIGN_CENTER_HORIZONTAL)
-                item_rect.x += (cell_rect.width - size.x)/2;
-            else if (align & wxALIGN_RIGHT)
-                item_rect.x += cell_rect.width - size.x;
-            // else: wxALIGN_LEFT is the default
-
-            item_rect.width = size.x;
-        }
-
-        if ( size.y < cell_rect.height )
-        {
-            if (align & wxALIGN_CENTER_VERTICAL)
-                item_rect.y += (cell_rect.height - size.y)/2;
-            else if (align & wxALIGN_BOTTOM)
-                item_rect.y += cell_rect.height - size.y;
-            // else: wxALIGN_TOP is the default
-
-            item_rect.height = size.y;
-        }
-    }
-
-    return Render(item_rect, &dc, state);
+    delete m_dc;
 }
 
 wxDC *wxDataViewRenderer::GetDC()
@@ -693,19 +673,6 @@ int wxDataViewRenderer::GetAlignment() const
     return m_align;
 }
 
-int wxDataViewRenderer::CalculateAlignment() const
-{
-    if (m_align == wxDVR_DEFAULT_ALIGNMENT)
-    {
-        if (GetOwner() == NULL)
-        return wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL;
-
-        return GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL;
-    }
-
-    return m_align;
-}
-
 // ---------------------------------------------------------
 // wxDataViewCustomRenderer
 // ---------------------------------------------------------
@@ -718,71 +685,15 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
 {
 }
 
-void
-wxDataViewCustomRenderer::RenderText(wxDC& dc,
-                                     const wxRect& rect,
-                                     int align,
-                                     const wxString& text,
-                                     const wxDataViewItemAttr *attr,
-                                     int state,
-                                     int xoffset)
-{
-    // override custom foreground with the standard one for the selected items
-    // because we currently don't allow changing the selection background and
-    // custom colours may be unreadable on it
-    wxColour col;
-    if ( state & wxDATAVIEW_CELL_SELECTED )
-        col = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
-    else if ( attr && attr->HasColour() )
-        col = attr->GetColour();
-    else // use default foreground
-        col = GetOwner()->GetOwner()->GetForegroundColour();
-
-    wxDCTextColourChanger changeFg(dc, col);
-
-    wxDCFontChanger changeFont(dc);
-    if ( attr && attr->HasFont() )
-    {
-        wxFont font(dc.GetFont());
-        if ( attr->GetBold() )
-            font.MakeBold();
-        if ( attr->GetItalic() )
-            font.MakeItalic();
-
-        changeFont.Set(font);
-    }
-
-    wxRect rectText = rect;
-    rectText.x += xoffset;
-    rectText.width -= xoffset;
-
-    // check if we want to ellipsize the text if it doesn't fit
-    wxString ellipsizedText;
-    if ( GetEllipsizeMode() != wxELLIPSIZE_NONE )
-    {
-        ellipsizedText = wxControl::Ellipsize
-                                    (
-                                        text,
-                                        dc,
-                                        GetEllipsizeMode(),
-                                        rect.width,
-                                        wxELLIPSIZE_FLAGS_NONE
-                                    );
-    }
-
-    dc.DrawLabel(ellipsizedText.empty() ? text : ellipsizedText,
-                 rectText, align);
-}
-
 // ---------------------------------------------------------
 // wxDataViewTextRenderer
 // ---------------------------------------------------------
 
-IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewCustomRenderer)
+IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewRenderer)
 
 wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype,
                                                 wxDataViewCellMode mode, int align ) :
-    wxDataViewCustomRenderer( varianttype, mode, align )
+    wxDataViewRenderer( varianttype, mode, align )
 {
 }
 
@@ -824,14 +735,9 @@ bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl *editor, wxVarian
     return true;
 }
 
-bool
-wxDataViewTextRenderer::RenderWithAttr(wxDC& dc,
-                                       const wxRect& rect,
-                                       int align,
-                                       const wxDataViewItemAttr *attr,
-                                       int state)
+bool wxDataViewTextRenderer::Render(wxRect rect, wxDC *dc, int state)
 {
-    RenderText(dc, rect, align, m_text, attr, state);
+    RenderText(m_text, 0, rect, dc, state);
     return true;
 }
 
@@ -847,11 +753,11 @@ wxSize wxDataViewTextRenderer::GetSize() const
 // wxDataViewBitmapRenderer
 // ---------------------------------------------------------
 
-IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewCustomRenderer)
+IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer)
 
 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype,
                                                     wxDataViewCellMode mode, int align ) :
-    wxDataViewCustomRenderer( varianttype, mode, align )
+    wxDataViewRenderer( varianttype, mode, align )
 {
 }
 
@@ -894,11 +800,11 @@ wxSize wxDataViewBitmapRenderer::GetSize() const
 // wxDataViewToggleRenderer
 // ---------------------------------------------------------
 
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer, wxDataViewCustomRenderer)
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer, wxDataViewRenderer)
 
 wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype,
                         wxDataViewCellMode mode, int align ) :
-    wxDataViewCustomRenderer( varianttype, mode, align )
+    wxDataViewRenderer( varianttype, mode, align )
 {
     m_toggle = false;
 }
@@ -923,6 +829,12 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state
     if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE)
         flags |= wxCONTROL_DISABLED;
 
+    // check boxes we draw must always have the same, standard size (if it's
+    // bigger than the cell size the checkbox will be truncated because the
+    // caller had set the clipping rectangle to prevent us from drawing outside
+    // the cell)
+    cell.SetSize(GetSize());
+
     wxRendererNative::Get().DrawCheckBox(
             GetOwner()->GetOwner(),
             *dc,
@@ -932,12 +844,12 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state
     return true;
 }
 
-bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell),
-                                        wxDataViewModel *model,
-                                        const wxDataViewItem & item, unsigned int col)
+void wxDataViewToggleRenderer::WXOnActivate(wxDataViewModel *model,
+                                            const wxVariant& valueOld,
+                                            const wxDataViewItem & item,
+                                            unsigned int col)
 {
-    model->ChangeValue(!m_toggle, item, col);
-    return true;
+    model->ChangeValue(!valueOld.GetBool(), item, col);
 }
 
 wxSize wxDataViewToggleRenderer::GetSize() const
@@ -951,11 +863,11 @@ wxSize wxDataViewToggleRenderer::GetSize() const
 // wxDataViewProgressRenderer
 // ---------------------------------------------------------
 
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer, wxDataViewCustomRenderer)
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer, wxDataViewRenderer)
 
 wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString &label,
     const wxString &varianttype, wxDataViewCellMode mode, int align ) :
-    wxDataViewCustomRenderer( varianttype, mode, align )
+    wxDataViewRenderer( varianttype, mode, align )
 {
     m_label = label;
     m_value = 0;
@@ -977,24 +889,23 @@ bool wxDataViewProgressRenderer::GetValue( wxVariant &value ) const
     return true;
 }
 
-bool wxDataViewProgressRenderer::RenderWithAttr(wxDC& dc,
-                                                const wxRect& rect,
-                                                int WXUNUSED(align),
-                                                const wxDataViewItemAttr *attr,
-                                                int WXUNUSED(state))
+bool
+wxDataViewProgressRenderer::Render(wxRect rect, wxDC *dc, int WXUNUSED(state))
 {
-    // deflat the rect to leave a small border between bars in adjacent rows
+    // deflate the rect to leave a small border between bars in adjacent rows
     wxRect bar = rect.Deflate(0, 1);
 
-    dc.SetBrush( *wxTRANSPARENT_BRUSH );
-    dc.SetPen( *wxBLACK_PEN );
-    dc.DrawRectangle( bar );
+    dc->SetBrush( *wxTRANSPARENT_BRUSH );
+    dc->SetPen( *wxBLACK_PEN );
+    dc->DrawRectangle( bar );
 
     bar.width = (int)(bar.width * m_value / 100.);
-    dc.SetPen( *wxTRANSPARENT_PEN );
-    dc.SetBrush( attr && attr->HasColour() ? wxBrush(attr->GetColour())
-                                           : *wxBLUE_BRUSH );
-    dc.DrawRectangle( bar );
+    dc->SetPen( *wxTRANSPARENT_PEN );
+
+    const wxDataViewItemAttr& attr = GetAttr();
+    dc->SetBrush( attr.HasColour() ? wxBrush(attr.GetColour())
+                                  : *wxBLUE_BRUSH );
+    dc->DrawRectangle( bar );
 
     return true;
 }
@@ -1057,11 +968,11 @@ void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event )
 
 #endif // wxUSE_DATE_RENDERER_POPUP
 
-IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer)
+IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer, wxDataViewRenderer)
 
 wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString &varianttype,
                         wxDataViewCellMode mode, int align ) :
-    wxDataViewCustomRenderer( varianttype, mode, align )
+    wxDataViewRenderer( varianttype, mode, align )
 {
 }
 
@@ -1094,35 +1005,34 @@ wxSize wxDataViewDateRenderer::GetSize() const
     return wxSize(x,y+d);
 }
 
-bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model,
-                                    const wxDataViewItem & item, unsigned int col )
+void wxDataViewDateRenderer::WXOnActivate(wxDataViewModel *model,
+                                          const wxVariant& valueOld,
+                                          const wxDataViewItem & item,
+                                          unsigned int col )
 {
-    wxVariant variant;
-    model->GetValue( variant, item, col );
-    wxDateTime value = variant.GetDateTime();
+    wxDateTime dtOld = valueOld.GetDateTime();
 
 #if wxUSE_DATE_RENDERER_POPUP
     wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient(
-        GetOwner()->GetOwner()->GetParent(), &value, model, item, col);
+        GetOwner()->GetOwner()->GetParent(), &dtOld, model, item, col);
     wxPoint pos = wxGetMousePosition();
     popup->Move( pos );
     popup->Layout();
     popup->Popup( popup->m_cal );
 #else // !wxUSE_DATE_RENDERER_POPUP
-    wxMessageBox(value.Format());
+    wxMessageBox(dtOld.Format());
 #endif // wxUSE_DATE_RENDERER_POPUP/!wxUSE_DATE_RENDERER_POPUP
-    return true;
 }
 
 // ---------------------------------------------------------
 // wxDataViewIconTextRenderer
 // ---------------------------------------------------------
 
-IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer)
+IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewRenderer)
 
 wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(
 const wxString &varianttype, wxDataViewCellMode mode, int align ) :
-    wxDataViewCustomRenderer( varianttype, mode, align )
+    wxDataViewRenderer( varianttype, mode, align )
 {
     SetMode(mode);
     SetAlignment(align);
@@ -1139,23 +1049,18 @@ bool wxDataViewIconTextRenderer::GetValue( wxVariant& WXUNUSED(value) ) const
     return false;
 }
 
-bool
-wxDataViewIconTextRenderer::RenderWithAttr(wxDC& dc,
-                                           const wxRect& rect,
-                                           int align,
-                                           const wxDataViewItemAttr *attr,
-                                           int state)
+bool wxDataViewIconTextRenderer::Render(wxRect rect, wxDC *dc, int state)
 {
     int xoffset = 0;
 
     const wxIcon& icon = m_value.GetIcon();
     if ( icon.IsOk() )
     {
-        dc.DrawIcon(icon, rect.x, rect.y + (rect.height - icon.GetHeight())/2);
+        dc->DrawIcon(icon, rect.x, rect.y + (rect.height - icon.GetHeight())/2);
         xoffset = icon.GetWidth()+4;
     }
 
-    RenderText(dc, rect, align, m_value.GetText(), attr, state, xoffset);
+    RenderText(m_value.GetText(), xoffset, rect, dc, state);
 
     return true;
 }
@@ -1641,15 +1546,15 @@ wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent )
         model->GetValue( value, item, column->GetModelColumn());
         cell->SetValue( value );
 
+        wxDataViewItemAttr attr;
+        model->GetAttr(item, column->GetModelColumn(), attr);
+        cell->SetAttr(attr);
+
         wxRect item_rect(x, 0, width, height);
         item_rect.Deflate(PADDING_RIGHTLEFT, 0);
 
         // dc.SetClippingRegion( item_rect );
-        wxDataViewItemAttr attr;
-        const bool
-            hasAttr = model->GetAttr(item, column->GetModelColumn(), attr);
-        cell->RenderWithAttr(dc, item_rect, cell->CalculateAlignment(),
-                                hasAttr ? &attr : NULL, 0);
+        cell->WXCallRender(item_rect, &dc, 0);
         // dc.DestroyClippingRegion();
 
         x += width;
@@ -1694,6 +1599,13 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
     // compute which columns needs to be redrawn
     unsigned int cols = GetOwner()->GetColumnCount();
+    if ( !cols )
+    {
+        // we assume that we have at least one column below and painting an
+        // empty control is unnecessary anyhow
+        return;
+    }
+
     unsigned int col_start = 0;
     unsigned int x_start;
     for (x_start = 0; col_start < cols; col_start++)
@@ -1772,7 +1684,8 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             if (m_hasFocus)
                 flags |= wxCONTROL_FOCUSED;
 
-            wxRect rect( x_start, GetLineStart( item ), x_last, GetLineHeight( item ) );
+            wxRect rect( x_start, GetLineStart( item ),
+                         x_last - x_start, GetLineHeight( item ) );
             wxRendererNative::Get().DrawItemSelectionRect
                                 (
                                     this,
@@ -1787,7 +1700,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     if (m_dropHint)
     {
         wxRect rect( x_start, GetLineStart( m_dropHintLine ),
-                    x_last, GetLineHeight( m_dropHintLine ) );
+                     x_last - x_start, GetLineHeight( m_dropHintLine ) );
         dc.SetPen( *wxBLACK_PEN );
         dc.SetBrush( *wxTRANSPARENT_BRUSH );
         dc.DrawRectangle( rect );
@@ -1811,7 +1724,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         wxDataViewRenderer *cell = col->GetRenderer();
         cell_rect.width = col->GetWidth();
 
-        if (col->IsHidden())
+        if ( col->IsHidden() || cell_rect.width <= 0 )
             continue;       // skip it!
 
         for (unsigned int item = item_start; item < item_last; item++)
@@ -1841,44 +1754,50 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             model->GetValue( value, dataitem, col->GetModelColumn());
             cell->SetValue( value );
 
+            wxDataViewItemAttr attr;
+            model->GetAttr(dataitem, col->GetModelColumn(), attr);
+            cell->SetAttr(attr);
+
             // update cell_rect
             cell_rect.y = GetLineStart( item );
             cell_rect.height = GetLineHeight( item );
 
-            // Draw the expander here.
+            // deal with the expander
             int indent = 0;
             if ((!IsVirtualList()) && (col == expander))
             {
-                indent = node->GetIndentLevel();
-
                 // Calculate the indent first
-                indent = cell_rect.x + GetOwner()->GetIndent() * indent;
+                indent = GetOwner()->GetIndent() * node->GetIndentLevel();
 
-                int expander_width = m_lineHeight - 2*EXPANDER_MARGIN;
+                // we reserve m_lineHeight of horizontal space for the expander
+                // but leave EXPANDER_MARGIN around the expander itself
+                int exp_x = cell_rect.x + indent + EXPANDER_MARGIN;
 
-                // change the cell_rect.x to the appropriate pos
-                int expander_x = indent + EXPANDER_MARGIN;
-                int expander_y = cell_rect.y + EXPANDER_MARGIN + (GetLineHeight(item) / 2)
-                                 - (expander_width/2) - EXPANDER_OFFSET;
+                indent += m_lineHeight;
 
-                indent = indent + m_lineHeight;
-                    // try to use the m_lineHeight as the expander space
-
-                dc.SetPen( m_penExpander );
-                dc.SetBrush( wxNullBrush );
-                if( node->HasChildren() )
+                // draw expander if needed and visible
+                if ( node->HasChildren() && exp_x < cell_rect.GetRight() )
                 {
-                    wxRect rect( expander_x , expander_y, expander_width, expander_width);
+                    dc.SetPen( m_penExpander );
+                    dc.SetBrush( wxNullBrush );
+
+                    int exp_size = m_lineHeight - 2*EXPANDER_MARGIN;
+                    int exp_y = cell_rect.y + (cell_rect.height - exp_size)/2
+                                   + EXPANDER_MARGIN - EXPANDER_OFFSET;
+
+                    const wxRect rect(exp_x, exp_y, exp_size, exp_size);
+
                     int flag = 0;
-                    if (m_underMouse == node)
-                    {
+                    if ( m_underMouse == node )
                         flag |= wxCONTROL_CURRENT;
-                    }
-                    if( node->IsOpen() )
-                        wxRendererNative::Get().DrawTreeItemButton( this, dc, rect,
-                                                                    flag|wxCONTROL_EXPANDED );
-                    else
-                        wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag);
+                    if ( node->IsOpen() )
+                        flag |= wxCONTROL_EXPANDED;
+
+                    // ensure that we don't overflow the cell (which might
+                    // happen if the column is very narrow)
+                    wxDCClipper clip(dc, cell_rect);
+
+                    wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag);
                 }
 
                 // force the expander column to left-center align
@@ -1898,6 +1817,9 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             item_rect.x += indent;
             item_rect.width -= indent;
 
+            if ( item_rect.width <= 0 )
+                continue;
+
             int state = 0;
             if (m_hasFocus && (m_selection.Index(item) != wxNOT_FOUND))
                 state |= wxDATAVIEW_CELL_SELECTED;
@@ -1911,11 +1833,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             //       make its own renderer and thus we cannot be sure of that.
             wxDCClipper clip(dc, item_rect);
 
-            wxDataViewItemAttr attr;
-            const bool
-                hasAttr = model->GetAttr(dataitem, col->GetModelColumn(), attr);
-            cell->RenderWithAttr(dc, item_rect, cell->CalculateAlignment(),
-                                    hasAttr ? &attr : NULL, state);
+            cell->WXCallRender(item_rect, &dc, state);
         }
 
         cell_rect.x += cell_rect.width;
@@ -2183,6 +2101,7 @@ bool wxDataViewMainWindow::Cleared()
 void wxDataViewMainWindow::UpdateDisplay()
 {
     m_dirty = true;
+    m_underMouse = NULL;
 }
 
 void wxDataViewMainWindow::OnInternalIdle()
@@ -3362,7 +3281,15 @@ void wxDataViewMainWindow::DestroyTree()
 
 void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
 {
-    if ( GetParent()->HandleAsNavigationKey(event) )
+    wxWindow * const parent = GetParent();
+
+    // propagate the char event upwards
+    wxKeyEvent eventForParent(event);
+    eventForParent.SetEventObject(parent);
+    if ( parent->ProcessWindowEvent(eventForParent) )
+        return;
+
+    if ( parent->HandleAsNavigationKey(event) )
         return;
 
     // no item -> nothing to do
@@ -3380,7 +3307,6 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
     {
         case WXK_RETURN:
             {
-                wxWindow *parent = GetParent();
                 wxDataViewEvent le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,
                                    parent->GetId());
                 le.SetItem( GetItemByRow(m_currentRow) );
@@ -3665,12 +3591,21 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         {
             if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE))
             {
+                const unsigned colIdx = col->GetModelColumn();
+
                 wxVariant value;
-                model->GetValue( value, item, col->GetModelColumn() );
-                cell->SetValue( value );
-                wxRect cell_rect( xpos, GetLineStart( current ),
-                                col->GetWidth(), GetLineHeight( current ) );
-                cell->Activate( cell_rect, model, item, col->GetModelColumn() );
+                model->GetValue( value, item, colIdx );
+
+                cell->WXOnActivate(model, value, item, colIdx);
+
+                if ( wxDataViewCustomRenderer *custom = cell->WXGetAsCustom() )
+                {
+                    cell->SetValue( value );
+
+                    wxRect cell_rect( xpos, GetLineStart( current ),
+                                    col->GetWidth(), GetLineHeight( current ) );
+                    custom->Activate( cell_rect, model, item, colIdx );
+                }
             }
             else
             {
@@ -3800,7 +3735,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
             {
                 ChangeCurrentRow(current);
                 ReverseRowSelection(m_currentRow);
-                SendSelectionChangedEvent(GetItemByRow(m_selection[0]) );
+                SendSelectionChangedEvent(GetItemByRow(m_currentRow));
             }
             else if (event.ShiftDown())
             {
@@ -3839,14 +3774,17 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         // Call LeftClick after everything else as under GTK+
         if (cell->GetMode() & wxDATAVIEW_CELL_ACTIVATABLE)
         {
-            // notify cell about right click
-            wxVariant value;
-            model->GetValue( value, item, col->GetModelColumn() );
-            cell->SetValue( value );
-            wxRect cell_rect( xpos, GetLineStart( current ),
-                              col->GetWidth(), GetLineHeight( current ) );
-             /* ignore ret */ cell->LeftClick( event.GetPosition(), cell_rect,
-                              model, item, col->GetModelColumn());
+            if ( wxDataViewCustomRenderer *custom = cell->WXGetAsCustom() )
+            {
+                // notify cell about click
+                wxVariant value;
+                model->GetValue( value, item, col->GetModelColumn() );
+                custom->SetValue( value );
+                wxRect cell_rect( xpos, GetLineStart( current ),
+                                  col->GetWidth(), GetLineHeight( current ) );
+                 /* ignore ret */ custom->LeftClick( event.GetPosition(), cell_rect,
+                                  model, item, col->GetModelColumn());
+            }
         }
     }
 }
@@ -3930,6 +3868,11 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
 
     m_clientArea = new wxDataViewMainWindow( this, wxID_ANY );
 
+    // We use the cursor keys for moving the selection, not scrolling, so call
+    // this method to ensure wxScrollHelperEvtHandler doesn't catch all
+    // keyboard events forwarded to us from wxListMainWindow.
+    DisableKeyboardScrolling();
+
     if (HasFlag(wxDV_NO_HEADER))
         m_headerArea = NULL;
     else
@@ -4149,6 +4092,18 @@ bool wxDataViewCtrl::ClearColumns()
 
 int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
 {
+#if 1
+    unsigned int len = GetColumnCount();
+    for ( unsigned int i = 0; i < len; i++ )
+    {
+        wxDataViewColumn * col = GetColumnAt(i);
+        if (column==col)
+            return i;
+    }
+    
+    return wxNOT_FOUND;
+#else
+    // This returns the position in pixels which is not what we want.
     int ret = 0,
         dummy = 0;
     unsigned int len = GetColumnCount();
@@ -4165,6 +4120,7 @@ int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
         }
     }
     return ret;
+#endif
 }
 
 wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const
@@ -4228,7 +4184,11 @@ void wxDataViewCtrl::Select( const wxDataViewItem & item )
         // Unselect all rows before select another in the single select mode
         if (m_clientArea->IsSingleSel())
             m_clientArea->SelectAllRows(false);
+            
         m_clientArea->SelectRow(row, true);
+        
+        // Also set focus to the selected item
+        m_clientArea->ChangeCurrentRow( row );
     }
 }