X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6989272940123609336605ddbc1ebe3db001ccb1..c5288c5cfebea56239369dddcce8ac3ef6f4a8dd:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 54de7c95c8..9b7df0db61 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -43,7 +43,9 @@ //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -wxDataViewModel *g_model = NULL; +class wxDataViewCtrlInternal; + +wxDataViewCtrlInternal *g_internal = NULL; class wxGtkTreeModelNode; @@ -66,7 +68,6 @@ public: gboolean get_iter( GtkTreeIter *iter, GtkTreePath *path ); GtkTreePath *get_path( GtkTreeIter *iter); - GtkTreePath *get_path_safe( GtkTreeIter *iter); gboolean iter_next( GtkTreeIter *iter ); gboolean iter_children( GtkTreeIter *iter, GtkTreeIter *parent); gboolean iter_has_child( GtkTreeIter *iter ); @@ -79,12 +80,21 @@ public: GtkWxTreeModel* GetGtkModel() { return m_gtk_model; } bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ); - bool ItemDeleted( const wxDataViewItem &item ); + bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ); bool ItemChanged( const wxDataViewItem &item ); bool ValueChanged( const wxDataViewItem &item, unsigned int col ); bool Cleared(); void Resort(); + void SetSortOrder( GtkSortType sort_order ) { m_sort_order = sort_order; } + GtkSortType GetSortOrder() { return m_sort_order; } + + void SetSortColumn( int column ) { m_sort_column = column; } + int GetSortColumn() { return m_sort_column; } + + bool IsSorted() { return (m_sort_column >= 0); } + + protected: void InitTree(); wxGtkTreeModelNode *FindNode( const wxDataViewItem &item ); @@ -98,6 +108,8 @@ private: wxDataViewModel *m_wx_model; GtkWxTreeModel *m_gtk_model; wxDataViewCtrl *m_owner; + GtkSortType m_sort_order; + int m_sort_column; }; @@ -105,10 +117,16 @@ private: // wxGtkTreeModelNode //----------------------------------------------------------------------------- -int LINKAGEMODE wxGtkTreeModelNodeCmp( void *id1, void *id2 ); +int LINKAGEMODE wxGtkTreeModelChildCmp( void** id1, void** id2 ) +{ + int ret = g_internal->GetDataViewModel()->Compare( *id1, *id2, + g_internal->GetSortColumn(), (g_internal->GetSortOrder() == GTK_SORT_ASCENDING) ); + + return ret; +} WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes ); -WX_DEFINE_SORTED_ARRAY( void* , wxGtkTreeModelChildren ); +WX_DEFINE_ARRAY_PTR( void*, wxGtkTreeModelChildren ); class wxGtkTreeModelNode { @@ -119,50 +137,57 @@ public: m_parent = parent; m_item = item; m_internal = internal; - g_model = internal->GetDataViewModel(); - m_children = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp ); } ~wxGtkTreeModelNode() { - g_model = m_internal->GetDataViewModel(); - size_t count = m_children->GetCount(); + size_t count = m_children.GetCount(); size_t i; for (i = 0; i < count; i++) { wxGtkTreeModelNode *child = m_nodes.Item( i ); delete child; } - delete m_children; } unsigned int AddNode( wxGtkTreeModelNode* child ) { - g_model = m_internal->GetDataViewModel(); m_nodes.Add( child ); - return m_children->Add( child->GetItem().GetID() ); + + void *id = child->GetItem().GetID(); + + m_children.Add( id ); + + if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare()) + { + g_internal = m_internal; + m_children.Sort( &wxGtkTreeModelChildCmp ); + return m_children.Index( id ); + } + + return m_children.GetCount()-1; } unsigned int AddLeave( void* id ) { - g_model = m_internal->GetDataViewModel(); - return m_children->Add( id ); + m_children.Add( id ); + + if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare()) + { + g_internal = m_internal; + m_children.Sort( &wxGtkTreeModelChildCmp ); + return m_children.Index( id ); + } + + return m_children.GetCount()-1; } void DeleteChild( void* id ) { - g_model = m_internal->GetDataViewModel(); - size_t pos; - size_t count = m_children->GetCount(); - for (pos = 0; pos < count; pos++) - { - if (m_children->Item( pos ) == id) - { - m_children->RemoveAt( pos ); - break; - } - } - count = m_nodes.GetCount(); + m_children.Remove( id ); + + unsigned int count = m_nodes.GetCount(); + unsigned int pos; for (pos = 0; pos < count; pos++) { wxGtkTreeModelNode *node = m_nodes.Item( pos ); @@ -181,9 +206,9 @@ public: wxGtkTreeModelNodes &GetNodes() { return m_nodes; } wxGtkTreeModelChildren &GetChildren() - { return *m_children; } + { return m_children; } - unsigned int GetChildCount() { return m_children->GetCount(); } + unsigned int GetChildCount() { return m_children.GetCount(); } unsigned int GetNodesCount() { return m_nodes.GetCount(); } wxDataViewItem &GetItem() { return m_item; } @@ -194,17 +219,12 @@ public: private: wxGtkTreeModelNode *m_parent; wxGtkTreeModelNodes m_nodes; - wxGtkTreeModelChildren *m_children; + wxGtkTreeModelChildren m_children; wxDataViewItem m_item; wxDataViewCtrlInternal *m_internal; }; -int LINKAGEMODE wxGtkTreeModelNodeCmp( void* id1, void* id2 ) -{ - return g_model->Compare( id1, id2 ); -} - //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- @@ -257,8 +277,6 @@ static gboolean wxgtk_tree_model_get_iter (GtkTreeModel *tree_mo GtkTreePath *path); static GtkTreePath *wxgtk_tree_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter); -static GtkTreePath *wxgtk_tree_model_get_path_safe (GtkTreeModel *tree_model, - GtkTreeIter *iter); static void wxgtk_tree_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, @@ -474,17 +492,6 @@ wxgtk_tree_model_get_path (GtkTreeModel *tree_model, return wxtree_model->internal->get_path( iter ); } -static GtkTreePath * -wxgtk_tree_model_get_path_safe (GtkTreeModel *tree_model, - GtkTreeIter *iter) -{ - GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), NULL); - g_return_val_if_fail (iter->stamp == GTK_WX_TREE_MODEL (wxtree_model)->stamp, NULL); - - return wxtree_model->internal->get_path_safe( iter ); -} - static void wxgtk_tree_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, @@ -589,43 +596,48 @@ gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortabl g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE); + if (!tree_model->internal->IsSorted()) + { + if (sort_column_id) + *sort_column_id = -1; + + return TRUE; + } + + if (sort_column_id) - *sort_column_id = tree_model->internal->GetDataViewModel()->GetSortingColumn(); + *sort_column_id = tree_model->internal->GetSortColumn(); if (order) - { - bool ascending = tree_model->internal->GetDataViewModel()->GetSortOrderAscending(); - if (ascending) - *order = GTK_SORT_ASCENDING; - else - *order = GTK_SORT_DESCENDING; - } + *order = tree_model->internal->GetSortOrder(); return TRUE; } -void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, +void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order) { GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); - bool ascending = TRUE; - if (order != GTK_SORT_ASCENDING) - ascending = FALSE; - - if ((sort_column_id == (gint) tree_model->internal->GetDataViewModel()->GetSortingColumn()) && - (ascending == tree_model->internal->GetDataViewModel()->GetSortOrderAscending())) + if ((sort_column_id == (gint) tree_model->internal->GetSortColumn()) && + (order == tree_model->internal->GetSortOrder())) return; - tree_model->internal->GetDataViewModel()->SetSortingColumn( sort_column_id ); + tree_model->internal->SetSortColumn( sort_column_id ); - tree_model->internal->GetDataViewModel()->SetSortOrderAscending( ascending ); + tree_model->internal->SetSortOrder( order ); gtk_tree_sortable_sort_column_changed (sortable); tree_model->internal->GetDataViewModel()->Resort(); + + wxDataViewCtrl *dv = tree_model->internal->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, dv->GetId() ); + // TODO event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + dv->GetEventHandler()->ProcessEvent( event ); } void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable, @@ -1022,7 +1034,7 @@ public: ~wxGtkDataViewModelNotifier(); virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ); - virtual bool ItemDeleted( const wxDataViewItem &item ); + virtual bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ); virtual bool ItemChanged( const wxDataViewItem &item ); virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col ); virtual bool Cleared(); @@ -1069,19 +1081,19 @@ bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const return true; } -bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &item ) +bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ) { GtkTreeIter iter; iter.stamp = m_wxgtk_model->stamp; iter.user_data = (gpointer) item.GetID(); - GtkTreePath *path = wxgtk_tree_model_get_path_safe( + GtkTreePath *path = wxgtk_tree_model_get_path( GTK_TREE_MODEL(m_wxgtk_model), &iter ); gtk_tree_model_row_deleted( GTK_TREE_MODEL(m_wxgtk_model), path ); gtk_tree_path_free (path); - m_owner->GtkGetInternal()->ItemDeleted( item ); + m_owner->GtkGetInternal()->ItemDeleted( parent, item ); return true; } @@ -1161,6 +1173,51 @@ bool wxGtkDataViewModelNotifier::Cleared() // wxDataViewRenderer // --------------------------------------------------------- +static gpointer s_user_data = NULL; + +static void +wxgtk_cell_editable_editing_done( GtkCellEditable *editable, + wxDataViewRenderer *wxrenderer ) +{ + wxDataViewColumn *column = wxrenderer->GetOwner(); + wxDataViewCtrl *dv = column->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, dv->GetId() ); + event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + wxDataViewItem item( s_user_data ); + event.SetItem( item ); + dv->GetEventHandler()->ProcessEvent( event ); +} + +static void +wxgtk_renderer_editing_started( GtkCellRenderer *cell, GtkCellEditable *editable, + gchar *path, wxDataViewRenderer *wxrenderer ) +{ + wxDataViewColumn *column = wxrenderer->GetOwner(); + wxDataViewCtrl *dv = column->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv->GetId() ); + event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + GtkTreePath *tree_path = gtk_tree_path_new_from_string( path ); + GtkTreeIter iter; + dv->GtkGetInternal()->get_iter( &iter, tree_path ); + gtk_tree_path_free( tree_path ); + wxDataViewItem item( iter.user_data ); + event.SetItem( item ); + dv->GetEventHandler()->ProcessEvent( event ); + + if (GTK_IS_CELL_EDITABLE(editable)) + { + s_user_data = iter.user_data; + + g_signal_connect (GTK_CELL_EDITABLE (editable), "editing_done", + G_CALLBACK (wxgtk_cell_editable_editing_done), + (gpointer) wxrenderer ); + + } +} + + IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase) wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode, @@ -1173,6 +1230,16 @@ wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewC // after the m_renderer pointer has been initialized } +void wxDataViewRenderer::GtkInitHandlers() +{ + if (!gtk_check_version(2,6,0)) + { + g_signal_connect (GTK_CELL_RENDERER(m_renderer), "editing_started", + G_CALLBACK (wxgtk_renderer_editing_started), + this); + } +} + void wxDataViewRenderer::SetMode( wxDataViewCellMode mode ) { GtkCellRendererMode gtkMode; @@ -1337,6 +1404,8 @@ wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxD g_value_unset( &gvalue ); g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this ); + + GtkInitHandlers(); } SetMode(mode); @@ -1600,6 +1669,8 @@ bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode, int align) SetMode(mode); SetAlignment(align); + GtkInitHandlers(); + return true; } @@ -1819,6 +1890,67 @@ bool wxDataViewDateRenderer::Activate( wxRect cell, wxDataViewModel *model, return true; } + +// --------------------------------------------------------- +// wxDataViewIconTextRenderer +// --------------------------------------------------------- + +IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer) + +wxDataViewIconTextRenderer::wxDataViewIconTextRenderer( + const wxString &varianttype, wxDataViewCellMode mode, int align ) : + wxDataViewCustomRenderer( varianttype, mode, align ) +{ + SetMode(mode); + SetAlignment(align); +} + +wxDataViewIconTextRenderer::~wxDataViewIconTextRenderer() +{ +} + +bool wxDataViewIconTextRenderer::SetValue( const wxVariant &value ) +{ + m_value << value; + return true; +} + +bool wxDataViewIconTextRenderer::GetValue( wxVariant &value ) const +{ + return false; +} + +bool wxDataViewIconTextRenderer::Render( wxRect cell, wxDC *dc, int state ) +{ + dc->SetFont( GetOwner()->GetOwner()->GetFont() ); + + const wxIcon &icon = m_value.GetIcon(); + if (icon.IsOk()) + { + dc->DrawIcon( icon, cell.x, cell.y ); // TODO centre + cell.x += icon.GetWidth()+4; + } + + dc->DrawText( m_value.GetText(), cell.x, cell.y ); + + return true; +} + +wxSize wxDataViewIconTextRenderer::GetSize() const +{ + return wxSize(80,16); // TODO +} + +wxControl* wxDataViewIconTextRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value ) +{ + return NULL; +} + +bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl( wxControl* editor, wxVariant &value ) +{ + return false; +} + // --------------------------------------------------------- // wxDataViewColumn // --------------------------------------------------------- @@ -1839,7 +1971,7 @@ gtk_dataview_header_button_press_callback( GtkWidget *widget, event.SetDataViewColumn( column ); event.SetModel( dv->GetModel() ); if (dv->GetEventHandler()->ProcessEvent( event )) - return TRUE; + return FALSE; } return FALSE; @@ -1906,6 +2038,9 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, IMPLEMENT_CLASS(wxDataViewColumn, wxDataViewColumnBase) +#include +WX_DEFINE_LIST(wxDataViewColumnList); + wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, unsigned int model_column, int width, wxAlignment align, int flags ) : @@ -2085,9 +2220,14 @@ 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 @@ -2116,6 +2256,8 @@ void wxDataViewColumn::SetSortOrder( bool 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 @@ -2152,8 +2294,6 @@ void wxDataViewColumn::SetWidth( int width ) void wxGtkTreeModelNode::Resort() { - g_model = m_internal->GetDataViewModel(); - size_t child_count = GetChildCount(); if (child_count == 0) return; @@ -2170,51 +2310,30 @@ void wxGtkTreeModelNode::Resort() return; } - wxGtkTreeModelChildren *new_array = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp ); - - size_t pos; - for (pos = 0; pos < child_count; pos++) - new_array->Add( m_children->Item( pos ) ); + 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 = new_array->Item( pos ); - size_t old_pos; - for (old_pos = 0; old_pos < child_count; old_pos++) - { - if (id == m_children->Item(old_pos)) - { - new_order[pos] = old_pos; - break; - } - } + void *id = m_children.Item( pos ); + int old_pos = temp.Index( id ); + new_order[pos] = old_pos; } -// for (pos = 0; pos < count; pos++) -// m_children->Clear(); - delete m_children; - - m_children = new_array; - GtkTreeModel *gtk_tree_model = GTK_TREE_MODEL( m_internal->GetGtkModel() ); - GtkTreePath *path = gtk_tree_path_new (); - wxGtkTreeModelNode *parent = GetParent(); - void *id = GetItem().GetID(); - - while (parent) - { - int pos = parent->GetChildren().Index( id ); - gtk_tree_path_prepend_index( path, pos ); - id = parent->GetItem().GetID(); - parent = parent->GetParent(); - } - GtkTreeIter iter; - iter.user_data = id; + 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); @@ -2239,6 +2358,8 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, m_wx_model = wx_model; m_gtk_model = gtk_model; m_root = NULL; + m_sort_order = GTK_SORT_ASCENDING; + m_sort_column = -1; InitTree(); } @@ -2259,17 +2380,19 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node ) { if (node->GetChildCount() == 0) { - wxDataViewItem child = m_wx_model->GetFirstChild( node->GetItem() ); - while (child.IsOk()) + 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 - - child = m_wx_model->GetNextSibling( child ); } } } @@ -2296,10 +2419,10 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa return true; } -bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &item ) +bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ) { - wxGtkTreeModelNode *parent = FindParentNode( item ); - parent->DeleteChild( item.GetID() ); + wxGtkTreeModelNode *parent_node = FindNode( parent ); + parent_node->DeleteChild( item.GetID() ); wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED, m_owner->GetId() ); event.SetEventObject( m_owner ); @@ -2345,8 +2468,6 @@ bool wxDataViewCtrlInternal::Cleared() gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path ) { - g_model = m_wx_model; - int depth = gtk_tree_path_get_depth( path ); wxGtkTreeModelNode *node = m_root; @@ -2387,8 +2508,6 @@ gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) { - g_model = m_wx_model; - GtkTreePath *retval = gtk_tree_path_new (); void *id = iter->user_data; @@ -2396,6 +2515,7 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) while (node) { int pos = node->GetChildren().Index( id ); + gtk_tree_path_prepend_index( retval, pos ); id = node->GetItem().GetID(); @@ -2405,44 +2525,15 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) return retval; } -GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter ) -{ - g_model = m_wx_model; - - GtkTreePath *retval = gtk_tree_path_new (); - void *id = iter->user_data; - - wxGtkTreeModelNode *node = FindParentNode( iter ); - while (node) - { - size_t pos; - for (pos = 0; pos < node->GetChildren().GetCount(); pos++) - { - if (id == node->GetChildren().Item( pos )) - { - gtk_tree_path_prepend_index( retval, (int) pos ); - continue; - } - } - - id = node->GetItem().GetID(); - node = node->GetParent(); - } - - return retval; -} - gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) { - g_model = m_wx_model; - wxGtkTreeModelNode *parent = FindParentNode( iter ); if( parent == NULL ) return FALSE; - unsigned int pos = parent->GetChildren().Index( iter->user_data ); - - if (pos == parent->GetChildCount()-1) + int pos = parent->GetChildren().Index( iter->user_data ); + + if (pos == (int) parent->GetChildCount()-1) return FALSE; iter->stamp = m_gtk_model->stamp; @@ -2453,8 +2544,6 @@ gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent ) { - g_model = m_wx_model; - wxDataViewItem item( (void*) parent->user_data ); if (!m_wx_model->IsContainer( item )) @@ -2474,8 +2563,6 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter * gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) { - g_model = m_wx_model; - wxDataViewItem item( (void*) iter->user_data ); bool is_container = m_wx_model->IsContainer( item ); @@ -2490,8 +2577,6 @@ gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) { - g_model = m_wx_model; - wxDataViewItem item( (void*) iter->user_data ); if (!m_wx_model->IsContainer( item )) @@ -2507,8 +2592,6 @@ gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ) { - g_model = m_wx_model; - void* id = NULL; if (parent) id = (void*) parent->user_data; wxDataViewItem item( id ); @@ -2529,8 +2612,6 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child ) { - g_model = m_wx_model; - wxGtkTreeModelNode *node = FindParentNode( child ); if (!node) return FALSE; @@ -2558,7 +2639,7 @@ wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *tr } wxGtkTreeModelNode * node = treeNode; - for( ItemList::Node * n = list.GetFirst(); n; n = n->GetNext() ) + for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() ) { if( node && node->GetNodes().GetCount() != 0 ) { @@ -2644,7 +2725,7 @@ wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNo } wxGtkTreeModelNode * node = treeNode; - for( ItemList::Node * n = list.GetFirst(); n; n = n->GetNext() ) + for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() ) { if( node && node->GetNodes().GetCount() != 0 ) { @@ -2709,7 +2790,7 @@ wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCt return; wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED, dv->GetId() ); - // TODO: item + event.SetItem( dv->GetSelection() ); event.SetModel( dv->GetModel() ); dv->GetEventHandler()->ProcessEvent( event ); } @@ -2728,8 +2809,60 @@ wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path, 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 + // wxDataViewCtrl //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -2753,8 +2886,7 @@ void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation *alloc, wxDataViewCtrl *win ) { - - wxWindowList::Node *node = win->GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst(); while (node) { wxWindow *child = node->GetData(); @@ -2863,9 +2995,21 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, GtkEnableSelectionEvents(); - g_signal_connect_after (m_treeview, "row_activated", + g_signal_connect_after (m_treeview, "row-activated", G_CALLBACK (wxdataview_row_activated_callback), this); + g_signal_connect (m_treeview, "test-collapse-row", + G_CALLBACK (wxdataview_test_collapse_row_callback), this); + + g_signal_connect_after (m_treeview, "row-collapsed", + G_CALLBACK (wxdataview_row_collapsed_callback), this); + + g_signal_connect (m_treeview, "test-expand-row", + G_CALLBACK (wxdataview_test_expand_row_callback), this); + + g_signal_connect_after (m_treeview, "row-expanded", + G_CALLBACK (wxdataview_row_expanded_callback), this); + return true; } @@ -2908,19 +3052,105 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) if (!wxDataViewCtrlBase::AppendColumn(col)) return false; - GtkTreeViewColumn *column = (GtkTreeViewColumn *)col->GetGtkHandle(); + m_cols.Append( col ); + + gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ); + + return true; +} + +unsigned int wxDataViewCtrl::GetColumnCount() const +{ + return m_cols.GetCount(); +} + +wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const +{ + GtkTreeViewColumn *gtk_col = gtk_tree_view_get_column( GTK_TREE_VIEW(m_treeview), pos ); + if (!gtk_col) + return NULL; + + wxDataViewColumnList::const_iterator iter; + for (iter = m_cols.begin(); iter != m_cols.end(); iter++) + { + wxDataViewColumn *col = *iter; + if (GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) == gtk_col) + { + return col; + } + } + + return NULL; +} + +bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) +{ + gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN(column->GetGtkHandle()) ); + + m_cols.remove( column ); - gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), column ); + delete column; return true; } -wxDataViewItem wxDataViewCtrl::GetSelection() +bool wxDataViewCtrl::ClearColumns() +{ + wxDataViewColumnList::iterator iter; + for (iter = m_cols.begin(); iter != m_cols.end(); iter++) + { + wxDataViewColumn *col = *iter; + gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ); + } + + m_cols.clear(); + + return true; +} + +void wxDataViewCtrl::Expand( const wxDataViewItem & item ) +{ + GtkTreeIter iter; + iter.user_data = item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_view_expand_row( GTK_TREE_VIEW(m_treeview), path, false ); + gtk_tree_path_free( path ); +} + +void wxDataViewCtrl::Collapse( const wxDataViewItem & item ) +{ + GtkTreeIter iter; + iter.user_data = item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_view_collapse_row( GTK_TREE_VIEW(m_treeview), path ); + gtk_tree_path_free( path ); +} + +wxDataViewItem wxDataViewCtrl::GetSelection() const { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); if (m_windowStyle & wxDV_MULTIPLE) { + // Report the first one + GtkTreeModel *model; + GList *list = gtk_tree_selection_get_selected_rows( selection, &model ); + + if (list) + { + GtkTreePath *path = (GtkTreePath*) list->data; + GtkTreeIter iter; + m_internal->get_iter( &iter, path ); + + // delete list + g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL ); + g_list_free( list ); + + return wxDataViewItem( (void*) iter.user_data ); + } } else { @@ -2935,8 +3165,154 @@ wxDataViewItem wxDataViewCtrl::GetSelection() return wxDataViewItem(0); } +int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const +{ + sel.Clear(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + if (HasFlag(wxDV_MULTIPLE)) + { + GtkTreeModel *model; + GList *list = gtk_tree_selection_get_selected_rows( selection, &model ); + + int count = 0; + while (list) + { + GtkTreePath *path = (GtkTreePath*) list->data; + + GtkTreeIter iter; + m_internal->get_iter( &iter, path ); + + sel.Add( wxDataViewItem( (void*) iter.user_data ) ); + + list = g_list_next( list ); + count++; + } + + // delete list + g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL ); + g_list_free( list ); + + return count; + } + else + { + GtkTreeModel *model; + GtkTreeIter iter; + gboolean has_selection = gtk_tree_selection_get_selected( selection, &model, &iter ); + if (has_selection) + { + sel.Add( wxDataViewItem( (void*) iter.user_data) ); + return 1; + } + } + + return 0; +} + +void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel ) +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + gtk_tree_selection_unselect_all( selection ); + + size_t i; + for (i = 0; i < sel.GetCount(); i++) + { + GtkTreeIter iter; + iter.user_data = (gpointer) sel[i].GetID(); + gtk_tree_selection_select_iter( selection, &iter ); + } + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::Select( const wxDataViewItem & item ) +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + gtk_tree_selection_select_iter( selection, &iter ); + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::Unselect( const wxDataViewItem & item ) +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + gtk_tree_selection_unselect_iter( selection, &iter ); + + GtkEnableSelectionEvents(); +} + +bool wxDataViewCtrl::IsSelected( const wxDataViewItem & item ) const +{ + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + + return gtk_tree_selection_iter_is_selected( selection, &iter ); +} + +void wxDataViewCtrl::SelectAll() +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + gtk_tree_selection_select_all( selection ); + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::UnselectAll() +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + gtk_tree_selection_unselect_all( selection ); + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataViewColumn *column ) +{ + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(m_treeview), path, NULL, false, 0.0, 0.0 ); + gtk_tree_path_free( path ); +} + +void wxDataViewCtrl::HitTest( const wxPoint &point, + wxDataViewItem &item, wxDataViewColumn *&column ) const +{ + item = wxDataViewItem(0); + column = NULL; +} + +wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem &item, + const wxDataViewColumn *column ) const +{ + return wxRect(); +} + void wxDataViewCtrl::DoSetExpanderColumn() { + gtk_tree_view_set_expander_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN( GetExpanderColumn()->GetGtkHandle() ) ); } void wxDataViewCtrl::DoSetIndent() @@ -2946,15 +3322,15 @@ void wxDataViewCtrl::DoSetIndent() void wxDataViewCtrl::GtkDisableSelectionEvents() { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); - g_signal_connect_after (selection, "changed", - G_CALLBACK (wxdataview_selection_changed_callback), this); + g_signal_handlers_disconnect_by_func( selection, + (gpointer) (wxdataview_selection_changed_callback), this); } void wxDataViewCtrl::GtkEnableSelectionEvents() { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); - g_signal_handlers_disconnect_by_func( selection, - (gpointer) (wxdataview_selection_changed_callback), this); + g_signal_connect_after (selection, "changed", + G_CALLBACK (wxdataview_selection_changed_callback), this); } // static