+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+ if (bitmap.Ok())
+ {
+ GtkImage *gtk_image = GTK_IMAGE( gtk_image_new() );
+
+ GdkBitmap *mask = (GdkBitmap *) NULL;
+ if (bitmap.GetMask())
+ mask = bitmap.GetMask()->GetBitmap();
+
+ if (bitmap.HasPixbuf())
+ {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(gtk_image),
+ bitmap.GetPixbuf());
+ }
+ else
+ {
+ gtk_image_set_from_pixmap(GTK_IMAGE(gtk_image),
+ bitmap.GetPixmap(), mask);
+ }
+ gtk_widget_show( GTK_WIDGET(gtk_image) );
+
+ gtk_tree_view_column_set_widget( column, GTK_WIDGET(gtk_image) );
+ }
+ else
+ {
+ gtk_tree_view_column_set_widget( column, NULL );
+ }
+}
+
+void wxDataViewColumn::SetHidden( bool hidden )
+{
+ gtk_tree_view_column_set_visible( GTK_TREE_VIEW_COLUMN(m_column), !hidden );
+}
+
+void wxDataViewColumn::SetResizeable( bool resizeable )
+{
+ gtk_tree_view_column_set_resizable( GTK_TREE_VIEW_COLUMN(m_column), resizeable );
+}
+
+void wxDataViewColumn::SetAlignment( wxAlignment align )
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+
+ gfloat xalign = 0.0;
+ if (align == wxALIGN_RIGHT)
+ xalign = 1.0;
+ if (align == wxALIGN_CENTER_HORIZONTAL ||
+ align == wxALIGN_CENTER)
+ xalign = 0.5;
+
+ gtk_tree_view_column_set_alignment( column, xalign );
+}
+
+wxAlignment wxDataViewColumn::GetAlignment() const
+{
+ gfloat xalign = gtk_tree_view_column_get_alignment( GTK_TREE_VIEW_COLUMN(m_column) );
+
+ if (xalign == 1.0)
+ return wxALIGN_RIGHT;
+ if (xalign == 0.5)
+ return wxALIGN_CENTER_HORIZONTAL;
+
+ return wxALIGN_LEFT;
+}
+
+void wxDataViewColumn::SetSortable( bool sortable )
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+
+ if (sortable)
+ {
+ gtk_tree_view_column_set_sort_column_id( column, GetModelColumn() );
+ }
+ else
+ {
+ gtk_tree_view_column_set_sort_column_id( column, -1 );
+ gtk_tree_view_column_set_sort_indicator( 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);
+}
+
+bool wxDataViewColumn::IsResizeable() const
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+ return gtk_tree_view_column_get_resizable( column );
+}
+
+bool wxDataViewColumn::IsHidden() const
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+ return !gtk_tree_view_column_get_visible( column );
+}
+
+void wxDataViewColumn::SetSortOrder( bool ascending )
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+
+ if (ascending)
+ gtk_tree_view_column_set_sort_order( column, GTK_SORT_ASCENDING );
+ else
+ gtk_tree_view_column_set_sort_order( column, GTK_SORT_DESCENDING );
+
+ gtk_tree_view_column_set_sort_indicator( column, TRUE );
+}
+
+bool wxDataViewColumn::IsSortOrderAscending() const
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
+
+ return (gtk_tree_view_column_get_sort_order( column ) != GTK_SORT_DESCENDING);
+}
+
+void wxDataViewColumn::SetMinWidth( int width )
+{
+ gtk_tree_view_column_set_min_width( GTK_TREE_VIEW_COLUMN(m_column), width );
+}
+
+int wxDataViewColumn::GetMinWidth() const
+{
+ return gtk_tree_view_column_get_min_width( GTK_TREE_VIEW_COLUMN(m_column) );
+}
+
+int wxDataViewColumn::GetWidth() const
+{
+ return gtk_tree_view_column_get_width( GTK_TREE_VIEW_COLUMN(m_column) );
+}
+
+void wxDataViewColumn::SetWidth( int width )
+{
+ gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), width );
+}
+
+
+//-----------------------------------------------------------------------------
+// wxGtkTreeModelNode
+//-----------------------------------------------------------------------------
+
+void wxGtkTreeModelNode::Resort()
+{
+ size_t child_count = GetChildCount();
+ if (child_count == 0)
+ return;
+
+ size_t node_count = GetNodesCount();
+
+ if (child_count == 1)
+ {
+ if (node_count == 1)
+ {
+ wxGtkTreeModelNode *node = m_nodes.Item( 0 );
+ node->Resort();
+ }
+ return;
+ }
+
+ wxGtkTreeModelChildren temp;
+ WX_APPEND_ARRAY( temp, m_children );
+
+ g_internal = m_internal;
+ m_children.Sort( &wxGtkTreeModelChildCmp );
+
+ gint *new_order = new gint[child_count];
+
+ unsigned int pos;
+ for (pos = 0; pos < child_count; pos++)
+ {
+ void *id = m_children.Item( pos );
+ int old_pos = temp.Index( id );
+ new_order[pos] = old_pos;
+ }
+
+ GtkTreeModel *gtk_tree_model = GTK_TREE_MODEL( m_internal->GetGtkModel() );
+
+ GtkTreeIter iter;
+ iter.user_data = GetItem().GetID();
+ iter.stamp = m_internal->GetGtkModel()->stamp;
+
+ GtkTreePath *path = m_internal->get_path( &iter );
+
+ gtk_tree_model_rows_reordered( gtk_tree_model, path, &iter, new_order );
+
+ gtk_tree_path_free (path);
+
+ delete [] new_order;
+
+ for (pos = 0; pos < node_count; pos++)
+ {
+ wxGtkTreeModelNode *node = m_nodes.Item( pos );
+ node->Resort();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// wxDataViewCtrlInternal
+//-----------------------------------------------------------------------------
+
+wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
+ wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model )
+{
+ m_owner = owner;
+ m_wx_model = wx_model;
+ m_gtk_model = gtk_model;
+ m_root = NULL;
+ m_sort_order = GTK_SORT_ASCENDING;
+ m_sort_column = -1;
+ m_dataview_sort_column = NULL;
+ InitTree();
+}
+
+wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
+{
+ g_object_unref( m_gtk_model );
+}
+
+void wxDataViewCtrlInternal::InitTree()
+{
+ wxDataViewItem item;
+ m_root = new wxGtkTreeModelNode( NULL, item, this );
+
+ BuildBranch( m_root );
+}
+
+void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node )
+{
+ if (node->GetChildCount() == 0)
+ {
+ wxDataViewItemArray children;
+ unsigned int count = m_wx_model->GetChildren( node->GetItem(), children );
+ unsigned int pos;
+ for (pos = 0; pos < count; pos++)
+ {
+ wxDataViewItem child = children[pos];
+
+ if (m_wx_model->IsContainer( child ))
+ node->AddNode( new wxGtkTreeModelNode( node, child, this ) );
+ else
+ node->AddLeave( child.GetID() );
+
+ // Don't send any events here
+ }
+ }
+}
+
+void wxDataViewCtrlInternal::Resort()
+{
+ m_root->Resort();
+}
+
+bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ if (m_wx_model->IsContainer( item ))
+ parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) );
+ else
+ parent_node->AddLeave( item.GetID() );
+
+ return true;
+}
+
+bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ parent_node->DeleteChild( item.GetID() );
+
+ return true;
+}
+
+bool wxDataViewCtrlInternal::ItemChanged( const wxDataViewItem &item )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() );
+ event.SetEventObject( m_owner );
+ event.SetModel( m_owner->GetModel() );
+ event.SetItem( item );
+ m_owner->GetEventHandler()->ProcessEvent( event );
+
+ return true;
+}
+
+bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned int col )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() );
+ event.SetEventObject( m_owner );
+ event.SetModel( m_owner->GetModel() );
+ event.SetColumn( col );
+ event.SetDataViewColumn( GetOwner()->GetColumn(col) );
+ event.SetItem( item );
+ m_owner->GetEventHandler()->ProcessEvent( event );
+
+ return true;
+}
+
+bool wxDataViewCtrlInternal::Cleared()
+{
+ return true;
+}
+
+gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path )
+{
+ int depth = gtk_tree_path_get_depth( path );
+
+ wxGtkTreeModelNode *node = m_root;
+
+ int i;
+ for (i = 0; i < depth; i++)
+ {
+ BuildBranch( node );
+
+ gint pos = gtk_tree_path_get_indices (path)[i];
+ if (pos < 0) return FALSE;
+ if ((size_t)pos >= node->GetChildCount()) return FALSE;
+
+ void* id = node->GetChildren().Item( (size_t) pos );
+
+ if (i == depth-1)
+ {
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = id;
+ return TRUE;
+ }
+
+ size_t count = node->GetNodes().GetCount();
+ size_t pos2;
+ for (pos2 = 0; pos2 < count; pos2++)
+ {
+ wxGtkTreeModelNode *child_node = node->GetNodes().Item( pos2 );
+ if (child_node->GetItem().GetID() == id)
+ {
+ node = child_node;
+ break;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
+{
+ GtkTreePath *retval = gtk_tree_path_new ();
+ void *id = iter->user_data;
+
+ wxGtkTreeModelNode *node = FindParentNode( iter );
+ while (node)
+ {
+ int pos = node->GetChildren().Index( id );
+
+ gtk_tree_path_prepend_index( retval, pos );
+
+ id = node->GetItem().GetID();
+ node = node->GetParent();
+ }
+
+ return retval;
+}
+
+gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
+{
+ wxGtkTreeModelNode *parent = FindParentNode( iter );
+ if( parent == NULL )
+ return FALSE;
+
+ int pos = parent->GetChildren().Index( iter->user_data );
+
+ if (pos == (int) parent->GetChildCount()-1)
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = parent->GetChildren().Item( pos+1 );
+
+ return TRUE;
+}
+
+gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent )
+{
+ wxDataViewItem item( (void*) parent->user_data );
+
+ if (!m_wx_model->IsContainer( item ))
+ return FALSE;
+
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ BuildBranch( parent_node );
+
+ if (parent_node->GetChildCount() == 0)
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = (gpointer) parent_node->GetChildren().Item( 0 );
+
+ return TRUE;
+}
+
+gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter )
+{
+ wxDataViewItem item( (void*) iter->user_data );
+
+ bool is_container = m_wx_model->IsContainer( item );
+
+ if (!is_container)
+ return FALSE;
+
+ wxGtkTreeModelNode *node = FindNode( iter );
+ BuildBranch( node );
+
+ return (node->GetChildCount() > 0);
+}
+
+gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
+{
+ wxDataViewItem item( (void*) iter->user_data );
+
+ if (!m_wx_model->IsContainer( item ))
+ return 0;
+
+ wxGtkTreeModelNode *parent_node = FindNode( iter );
+ BuildBranch( parent_node );
+
+ // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() );
+
+ return parent_node->GetChildCount();
+}
+
+gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n )
+{
+ void* id = NULL;
+ if (parent) id = (void*) parent->user_data;
+ wxDataViewItem item( id );
+
+ if (!m_wx_model->IsContainer( item ))
+ return FALSE;
+
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ BuildBranch( parent_node );
+
+ // wxPrintf( "iter_nth_child %d\n", n );
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = parent_node->GetChildren().Item( n );
+
+ return TRUE;
+}
+
+gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child )
+{
+ wxGtkTreeModelNode *node = FindParentNode( child );
+ if (!node)
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = (gpointer) node->GetItem().GetID();
+
+ return TRUE;
+}
+
+static wxGtkTreeModelNode*
+wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
+{
+ if( model == NULL )
+ return NULL;
+
+ ItemList list;
+ list.DeleteContents( true );
+ wxDataViewItem it( item );
+
+ while( it.IsOk() )
+ {
+ wxDataViewItem * pItem = new wxDataViewItem( it );
+ list.Insert( pItem );
+ it = model->GetParent( it );
+ }
+
+ wxGtkTreeModelNode * node = treeNode;
+ for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
+ {
+ if( node && node->GetNodes().GetCount() != 0 )
+ {
+ int len = node->GetNodes().GetCount();
+ wxGtkTreeModelNodes nodes = node->GetNodes();
+ int j = 0;
+ for( ; j < len; j ++)
+ {
+ if( nodes[j]->GetItem() == *(n->GetData()))
+ {
+ node = nodes[j];
+ break;
+ }
+ }
+
+ if( j == len )
+ {
+ return NULL;
+ }
+ }
+ else
+ return NULL;
+ }
+ return node;
+
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter )
+{
+ if (!iter)
+ return m_root;
+
+ wxDataViewItem item( (void*) iter->user_data );
+ if (!item.IsOk())
+ return m_root;
+
+ wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
+
+ if (!result)
+ {
+ wxLogDebug( "Not found %p", iter->user_data );
+ char *crash = NULL;
+ *crash = 0;
+ }
+
+ return result;
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item )
+{
+ if (!item.IsOk())
+ return m_root;
+
+ wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
+
+ if (!result)
+ {
+ wxLogDebug( "Not found %p", item.GetID() );
+ char *crash = NULL;
+ *crash = 0;
+ }
+
+ return result;
+}
+
+static wxGtkTreeModelNode*
+wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
+{
+ if( model == NULL )
+ return NULL;
+
+ ItemList list;
+ list.DeleteContents( true );
+ if( !item.IsOk() )
+ return NULL;
+
+ wxDataViewItem it( model->GetParent( item ) );
+ while( it.IsOk() )
+ {
+ wxDataViewItem * pItem = new wxDataViewItem( it );
+ list.Insert( pItem );
+ it = model->GetParent( it );
+ }
+
+ wxGtkTreeModelNode * node = treeNode;
+ for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
+ {
+ if( node && node->GetNodes().GetCount() != 0 )
+ {
+ int len = node->GetNodes().GetCount();
+ wxGtkTreeModelNodes nodes = node->GetNodes();
+ int j = 0;
+ for( ; j < len; j ++)
+ {
+ if( nodes[j]->GetItem() == *(n->GetData()))
+ {
+ node = nodes[j];
+ break;
+ }
+ }
+
+ if( j == len )
+ {
+ return NULL;
+ }
+ }
+ else
+ return NULL;
+ }
+ //Examine whether the node is item's parent node
+ int len = node->GetChildCount();
+ for( int i = 0; i < len ; i ++ )
+ {
+ if( node->GetChildren().Item( i ) == item.GetID() )
+ return node;
+ }
+ return NULL;
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( GtkTreeIter *iter )
+{
+ if (!iter)
+ return NULL;
+
+ wxDataViewItem item( (void*) iter->user_data );
+ if (!item.IsOk())
+ return NULL;
+
+ return wxDataViewCtrlInternal_FindParentNode( m_wx_model, m_root, item );
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( const wxDataViewItem &item )
+{
+ if (!item.IsOk())
+ return NULL;
+
+ return wxDataViewCtrlInternal_FindParentNode( m_wx_model, m_root, item );
+}
+
+//-----------------------------------------------------------------------------
+// wxDataViewCtrl signal callbacks
+//-----------------------------------------------------------------------------
+
+static void
+wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCtrl *dv )
+{
+ if (!GTK_WIDGET_REALIZED(dv->m_widget))
+ return;
+
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, dv->GetId() );
+ event.SetItem( dv->GetSelection() );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+}
+
+static void
+wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path,
+ GtkTreeViewColumn *column, wxDataViewCtrl *dv )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, dv->GetId() );
+
+ GtkTreeIter iter;
+ dv->GtkGetInternal()->get_iter( &iter, path );
+ wxDataViewItem item( (void*) iter.user_data );;
+ event.SetItem( item );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+}
+
+static gboolean
+wxdataview_test_expand_row_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+ GtkTreePath *path, wxDataViewCtrl *dv )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, dv->GetId() );
+
+ wxDataViewItem item( (void*) iter->user_data );;
+ event.SetItem( item );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+
+ return !event.IsAllowed();
+}
+
+static void
+wxdataview_row_expanded_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+ GtkTreePath *path, wxDataViewCtrl *dv )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, dv->GetId() );
+
+ wxDataViewItem item( (void*) iter->user_data );;
+ event.SetItem( item );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+}
+
+static gboolean
+wxdataview_test_collapse_row_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+ GtkTreePath *path, wxDataViewCtrl *dv )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, dv->GetId() );
+
+ wxDataViewItem item( (void*) iter->user_data );;
+ event.SetItem( item );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+
+ return !event.IsAllowed();
+}
+
+static void
+wxdataview_row_collapsed_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+ GtkTreePath *path, wxDataViewCtrl *dv )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, dv->GetId() );
+
+ wxDataViewItem item( (void*) iter->user_data );;
+ event.SetItem( item );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+}
+
+//-----------------------------------------------------------------------------
+ // wxDataViewCtrl
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// InsertChild for wxDataViewCtrl
+//-----------------------------------------------------------------------------
+
+static void wxInsertChildInDataViewCtrl( wxWindowGTK* parent, wxWindowGTK* child )
+{
+ wxDataViewCtrl * dvc = (wxDataViewCtrl*) parent;
+ GtkWidget *treeview = dvc->GtkGetTreeView();
+
+ // Insert widget in GtkTreeView
+ if (GTK_WIDGET_REALIZED(treeview))
+ gtk_widget_set_parent_window( child->m_widget,
+ gtk_tree_view_get_bin_window( GTK_TREE_VIEW(treeview) ) );
+ gtk_widget_set_parent( child->m_widget, treeview );
+}
+
+static
+void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget),
+ GtkAllocation *alloc,
+ wxDataViewCtrl *win )
+{
+ wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
+ while (node)
+ {
+ wxWindow *child = node->GetData();
+
+ GtkRequisition req;
+ gtk_widget_size_request( child->m_widget, &req );
+
+ GtkAllocation alloc;
+ alloc.x = child->m_x;
+ alloc.y = child->m_y;
+ alloc.width = child->m_width;
+ alloc.height = child->m_height;
+ gtk_widget_size_allocate( child->m_widget, &alloc );
+
+ node = node->GetNext();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// "motion_notify_event"
+//-----------------------------------------------------------------------------
+
+static gboolean
+gtk_dataview_motion_notify_callback( GtkWidget *widget,
+ GdkEventMotion *gdk_event,
+ wxDataViewCtrl *dv )
+{
+ if (gdk_event->is_hint)
+ {
+ int x = 0;
+ int y = 0;
+ GdkModifierType state;
+ gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+ gdk_event->x = x;
+ gdk_event->y = y;
+ }
+
+ GtkTreePath *path = NULL;
+ GtkTreeViewColumn *column = NULL;
+ gint cell_x = 0;
+ gint cell_y = 0;
+ if (gtk_tree_view_get_path_at_pos(
+ GTK_TREE_VIEW(dv->GtkGetTreeView()),
+ (int) gdk_event->x, (int) gdk_event->y,
+ &path,
+ &column,
+ &cell_x,
+ &cell_y))
+ {
+ if (path)
+ {
+ GtkTreeIter iter;
+ dv->GtkGetInternal()->get_iter( &iter, path );
+
+ // wxPrintf( "mouse %d %d\n", (int) gdk_event->x, (int) gdk_event->y );
+
+ gtk_tree_path_free( path );
+ }
+ }
+
+
+ return FALSE;
+}
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
+
+wxDataViewCtrl::~wxDataViewCtrl()
+{
+ if (m_notifier)
+ GetModel()->RemoveNotifier( m_notifier );
+
+ // remove the model from the GtkTreeView before it gets destroyed by the
+ // wxDataViewCtrlBase's dtor
+ gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), NULL );
+
+ delete m_internal;
+}
+
+void wxDataViewCtrl::Init()
+{
+ m_notifier = NULL;
+}
+
+bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,