]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/datavgen.cpp
fix MSVC warnings about possibly uninitialized variables; some reindentation
[wxWidgets.git] / src / generic / datavgen.cpp
index b99a103b8e6144593467f24dff0555ab7a8fe74f..f6e109d249f6323d53bbb5e88e064a7b89fd4564 100644 (file)
@@ -34,6 +34,7 @@
     #include "wx/settings.h"
     #include "wx/msgdlg.h"
     #include "wx/dcscreen.h"
+    #include "wx/frame.h"
 #endif
 
 #include "wx/stockitem.h"
@@ -46,6 +47,7 @@
 #include "wx/listimpl.cpp"
 #include "wx/imaglist.h"
 #include "wx/headerctrl.h"
+#include "wx/dnd.h"
 
 //-----------------------------------------------------------------------------
 // classes
@@ -191,7 +193,7 @@ private:
     }
 
     DECLARE_EVENT_TABLE()
-    DECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow)
+    wxDECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow);
 };
 
 BEGIN_EVENT_TABLE(wxDataViewHeaderWindow, wxHeaderCtrl)
@@ -415,6 +417,9 @@ public:
     wxDataViewCtrl *GetOwner() { return m_owner; }
     const wxDataViewCtrl *GetOwner() const { return m_owner; }
 
+#if wxUSE_DRAG_AND_DROP
+    wxBitmap CreateItemBitmap( unsigned int row, int &indent );
+#endif // wxUSE_DRAG_AND_DROP
     void OnPaint( wxPaintEvent &event );
     void OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event);
     void OnChar( wxKeyEvent &event );
@@ -485,18 +490,16 @@ public:
     void Collapse( unsigned int row ) { OnCollapsing( row ); }
     bool IsExpanded( unsigned int row ) const;
 
-    bool EnableDragSource( const wxDataFormat &format )
-    {
-        m_dragFormat = format;
-        m_dragEnabled = format != wxDF_INVALID;
-        return true;
-    }
-    bool EnableDropTarget( const wxDataFormat &format )
-    {
-        m_dropFormat = format;
-        m_dropEnabled = format != wxDF_INVALID;
-        return true;
-    }
+#if wxUSE_DRAG_AND_DROP
+    bool EnableDragSource( const wxDataFormat &format );
+    bool EnableDropTarget( const wxDataFormat &format );
+
+    void RemoveDropHint();
+    wxDragResult OnDragOver( wxDataFormat format, wxCoord x, wxCoord y, wxDragResult def );
+    bool OnDrop( wxDataFormat format, wxCoord x, wxCoord y );
+    wxDragResult OnData( wxDataFormat format, wxCoord x, wxCoord y, wxDragResult def );
+    void OnLeave();
+#endif // wxUSE_DRAG_AND_DROP
 
 private:
     wxDataViewTreeNode * GetTreeNodeByRow( unsigned int row ) const;
@@ -525,14 +528,18 @@ private:
 
     bool                        m_hasFocus;
 
+#if wxUSE_DRAG_AND_DROP
     int                         m_dragCount;
     wxPoint                     m_dragStart;
-    
+
     bool                        m_dragEnabled;
     wxDataFormat                m_dragFormat;
-    
+
     bool                        m_dropEnabled;
     wxDataFormat                m_dropFormat;
+    bool                        m_dropHint;
+    unsigned int                m_dropHintLine;
+#endif // wxUSE_DRAG_AND_DROP
 
     // for double click logic
     unsigned int m_lineLastClicked,
@@ -1135,6 +1142,132 @@ wxDataViewIconTextRenderer::GetValueFromEditorCtrl(wxControl* WXUNUSED(editor),
     return false;
 }
 
+//-----------------------------------------------------------------------------
+// wxDataViewDropTarget
+//-----------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP
+
+class wxBitmapCanvas: public wxWindow
+{
+public:
+    wxBitmapCanvas( wxWindow *parent, const wxBitmap &bitmap, const wxSize &size ) :
+       wxWindow( parent, wxID_ANY, wxPoint(0,0), size )
+    {
+        m_bitmap = bitmap;
+        Connect( wxEVT_PAINT, wxPaintEventHandler(wxBitmapCanvas::OnPaint) );
+    }
+
+    void OnPaint( wxPaintEvent &WXUNUSED(event) )
+    {
+        wxPaintDC dc(this);
+        dc.DrawBitmap( m_bitmap, 0, 0);
+    }
+
+    wxBitmap m_bitmap;
+};
+
+class wxDataViewDropSource: public wxDropSource
+{
+public:
+    wxDataViewDropSource( wxDataViewMainWindow *win, unsigned int row ) :
+         wxDropSource( win )
+    {
+        m_win = win;
+        m_row = row;
+        m_hint = NULL;
+    }
+
+    ~wxDataViewDropSource()
+    {
+        delete m_hint;
+    }
+
+    virtual bool GiveFeedback( wxDragResult WXUNUSED(effect) )
+    {
+        wxPoint pos = wxGetMousePosition();
+
+        if (!m_hint)
+        {
+            int liney = m_win->GetLineStart( m_row );
+            int linex = 0;
+            m_win->GetOwner()->CalcUnscrolledPosition( 0, liney, NULL, &liney );
+            m_win->ClientToScreen( &linex, &liney );
+            m_dist_x = pos.x - linex;
+            m_dist_y = pos.y - liney;
+
+            int indent = 0;
+            wxBitmap ib = m_win->CreateItemBitmap( m_row, indent );
+            m_dist_x -= indent;
+            m_hint = new wxFrame( m_win->GetParent(), wxID_ANY, wxEmptyString,
+                                         wxPoint(pos.x - m_dist_x, pos.y + 5 ),
+                                         ib.GetSize(),
+                                         wxFRAME_TOOL_WINDOW |
+                                         wxFRAME_FLOAT_ON_PARENT |
+                                         wxFRAME_NO_TASKBAR |
+                                         wxNO_BORDER );
+            new wxBitmapCanvas( m_hint, ib, ib.GetSize() );
+            m_hint->Show();
+        }
+        else
+        {
+            m_hint->Move( pos.x - m_dist_x, pos.y + 5  );
+            m_hint->SetTransparent( 128 );
+        }
+
+        return false;
+    }
+
+    wxDataViewMainWindow   *m_win;
+    unsigned int            m_row;
+    wxFrame                *m_hint;
+    int m_dist_x,m_dist_y;
+};
+
+
+class wxDataViewDropTarget: public wxDropTarget
+{
+public:
+    wxDataViewDropTarget( wxDataObject *obj, wxDataViewMainWindow *win ) :
+        wxDropTarget( obj )
+    {
+        m_win = win;
+    }
+
+    virtual wxDragResult OnDragOver( wxCoord x, wxCoord y, wxDragResult def )
+        {
+           wxDataFormat format = GetMatchingPair();
+           if (format == wxDF_INVALID)
+              return wxDragNone;
+           return m_win->OnDragOver( format, x, y, def);
+        }
+
+    virtual bool OnDrop( wxCoord x, wxCoord y )
+        {
+           wxDataFormat format = GetMatchingPair();
+           if (format == wxDF_INVALID)
+              return false;
+           return m_win->OnDrop( format, x, y );
+        }
+
+    virtual wxDragResult OnData( wxCoord x, wxCoord y, wxDragResult def )
+        {
+           wxDataFormat format = GetMatchingPair();
+           if (format == wxDF_INVALID)
+              return wxDragNone;
+           if (!GetData())
+              return wxDragNone;
+           return m_win->OnData( format, x, y, def );
+        }
+
+    virtual void OnLeave()
+        { m_win->OnLeave(); }
+
+    wxDataViewMainWindow   *m_win;
+};
+
+#endif // wxUSE_DRAG_AND_DROP
+
 //-----------------------------------------------------------------------------
 // wxDataViewRenameTimer
 //-----------------------------------------------------------------------------
@@ -1191,14 +1324,19 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
 
     m_lineHeight = wxMax( 17, GetCharHeight() + 2 ); // 17 = mini icon height + 1
 
+#if wxUSE_DRAG_AND_DROP
     m_dragCount = 0;
     m_dragStart = wxPoint(0,0);
-    m_lineLastClicked = (unsigned int) -1;
-    m_lineBeforeLastClicked = (unsigned int) -1;
-    m_lineSelectSingleOnUp = (unsigned int) -1;
 
     m_dragEnabled = false;
     m_dropEnabled = false;
+    m_dropHint = false;
+    m_dropHintLine = (unsigned int) -1;
+#endif // wxUSE_DRAG_AND_DROP
+
+    m_lineLastClicked = (unsigned int) -1;
+    m_lineBeforeLastClicked = (unsigned int) -1;
+    m_lineSelectSingleOnUp = (unsigned int) -1;
 
     m_hasFocus = false;
 
@@ -1226,6 +1364,259 @@ wxDataViewMainWindow::~wxDataViewMainWindow()
     delete m_renameTimer;
 }
 
+
+#if wxUSE_DRAG_AND_DROP
+bool wxDataViewMainWindow::EnableDragSource( const wxDataFormat &format )
+{
+    m_dragFormat = format;
+    m_dragEnabled = format != wxDF_INVALID;
+
+    return true;
+}
+
+bool wxDataViewMainWindow::EnableDropTarget( const wxDataFormat &format )
+{
+    m_dropFormat = format;
+    m_dropEnabled = format != wxDF_INVALID;
+
+    if (m_dropEnabled)
+        SetDropTarget( new wxDataViewDropTarget( new wxCustomDataObject( format ), this ) );
+
+    return true;
+}
+
+void wxDataViewMainWindow::RemoveDropHint()
+{
+    if (m_dropHint)
+    {
+            m_dropHint = false;
+            RefreshRow( m_dropHintLine );
+            m_dropHintLine = (unsigned int) -1;
+    }
+}
+
+wxDragResult wxDataViewMainWindow::OnDragOver( wxDataFormat format, wxCoord x, wxCoord y, wxDragResult def )
+{
+    int xx = x;
+    int yy = y;
+    m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
+    unsigned int row = GetLineAt( yy );
+
+    if ((row >= GetRowCount()) || (yy > GetEndOfLastCol()))
+    {
+        RemoveDropHint();
+        return wxDragNone;
+    }
+
+    wxDataViewItem item = GetItemByRow( row );
+
+    wxDataViewModel *model = GetOwner()->GetModel();
+
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetItem( item );
+    event.SetModel( model );
+    event.SetDataFormat( format );
+    if (!m_owner->HandleWindowEvent( event ))
+    {
+        RemoveDropHint();
+        return wxDragNone;
+    }
+
+    if (!event.IsAllowed())
+    {
+        RemoveDropHint();
+        return wxDragNone;
+    }
+
+
+    if (m_dropHint && (row != m_dropHintLine))
+        RefreshRow( m_dropHintLine );
+    m_dropHint = true;
+    m_dropHintLine = row;
+    RefreshRow( row );
+
+    return def;
+}
+
+bool wxDataViewMainWindow::OnDrop( wxDataFormat format, wxCoord x, wxCoord y )
+{
+    RemoveDropHint();
+
+    int xx = x;
+    int yy = y;
+    m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
+    unsigned int row = GetLineAt( yy );
+
+    if ((row >= GetRowCount()) || (yy > GetEndOfLastCol()))
+        return false;
+
+    wxDataViewItem item = GetItemByRow( row );
+
+    wxDataViewModel *model = GetOwner()->GetModel();
+
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetItem( item );
+    event.SetModel( model );
+    event.SetDataFormat( format );
+    if (!m_owner->HandleWindowEvent( event ))
+        return false;
+
+    if (!event.IsAllowed())
+        return false;
+
+    return true;
+}
+
+wxDragResult wxDataViewMainWindow::OnData( wxDataFormat format, wxCoord x, wxCoord y, wxDragResult def )
+{
+    int xx = x;
+    int yy = y;
+    m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
+    unsigned int row = GetLineAt( yy );
+
+    if ((row >= GetRowCount()) || (yy > GetEndOfLastCol()))
+        return wxDragNone;
+
+    wxDataViewItem item = GetItemByRow( row );
+
+    wxDataViewModel *model = GetOwner()->GetModel();
+
+    wxCustomDataObject *obj = (wxCustomDataObject *) GetDropTarget()->GetDataObject();
+
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetItem( item );
+    event.SetModel( model );
+    event.SetDataFormat( format );
+    event.SetDataSize( obj->GetSize() );
+    event.SetDataBuffer( obj->GetData() );
+    if (!m_owner->HandleWindowEvent( event ))
+        return wxDragNone;
+
+    if (!event.IsAllowed())
+        return wxDragNone;
+
+    return def;
+}
+
+void wxDataViewMainWindow::OnLeave()
+{
+    RemoveDropHint();
+}
+
+wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent )
+{
+    int height = GetLineHeight( row );
+    int width = 0;
+    unsigned int cols = GetOwner()->GetColumnCount();
+    unsigned int col;
+    for (col = 0; col < cols; col++)
+    {
+        wxDataViewColumn *column = GetOwner()->GetColumnAt(col);
+        if (column->IsHidden())
+            continue;      // skip it!
+        width += column->GetWidth();
+    }
+
+    indent = 0;
+    if (!IsVirtualList())
+    {
+        wxDataViewTreeNode *node = GetTreeNodeByRow(row);
+        indent = GetOwner()->GetIndent() * node->GetIndentLevel();
+        indent = indent + m_lineHeight;  //try to use the m_lineHeight as the expander space
+
+               if(!node->HasChildren())
+                       delete node;
+    }
+    width -= indent;
+
+    wxBitmap bitmap( width, height );
+    wxMemoryDC dc( bitmap );
+    dc.SetFont( GetFont() );
+    dc.SetPen( *wxBLACK_PEN );
+    dc.SetBrush( *wxWHITE_BRUSH );
+    dc.DrawRectangle( 0,0,width,height );
+
+    wxDataViewModel *model = m_owner->GetModel();
+
+    wxDataViewColumn *expander = GetOwner()->GetExpanderColumn();
+    if (!expander)
+    {
+        // TODO-RTL: last column for RTL support
+        expander = GetOwner()->GetColumnAt( 0 );
+        GetOwner()->SetExpanderColumn(expander);
+    }
+
+
+    int x = 0;
+    for (col = 0; col < cols; col++)
+    {
+        wxDataViewColumn *column = GetOwner()->GetColumnAt( col );
+        wxDataViewRenderer *cell = column->GetRenderer();
+
+        if (column->IsHidden())
+            continue;       // skip it!
+
+        width = column->GetWidth();
+
+        if (column == expander)
+            width -= indent;
+
+        wxVariant value;
+        wxDataViewItem item = GetItemByRow( row );
+        model->GetValue( value, item, column->GetModelColumn());
+        cell->SetValue( value );
+
+        if (cell->GetWantsAttr())
+        {
+                wxDataViewItemAttr attr;
+                bool ret = model->GetAttr( item, column->GetModelColumn(), attr );
+                if (ret)
+                    cell->SetAttr( attr );
+                cell->SetHasAttr( ret );
+        }
+
+        wxSize size = cell->GetSize();
+        size.x = wxMin( 2*PADDING_RIGHTLEFT + size.x, width );
+        size.y = height;
+        wxRect item_rect(x, 0, size.x, size.y);
+
+        int align = cell->CalculateAlignment();
+        // horizontal alignment:
+        item_rect.x = x;
+        if (align & wxALIGN_CENTER_HORIZONTAL)
+            item_rect.x = x + (width / 2) - (size.x / 2);
+        else if (align & wxALIGN_RIGHT)
+            item_rect.x = x + width - size.x;
+        //else: wxALIGN_LEFT is the default
+
+        // vertical alignment:
+        item_rect.y = 0;
+        if (align & wxALIGN_CENTER_VERTICAL)
+            item_rect.y = (height / 2) - (size.y / 2);
+        else if (align & wxALIGN_BOTTOM)
+            item_rect.y = height - size.y;
+        //else: wxALIGN_TOP is the default
+
+        // add padding
+        item_rect.x += PADDING_RIGHTLEFT;
+        item_rect.width = size.x - 2 * PADDING_RIGHTLEFT;
+
+        //dc.SetClippingRegion( item_rect );
+        cell->Render( item_rect, &dc, 0 );
+        //dc.DestroyClippingRegion();
+
+        x += width;
+    }
+
+    return bitmap;
+}
+
+#endif // wxUSE_DRAG_AND_DROP
+
+
 void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
     wxDataViewModel *model = GetOwner()->GetModel();
@@ -1344,6 +1735,17 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         }
     }
 
+#if wxUSE_DRAG_AND_DROP
+    if (m_dropHint)
+    {
+        wxRect rect( x_start, GetLineStart( m_dropHintLine ),
+                     x_last, GetLineHeight( m_dropHintLine ) );
+        dc.SetPen( *wxBLACK_PEN );
+        dc.SetBrush( *wxTRANSPARENT_BRUSH );
+        dc.DrawRectangle( rect );
+    }
+#endif // wxUSE_DRAG_AND_DROP
+
     wxDataViewColumn *expander = GetOwner()->GetExpanderColumn();
     if (!expander)
     {
@@ -1516,9 +1918,23 @@ void wxDataViewMainWindow::OnRenameTimer()
             break;
         xpos += c->GetWidth();
     }
-    wxRect labelRect( xpos,
+
+       // we have to take an expander column into account and compute its indentation
+       // to get the editor at the correct x position where the actual text is
+       int indent = 0;
+       if (!IsVirtualList() && GetOwner()->GetExpanderColumn() == m_currentCol)
+       {
+               wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow);
+               indent = GetOwner()->GetIndent() * node->GetIndentLevel();
+               indent = indent + m_lineHeight;
+
+               if(!node->HasChildren())
+                       delete node;
+       }
+
+    wxRect labelRect( xpos + indent,
                       GetLineStart( m_currentRow ),
-                      m_currentCol->GetWidth(),
+                      m_currentCol->GetWidth() - indent,
                       GetLineHeight( m_currentRow ) );
 
     GetOwner()->CalcScrolledPosition( labelRect.x, labelRect.y,
@@ -1526,7 +1942,6 @@ void wxDataViewMainWindow::OnRenameTimer()
 
     wxDataViewItem item = GetItemByRow( m_currentRow );
     m_currentCol->GetRenderer()->StartEditing( item, labelRect );
-
 }
 
 //------------------------------------------------------------------
@@ -2440,17 +2855,17 @@ bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const
 {
     if (IsVirtualList())
        return false;
-       
+
     wxDataViewTreeNode * node = GetTreeNodeByRow(row);
     if (!node)
        return false;
-       
+
     if (!node->HasChildren())
     {
        delete node;
        return false;
     }
-    
+
     return node->IsOpen();
 }
 
@@ -2479,6 +2894,23 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row )
                    SortPrepare();
                    ::BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node);
                }
+
+               // By expanding the node all row indices that are currently in the selection list
+                          // and are greater than our node have become invalid. So we have to correct that now.
+                          const unsigned rowAdjustment = node->GetSubTreeCount();
+                          for(unsigned i=0; i<m_selection.size(); ++i)
+                          {
+                                  const unsigned testRow = m_selection[i];
+                                  // all rows above us are not affected, so skip them
+                                  if(testRow <= row)
+                                          continue;
+
+                                  m_selection[i] += rowAdjustment;
+                          }
+
+                          if(m_currentRow > row)
+                                  ChangeCurrentRow(m_currentRow + rowAdjustment);
+
                m_count = -1;
                UpdateDisplay();
                //Send the expanded event
@@ -2512,7 +2944,55 @@ void wxDataViewMainWindow::OnCollapsing(unsigned int row)
             wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,node->GetItem());
             if( e.GetSkipped() )
                 return;
-            node->ToggleOpen();
+
+                       // Find out if there are selected items below the current node.
+                       bool selectCollapsingRow = false;
+                       const unsigned rowAdjustment = node->GetSubTreeCount();
+                       unsigned maxRowToBeTested = row + rowAdjustment;
+                       for(unsigned i=0; i<m_selection.size(); ++i)
+                       {
+                               const unsigned testRow = m_selection[i];
+                               if(testRow > row && testRow <= maxRowToBeTested)
+                               {
+                                       selectCollapsingRow = true;
+                                       // get out as soon as we have found a node that is selected
+                                       break;
+                               }
+                       }
+
+                       node->ToggleOpen();
+
+                       // If the node to be closed has selected items the user won't see those any longer.
+                       // We select the collapsing node in this case.
+                       if(selectCollapsingRow)
+                       {
+                               SelectAllRows(false);
+                               ChangeCurrentRow(row);
+                               SelectRow(row, true);
+                               SendSelectionChangedEvent(GetItemByRow(row));
+                       }
+                       else
+                       {
+                               // if there were no selected items below our node we still need to "fix" the
+                               // selection list to adjust for the changing of the row indices.
+                               // We actually do the opposite of what we are doing in OnExpanding().
+                               for(unsigned i=0; i<m_selection.size(); ++i)
+                               {
+                                       const unsigned testRow = m_selection[i];
+                                       // all rows above us are not affected, so skip them
+                                       if(testRow <= row)
+                                               continue;
+
+                                       m_selection[i] -= rowAdjustment;
+                               }
+
+                               // if the "current row" is being collapsed away we change it to the current row ;-)
+                               if(m_currentRow > row && m_currentRow <= maxRowToBeTested)
+                                       ChangeCurrentRow(row);
+                               else if(m_currentRow > row)
+                                       ChangeCurrentRow(m_currentRow - rowAdjustment);
+                       }
+
             m_count = -1;
             UpdateDisplay();
             SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,nd->GetItem());
@@ -2542,7 +3022,7 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
     wxDataViewModel * model = GetOwner()->GetModel();
     if( model == NULL )
         return NULL;
-        
+
     if (!item.IsOk())
         return m_root;
 
@@ -2746,7 +3226,7 @@ static void BuildTreeHelper( wxDataViewModel * model,  wxDataViewItem & item, wx
 
     wxDataViewItemArray children;
     unsigned int num = model->GetChildren( item, children);
-    
+
     unsigned int index = 0;
     while( index < num )
     {
@@ -2943,7 +3423,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
     }
 
     //Test whether the mouse is hovered on the tree item button
-    bool hover = false;
+    bool hoverOverExpander = false;
     if ((!IsVirtualList()) && (GetOwner()->GetExpanderColumn() == col))
     {
         wxDataViewTreeNode * node = GetTreeNodeByRow(current);
@@ -2951,14 +3431,16 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         {
             int indent = node->GetIndentLevel();
             indent = GetOwner()->GetIndent()*indent;
-            wxRect rect( xpos + indent + EXPANDER_MARGIN,
-                         GetLineStart( current ) + EXPANDER_MARGIN + (GetLineHeight(current)/2) - (m_lineHeight/2) - EXPANDER_OFFSET,
-                         m_lineHeight-2*EXPANDER_MARGIN,
-                         m_lineHeight-2*EXPANDER_MARGIN + EXPANDER_OFFSET);
-            if( rect.Contains( x, y) )
+
+                       // we make the rectangle we are looking in a bit bigger than the actual
+                       // visual expander so the user can hit that little thing reliably
+            wxRect rect( xpos + indent,
+                         GetLineStart( current ) + (GetLineHeight(current) - m_lineHeight)/2,
+                         m_lineHeight, m_lineHeight);
+            if( rect.Contains(x, y) )
             {
                 //So the mouse is over the expander
-                hover = true;
+                hoverOverExpander = true;
                 if (m_underMouse && m_underMouse != node)
                 {
                     //wxLogMessage("Undo the row: %d", GetRowByItem(m_underMouse->GetItem()));
@@ -2975,7 +3457,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         if (node!=NULL && !node->HasChildren())
             delete node;
     }
-    if (!hover)
+    if (!hoverOverExpander)
     {
         if (m_underMouse != NULL)
         {
@@ -2987,6 +3469,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
 
     wxDataViewModel *model = GetOwner()->GetModel();
 
+#if wxUSE_DRAG_AND_DROP
     if (event.Dragging())
     {
         if (m_dragCount == 0)
@@ -3015,16 +3498,18 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
             event.SetModel( model );
             if (!m_owner->HandleWindowEvent( event ))
                 return;
-        
+
             if (!event.IsAllowed())
                 return;
-        
+
             wxDataObject *obj = event.GetDataObject();
             if (!obj)
                 return;
-        
-            wxPrintf( "success\n" );
-            // m_dragDataObject = obj;
+
+            wxDataViewDropSource drag( this, drag_item_row );
+            drag.SetData( *obj );
+            /* wxDragResult res = */ drag.DoDragDrop();
+            delete obj;
         }
         return;
     }
@@ -3032,8 +3517,9 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
     {
         m_dragCount = 0;
     }
+#endif // wxUSE_DRAG_AND_DROP
 
-    bool forceClick = false;
+    bool simulateClick = false;
 
     if (event.ButtonDClick())
     {
@@ -3049,7 +3535,12 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
 
     if (event.LeftDClick())
     {
-        if ( current == m_lineLastClicked )
+               if(hoverOverExpander)
+               {
+                       // a double click on the expander will be converted into a "simulated" normal click
+                       simulateClick = true;
+               }
+               else if ( current == m_lineLastClicked )
         {
             if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE))
             {
@@ -3077,11 +3568,11 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         {
             // The first click was on another item, so don't interpret this as
             // a double click, but as a simple click instead
-            forceClick = true;
+            simulateClick = true;
         }
     }
 
-    if (event.LeftUp())
+    if (event.LeftUp() && !hoverOverExpander)
     {
         if (m_lineSelectSingleOnUp != (unsigned int)-1)
         {
@@ -3091,34 +3582,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
             SendSelectionChangedEvent( GetItemByRow(m_lineSelectSingleOnUp) );
         }
 
-        //Process the event of user clicking the expander
-        bool expander = false;
-        if ((!IsVirtualList()) && (GetOwner()->GetExpanderColumn() == col))
-        {
-            wxDataViewTreeNode * node = GetTreeNodeByRow(current);
-            if( node!=NULL && node->HasChildren() )
-            {
-                int indent = node->GetIndentLevel();
-                indent = GetOwner()->GetIndent()*indent;
-                wxRect rect( xpos + indent + EXPANDER_MARGIN,
-                         GetLineStart( current ) + EXPANDER_MARGIN + (GetLineHeight(current)/2) - (m_lineHeight/2) - EXPANDER_OFFSET,
-                         m_lineHeight-2*EXPANDER_MARGIN,
-                         m_lineHeight-2*EXPANDER_MARGIN + EXPANDER_OFFSET);
-
-                if( rect.Contains( x, y) )
-                {
-                    expander = true;
-                    if( node->IsOpen() )
-                        OnCollapsing(current);
-                    else
-                        OnExpanding( current );
-                }
-            }
-            if (node && !node->HasChildren())
-               delete node;
-        }
         //If the user click the expander, we do not do editing even if the column with expander are editable
-        if (m_lastOnSame && !expander && !ignore_other_columns)
+        if (m_lastOnSame && !ignore_other_columns)
         {
             if ((col == m_currentCol) && (current == m_currentRow) &&
                 (cell->GetMode() & wxDATAVIEW_CELL_EDITABLE) )
@@ -3130,7 +3595,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         m_lastOnSame = false;
         m_lineSelectSingleOnUp = (unsigned int)-1;
     }
-    else
+    else if(!event.LeftUp())
     {
         // This is necessary, because after a DnD operation in
         // from and to ourself, the up event is swallowed by the
@@ -3167,7 +3632,18 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
     else if (event.MiddleDown())
     {
     }
-    if (event.LeftDown() || forceClick)
+
+       if((event.LeftDown() || simulateClick) && hoverOverExpander)
+       {
+               wxDataViewTreeNode* node = GetTreeNodeByRow(current);
+               // hoverOverExpander being true tells us that our node must be valid and have children.
+               // So we don't need any extra checks.
+               if( node->IsOpen() )
+                       OnCollapsing(current);
+               else
+                       OnExpanding(current);
+       }
+       else if ((event.LeftDown() || simulateClick) && !hoverOverExpander)
     {
         SetFocus();
 
@@ -3232,7 +3708,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
         // Update selection here...
         m_currentCol = col;
 
-        m_lastOnSame = !forceClick && ((col == oldCurrentCol) &&
+        m_lastOnSame = !simulateClick && ((col == oldCurrentCol) &&
                         (current == oldCurrentRow)) && oldWasSelected;
 
         // Call LeftClick after everything else as under GTK+
@@ -3311,8 +3787,8 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
            const wxPoint& pos, const wxSize& size,
            long style, const wxValidator& validator )
 {
-    if ( (style & wxBORDER_MASK) == 0)
-        style |= wxBORDER_SUNKEN;
+//    if ( (style & wxBORDER_MASK) == 0)
+//        style |= wxBORDER_SUNKEN;
 
     Init();
 
@@ -3344,6 +3820,11 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
     return true;
 }
 
+wxBorder wxDataViewCtrl::GetDefaultBorder() const
+{
+    return wxBORDER_THEME;
+}
+
 #ifdef __WXMSW__
 WXLRESULT wxDataViewCtrl::MSWWindowProc(WXUINT nMsg,
                                        WXWPARAM wParam,
@@ -3410,6 +3891,8 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
     return true;
 }
 
+#if wxUSE_DRAG_AND_DROP
+
 bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format )
 {
     return m_clientArea->EnableDragSource( format );
@@ -3420,6 +3903,8 @@ bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format )
     return m_clientArea->EnableDropTarget( format );
 }
 
+#endif // wxUSE_DRAG_AND_DROP
+
 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
 {
     if (!wxDataViewCtrlBase::AppendColumn(col))
@@ -3597,20 +4082,20 @@ void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )
             if (parent != last_parent)
                 ExpandAncestors(item);
         }
-        
+
         last_parent = parent;
         int row = m_clientArea->GetRowByItem( item );
         if( row >= 0 )
             selection.Add( static_cast<unsigned int>(row) );
     }
-    
+
     m_clientArea->SetSelections( selection );
 }
 
 void wxDataViewCtrl::Select( const wxDataViewItem & item )
 {
     ExpandAncestors( item );
-    
+
     int row = m_clientArea->GetRowByItem( item );
     if( row >= 0 )
     {
@@ -3735,7 +4220,7 @@ void wxDataViewCtrl::EnsureVisible( int row, int column )
 void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataViewColumn * column )
 {
     ExpandAncestors( item );
-  
+
     m_clientArea->RecalculateDisplay();
 
     int row = m_clientArea->GetRowByItem(item);