]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/dataview.cpp
include errno.h to fix buildbot compilation
[wxWidgets.git] / src / gtk / dataview.cpp
index 4610c07b01323fde08ed195bf99d005f2b1595ba..2d8a29c111169d671b62350ddff9990be20ba050 100644 (file)
     #include "wx/log.h"
     #include "wx/dcclient.h"
     #include "wx/sizer.h"
-    #include "wx/icon.h"
-    #include "wx/list.h"
     #include "wx/settings.h"
-    #include "wx/dataobj.h"
     #include "wx/crt.h"
 #endif
 
@@ -39,9 +36,7 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
-class wxDataViewCtrlInternal;
-
-wxDataViewCtrlInternal *g_internal = NULL;
+static wxDataViewCtrlInternal *gs_internal = NULL;
 
 class wxGtkTreeModelNode;
 
@@ -56,7 +51,7 @@ typedef struct _GtkWxTreeModel       GtkWxTreeModel;
 WX_DECLARE_LIST(wxDataViewItem, ItemList);
 WX_DEFINE_LIST(ItemList)
 
-class wxDataViewCtrlInternal
+class WXDLLIMPEXP_ADV wxDataViewCtrlInternal
 {
 public:
     wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model );
@@ -74,6 +69,10 @@ public:
     gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child );
 
     // dnd iface
+
+    bool EnableDragSource( const wxDataFormat &format );
+    bool EnableDropTarget( const wxDataFormat &format );
+
     gboolean row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path );
     gboolean drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath* path );
     gboolean drag_data_get( GtkTreeDragSource *drag_source, GtkTreePath *path,
@@ -124,6 +123,14 @@ private:
     GtkSortType           m_sort_order;
     wxDataViewColumn     *m_dataview_sort_column;
     int                   m_sort_column;
+
+    GtkTargetEntry        m_dragSourceTargetEntry;
+    wxCharBuffer          m_dragSourceTargetEntryTarget;
+    wxDataObject         *m_dragDataObject;
+
+    GtkTargetEntry        m_dropTargetTargetEntry;
+    wxCharBuffer          m_dropTargetTargetEntryTarget;
+    wxDataObject         *m_dropDataObject;
 };
 
 
@@ -131,10 +138,11 @@ private:
 // wxGtkTreeModelNode
 //-----------------------------------------------------------------------------
 
+static
 int LINKAGEMODE wxGtkTreeModelChildCmp( void** id1, void** id2 )
 {
-    int ret = g_internal->GetDataViewModel()->Compare( *id1, *id2,
-        g_internal->GetSortColumn(), (g_internal->GetSortOrder() == GTK_SORT_ASCENDING) );
+    int ret = gs_internal->GetDataViewModel()->Compare( *id1, *id2,
+        gs_internal->GetSortColumn(), (gs_internal->GetSortOrder() == GTK_SORT_ASCENDING) );
 
     return ret;
 }
@@ -174,7 +182,7 @@ public:
 
             if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare())
             {
-                g_internal = m_internal;
+                gs_internal = m_internal;
                 m_children.Sort( &wxGtkTreeModelChildCmp );
                 return m_children.Index( id );
             }
@@ -188,7 +196,7 @@ public:
 
             if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare())
             {
-                g_internal = m_internal;
+                gs_internal = m_internal;
                 m_children.Sort( &wxGtkTreeModelChildCmp );
                 return m_children.Index( id );
             }
@@ -527,6 +535,8 @@ wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
 
     wxString wxtype = wxtree_model->internal->GetDataViewModel()->GetColumnType( (unsigned int) index );
 
+    wxPrintf( "get_column_type %s\n", wxtype );
+
     if (wxtype == wxT("string"))
         gtype = G_TYPE_STRING;
     else
@@ -631,8 +641,10 @@ wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
 {
     GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
-    g_return_val_if_fail (wxtree_model->stamp == iter->stamp, 0);
-
+    
+    if (iter != NULL)
+        g_return_val_if_fail (wxtree_model->stamp == iter->stamp, 0);
+        
     return wxtree_model->internal->iter_n_children( iter );
 }
 
@@ -975,11 +987,11 @@ static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
 {
     GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
     wxDataViewCustomRenderer *cell = wxrenderer->cell;
-    
+
     // Renderer doesn't support in-place editing
     if (!cell->HasEditorCtrl())
         return NULL;
-        
+
     // An in-place editing control is still around
     if (cell->GetEditorCtrl())
         return NULL;
@@ -1086,18 +1098,17 @@ gtk_wx_cell_renderer_render (GtkCellRenderer      *renderer,
     rect.y += cell_area->y;
     rect.width  -= renderer->xpad * 2;
     rect.height -= renderer->ypad * 2;
-        
+
     GdkRectangle dummy;
     if (gdk_rectangle_intersect (expose_area, &rect, &dummy))
     {
         wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
         wxWindowDC* dc = (wxWindowDC*) cell->GetDC();
         wxWindowDCImpl *impl = (wxWindowDCImpl *) dc->GetImpl();
-        if (impl->m_gdkwindow == NULL)
-        {
-            impl->m_gdkwindow = window;
-            impl->SetUpDC();
-        }
+        // Reinitilise GDK window everytime as drawing can also
+        // be done into DnD drop window.
+        impl->m_gdkwindow = window;
+        impl->SetUpDC();
 
         int state = 0;
         if (flags & GTK_CELL_RENDERER_SELECTED)
@@ -1477,18 +1488,18 @@ wxDataViewCellMode wxDataViewRenderer::GetMode() const
 void wxDataViewRenderer::GtkUpdateAlignment()
 {
     int align = m_alignment;
-    
+
     // query alignment from column ?
     if (align == -1)
     {
         // None there yet
         if (GetOwner() == NULL)
             return;
-        
+
         align = GetOwner()->GetAlignment();
         align |= wxALIGN_CENTRE_VERTICAL;
     }
-    
+
     // horizontal alignment:
 
     gfloat xalign = 0.0;
@@ -1541,7 +1552,7 @@ static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
 static void wxGtkTextRendererEditedCallback( GtkCellRendererText *WXUNUSED(renderer),
     gchar *arg1, gchar *arg2, gpointer user_data )
 {
-    wxDataViewTextRenderer *cell = (wxDataViewTextRenderer*) user_data;
+    wxDataViewRenderer *cell = (wxDataViewRenderer*) user_data;
 
     wxString tmp = wxGTK_CONV_BACK_FONT(arg2, cell->GetOwner()->GetOwner()->GetFont());
     wxVariant value = tmp;
@@ -1605,7 +1616,7 @@ bool wxDataViewTextRenderer::GetValue( wxVariant &value ) const
     GValue gvalue = { 0, };
     g_value_init( &gvalue, G_TYPE_STRING );
     g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
-    wxString tmp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), wx_const_cast(wxDataViewTextRenderer*, this)->GetOwner()->GetOwner()->GetFont() );
+    wxString tmp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), const_cast<wxDataViewTextRenderer*>(this)->GetOwner()->GetOwner()->GetFont() );
     g_value_unset( &gvalue );
 
     value = tmp;
@@ -2021,6 +2032,120 @@ wxSize wxDataViewProgressRenderer::GetSize() const
     return wxSize(40,12);
 }
 
+// -------------------------------------
+// wxDataViewChoiceRenderer
+// -------------------------------------
+
+wxDataViewChoiceRenderer::wxDataViewChoiceRenderer( const wxArrayString &choices,
+                            wxDataViewCellMode mode, int alignment  ) :
+    wxDataViewCustomRenderer( "string", mode, alignment, true )
+{
+   m_choices = choices;
+
+#ifdef __WXGTK26__
+    if (!gtk_check_version(2,6,0))
+    {
+        m_renderer = (GtkCellRenderer*) gtk_cell_renderer_combo_new();
+
+        GtkListStore *store = gtk_list_store_new( 1, G_TYPE_STRING );
+        size_t n;
+        for (n = 0; n < m_choices.GetCount(); n++)
+            gtk_list_store_insert_with_values( store, NULL, n, 0, m_choices[n].utf8_str(), -1 );
+
+        g_object_set (m_renderer,
+                "model", store,
+                "text-column", 0,
+                "has-entry", FALSE,
+                NULL);
+
+        bool editable = (mode & wxDATAVIEW_CELL_EDITABLE);
+        g_object_set (m_renderer, "editable", editable, NULL);
+
+        SetAlignment(alignment);
+
+        g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this );
+
+        GtkInitHandlers();
+    }
+    else
+#endif
+    {
+        // Use custom cell code
+        wxDataViewCustomRenderer::Init(mode, alignment);
+    }
+}
+
+bool wxDataViewChoiceRenderer::Render( wxRect rect, wxDC *dc, int state )
+{
+    RenderText( m_data, 0, rect, dc, state );
+    return true;
+}
+
+wxSize wxDataViewChoiceRenderer::GetSize() const
+{
+    return wxSize(70,20);
+}
+
+bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value )
+{
+
+#ifdef __WXGTK26__
+    if (!gtk_check_version(2,6,0))
+    {
+        GValue gvalue = { 0, };
+        g_value_init( &gvalue, G_TYPE_STRING );
+        g_value_set_string( &gvalue, wxGTK_CONV_FONT( value.GetString(), GetOwner()->GetOwner()->GetFont() ) );
+        g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
+        g_value_unset( &gvalue );
+    }
+    else
+#endif
+        m_data = value.GetString();
+
+    return true;
+}
+
+bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const
+{
+#ifdef __WXGTK26__
+    if (!gtk_check_version(2,6,0))
+    {
+        GValue gvalue = { 0, };
+        g_value_init( &gvalue, G_TYPE_STRING );
+        g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
+        wxString temp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), const_cast<wxDataViewTextRenderer*>(this)->GetOwner()->GetOwner()->GetFont() );
+        g_value_unset( &gvalue );
+        value = temp;
+        wxPrintf( "temp %s\n", temp );
+    }
+    else
+#endif
+        value = m_data;
+
+    return true;
+}
+
+void wxDataViewChoiceRenderer::SetAlignment( int align )
+{
+    wxDataViewCustomRenderer::SetAlignment(align);
+
+    if (gtk_check_version(2,10,0))
+        return;
+
+    // horizontal alignment:
+    PangoAlignment pangoAlign = PANGO_ALIGN_LEFT;
+    if (align & wxALIGN_RIGHT)
+        pangoAlign = PANGO_ALIGN_RIGHT;
+    else if (align & wxALIGN_CENTER_HORIZONTAL)
+        pangoAlign = PANGO_ALIGN_CENTER;
+
+    GValue gvalue = { 0, };
+    g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
+    g_value_set_enum( &gvalue, pangoAlign );
+    g_object_set_property( G_OBJECT(m_renderer), "alignment", &gvalue );
+    g_value_unset( &gvalue );
+}
+
 // ---------------------------------------------------------
 // wxDataViewDateRenderer
 // ---------------------------------------------------------
@@ -2401,26 +2526,23 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column),
 
 }
 
-IMPLEMENT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
-
 #include <wx/listimpl.cpp>
 WX_DEFINE_LIST(wxDataViewColumnList)
 
 wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell,
                                     unsigned int model_column, int width,
-                                    wxAlignment align, int flags ) :
-    wxDataViewColumnBase( title, cell, model_column, width, align, flags )
+                                    wxAlignment align, int flags )
+    : wxDataViewColumnBase( cell, model_column )
 {
     Init( align, flags, width );
 
-    gtk_tree_view_column_set_clickable( GTK_TREE_VIEW_COLUMN(m_column), TRUE );
     SetTitle( title );
 }
 
 wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell,
                                     unsigned int model_column, int width,
-                                    wxAlignment align, int flags ) :
-    wxDataViewColumnBase( bitmap, cell, model_column, width, align, flags )
+                                    wxAlignment align, int flags )
+    : wxDataViewColumnBase( bitmap, cell, model_column )
 {
     Init( align, flags, width );
 
@@ -2449,17 +2571,13 @@ void wxDataViewColumn::Init(wxAlignment align, int flags, int width)
     m_label = gtk_label_new("");
     gtk_box_pack_end( GTK_BOX(box), GTK_WIDGET(m_label), FALSE, FALSE, 1 );
     gtk_tree_view_column_set_widget( column, box );
-    
+
     gtk_tree_view_column_pack_end( column, renderer, TRUE );
 
     gtk_tree_view_column_set_cell_data_func( column, renderer,
         wxGtkTreeCellDataFunc, (gpointer) GetRenderer(), NULL );
 }
 
-wxDataViewColumn::~wxDataViewColumn()
-{
-}
-
 void wxDataViewColumn::OnInternalIdle()
 {
     if (m_isConnected)
@@ -2514,7 +2632,7 @@ void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap )
     {
         GtkImage *gtk_image = GTK_IMAGE(m_image);
 
-        GdkBitmap *mask = (GdkBitmap *) NULL;
+        GdkBitmap *mask = NULL;
         if (bitmap.GetMask())
             mask = bitmap.GetMask()->GetBitmap();
 
@@ -2558,7 +2676,7 @@ void wxDataViewColumn::SetAlignment( wxAlignment align )
         xalign = 0.5;
 
     gtk_tree_view_column_set_alignment( column, xalign );
-    
+
     if (m_renderer && m_renderer->GetAlignment() == -1)
         m_renderer->GtkUpdateAlignment();
 }
@@ -2579,7 +2697,7 @@ void wxDataViewColumn::SetSortable( bool sortable )
 {
     GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
 
-    if (sortable)
+    if ( sortable )
     {
         gtk_tree_view_column_set_sort_column_id( column, GetModelColumn() );
     }
@@ -2587,13 +2705,28 @@ void wxDataViewColumn::SetSortable( bool sortable )
     {
         gtk_tree_view_column_set_sort_column_id( column, -1 );
         gtk_tree_view_column_set_sort_indicator( column, FALSE );
+        gtk_tree_view_column_set_clickable( column, FALSE );
     }
 }
 
 bool wxDataViewColumn::IsSortable() const
 {
     GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
-    return (gtk_tree_view_column_get_sort_column_id( column ) != -1);
+    return gtk_tree_view_column_get_clickable( column );
+}
+
+void wxDataViewColumn::SetAsSortKey( bool WXUNUSED(sort) )
+{
+    // it might not make sense to have this function in wxHeaderColumn at
+    // all in fact, changing of the sort order should only be done using the
+    // associated control API
+    wxFAIL_MSG( "not implemented" );
+}
+
+bool wxDataViewColumn::IsSortKey() const
+{
+    GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+    return gtk_tree_view_column_get_sort_indicator( column );
 }
 
 bool wxDataViewColumn::IsResizeable() const
@@ -2700,7 +2833,7 @@ void wxGtkTreeModelNode::Resort()
     wxGtkTreeModelChildren temp;
     WX_APPEND_ARRAY( temp, m_children );
 
-    g_internal = m_internal;
+    gs_internal = m_internal;
     m_children.Sort( &wxGtkTreeModelChildCmp );
 
     gint *new_order = new gint[child_count];
@@ -2749,6 +2882,9 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
     m_sort_column = -1;
     m_dataview_sort_column = NULL;
 
+    m_dragDataObject = NULL;
+    m_dropDataObject = NULL;
+
     if (!m_wx_model->IsVirtualListModel())
         InitTree();
 }
@@ -2756,6 +2892,9 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
 wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
 {
     g_object_unref( m_gtk_model );
+
+    delete m_dragDataObject;
+    delete m_dropDataObject;
 }
 
 void wxDataViewCtrlInternal::InitTree()
@@ -2789,15 +2928,62 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node )
 
 // GTK+ dnd iface
 
+bool wxDataViewCtrlInternal::EnableDragSource( const wxDataFormat &format )
+{
+    wxGtkString atom_str( gdk_atom_name( format  ) );
+    m_dragSourceTargetEntryTarget = wxCharBuffer( atom_str );
+
+    m_dragSourceTargetEntry.target =  m_dragSourceTargetEntryTarget.data();
+    m_dragSourceTargetEntry.flags = 0;
+    m_dragSourceTargetEntry.info = static_cast<guint>(-1);
+
+    gtk_tree_view_enable_model_drag_source( GTK_TREE_VIEW(m_owner->GtkGetTreeView() ),
+       GDK_BUTTON1_MASK, &m_dragSourceTargetEntry, 1, (GdkDragAction) GDK_ACTION_COPY );
+
+    return true;
+}
+
+bool wxDataViewCtrlInternal::EnableDropTarget( const wxDataFormat &format )
+{
+    wxGtkString atom_str( gdk_atom_name( format  ) );
+    m_dropTargetTargetEntryTarget = wxCharBuffer( atom_str );
+
+    m_dropTargetTargetEntry.target =  m_dropTargetTargetEntryTarget.data();
+    m_dropTargetTargetEntry.flags = 0;
+    m_dropTargetTargetEntry.info = static_cast<guint>(-1);
+
+    gtk_tree_view_enable_model_drag_dest( GTK_TREE_VIEW(m_owner->GtkGetTreeView() ),
+       &m_dropTargetTargetEntry, 1, (GdkDragAction) GDK_ACTION_COPY );
+
+    return true;
+}
+
 gboolean wxDataViewCtrlInternal::row_draggable( GtkTreeDragSource *WXUNUSED(drag_source),
     GtkTreePath *path )
 {
+    delete m_dragDataObject;
+
     GtkTreeIter iter;
     if (!get_iter( &iter, path )) return FALSE;
-
     wxDataViewItem item( (void*) iter.user_data );
 
-    return m_wx_model->IsDraggable( item );
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetItem( item );
+    event.SetModel( m_wx_model );
+    if (!m_owner->HandleWindowEvent( event ))
+        return FALSE;
+
+    if (!event.IsAllowed())
+        return FALSE;
+
+    wxDataObject *obj = event.GetDataObject();
+    if (!obj)
+        return FALSE;
+
+    m_dragDataObject = obj;
+
+    return TRUE;
 }
 
 gboolean
@@ -2812,40 +2998,77 @@ gboolean wxDataViewCtrlInternal::drag_data_get( GtkTreeDragSource *WXUNUSED(drag
 {
     GtkTreeIter iter;
     if (!get_iter( &iter, path )) return FALSE;
-
     wxDataViewItem item( (void*) iter.user_data );
 
-    wxDataFormat format( selection_data->target );
+    if (!m_dragDataObject->IsSupported( selection_data->target ))
+        return FALSE;
 
-    size_t size = m_wx_model->GetDragDataSize( item, format );
-    if (size == 0) return FALSE;
+    size_t size = m_dragDataObject->GetDataSize( selection_data->target );
+    if (size == 0)
+        return FALSE;
 
-    void *data = malloc( size );
+    void *buf = malloc( size );
 
-    m_wx_model->GetDragData( item, format, data, size );
+    gboolean res = FALSE;
+    if (m_dragDataObject->GetDataHere( selection_data->target, buf ))
+    {
+        res = TRUE;
 
-    gtk_selection_data_set( selection_data, selection_data->target,
-        8, (const guchar*) data, size );
+        gtk_selection_data_set( selection_data, selection_data->target,
+            8, (const guchar*) buf, size );
+    }
 
-    free( data );
+    free( buf );
 
-    return TRUE;
+    return res;
 }
 
 gboolean
 wxDataViewCtrlInternal::drag_data_received(GtkTreeDragDest *WXUNUSED(drag_dest),
-                                           GtkTreePath *WXUNUSED(dest),
-                                           GtkSelectionData *WXUNUSED(selection_data))
+                                           GtkTreePath *path,
+                                           GtkSelectionData *selection_data)
 {
-    return FALSE;
+    GtkTreeIter iter;
+    if (!get_iter( &iter, path )) return FALSE;
+    wxDataViewItem item( (void*) iter.user_data );
+
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetItem( item );
+    event.SetModel( m_wx_model );
+    event.SetDataFormat( selection_data->target );
+    event.SetDataSize( selection_data->length );
+    event.SetDataBuffer( selection_data->data );
+    if (!m_owner->HandleWindowEvent( event ))
+        return FALSE;
+
+    if (!event.IsAllowed())
+        return FALSE;
+
+    return TRUE;
 }
 
 gboolean
 wxDataViewCtrlInternal::row_drop_possible(GtkTreeDragDest *WXUNUSED(drag_dest),
-                                          GtkTreePath *WXUNUSED(dest_path),
-                                          GtkSelectionData *WXUNUSED(selection_data))
+                                          GtkTreePath *path,
+                                          GtkSelectionData *selection_data)
 {
-    return FALSE;
+    GtkTreeIter iter;
+    if (!get_iter( &iter, path )) return FALSE;
+    wxDataViewItem item( (void*) iter.user_data );
+
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetItem( item );
+    event.SetModel( m_wx_model );
+    event.SetDataFormat( selection_data->target );
+    if (!m_owner->HandleWindowEvent( event ))
+        return FALSE;
+
+    if (!event.IsAllowed())
+        return FALSE;
+
+    return TRUE;
 }
 
 // notifications from wxDataViewModel
@@ -3121,6 +3344,9 @@ gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
     }
     else
     {
+        if (iter == NULL)
+            return m_root->GetChildCount();
+            
         wxDataViewItem item( (void*) iter->user_data );
 
         if (!m_wx_model->IsContainer( item ))
@@ -3583,12 +3809,10 @@ void wxDataViewCtrl::Init()
 {
     m_notifier = NULL;
     m_internal = NULL;
-    
+
     m_cols.DeleteContents( true );
 }
 
-static GtkTargetEntry gs_target;
-
 bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
            const wxPoint& pos, const wxSize& size,
            long style, const wxValidator& validator )
@@ -3613,12 +3837,6 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
     g_signal_connect (m_treeview, "size_allocate",
                      G_CALLBACK (gtk_dataviewctrl_size_callback), this);
 
-    gs_target.target = const_cast<char *>("UTF8_STRING");
-    gs_target.flags = 0;
-    gs_target.info = static_cast<guint>(-1);
-    gtk_tree_view_enable_model_drag_source( GTK_TREE_VIEW(m_treeview),
-       GDK_BUTTON1_MASK, &gs_target, 1, (GdkDragAction) GDK_ACTION_COPY );
-
 #ifdef __WXGTK26__
     if (!gtk_check_version(2,6,0))
     {
@@ -3656,7 +3874,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
     gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(m_treeview), (style & wxDV_ROW_LINES) != 0 );
 
     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
-        GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
     gtk_widget_show (m_treeview);
 
     m_parent->DoAddChild( this );
@@ -3740,6 +3958,16 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
     return true;
 }
 
+bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format )
+{
+    return m_internal->EnableDragSource( format );
+}
+
+bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format )
+{
+    return m_internal->EnableDropTarget( format );
+}
+
 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
 {
     if (!wxDataViewCtrlBase::AppendColumn(col))
@@ -3891,6 +4119,17 @@ void wxDataViewCtrl::Collapse( const wxDataViewItem & item )
     gtk_tree_path_free( path );
 }
 
+bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
+{
+    GtkTreeIter iter;
+    iter.user_data = item.GetID();
+    GtkTreePath *path = m_internal->get_path( &iter );
+    bool res = gtk_tree_view_row_expanded( GTK_TREE_VIEW(m_treeview), path );
+    gtk_tree_path_free( path );
+
+    return res;
+}
+
 wxDataViewItem wxDataViewCtrl::GetSelection() const
 {
     GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
@@ -3980,12 +4219,23 @@ void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )
 
     gtk_tree_selection_unselect_all( selection );
 
+    wxDataViewItem last_parent;
+
     size_t i;
     for (i = 0; i < sel.GetCount(); i++)
     {
+        wxDataViewItem item = sel[i];
+        wxDataViewItem parent = GetModel()->GetParent( item );
+        if (parent)
+        {
+            if (parent != last_parent)
+                ExpandAncestors(item);
+        }
+        last_parent = parent;
+
         GtkTreeIter iter;
         iter.stamp = m_internal->GetGtkModel()->stamp;
-        iter.user_data = (gpointer) sel[i].GetID();
+        iter.user_data = (gpointer) item.GetID();
         gtk_tree_selection_select_iter( selection, &iter );
     }
 
@@ -3994,6 +4244,8 @@ void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )
 
 void wxDataViewCtrl::Select( const wxDataViewItem & item )
 {
+    ExpandAncestors(item);
+
     GtkDisableSelectionEvents();
 
     GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
@@ -4056,6 +4308,8 @@ void wxDataViewCtrl::UnselectAll()
 void wxDataViewCtrl::EnsureVisible(const wxDataViewItem& item,
                                    const wxDataViewColumn *WXUNUSED(column))
 {
+    ExpandAncestors(item);
+
     GtkTreeIter iter;
     iter.user_data = (gpointer) item.GetID();
     GtkTreePath *path = m_internal->get_path( &iter );