X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/55fbde1232bff0ed44c23775911574ac1b2f8a0a..dc834029a3eb341d9c9c5bebb4ce7b60560eeacb:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 7bab43fa23..e9ad3b983d 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -26,6 +26,8 @@ #include "wx/calctrl.h" #include "wx/popupwin.h" #include "wx/icon.h" +#include "wx/list.h" +#include "wx/listimpl.cpp" #include "wx/gtk/private.h" @@ -39,66 +41,23 @@ #include //----------------------------------------------------------------------------- -// classes //----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// wxGtkTreeModelNode -//----------------------------------------------------------------------------- +wxDataViewModel *g_model = NULL; class wxGtkTreeModelNode; -WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes ); - -class wxGtkTreeModelNode -{ -public: - wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item ) - { - m_parent = parent; - m_item = item; - } - - ~wxGtkTreeModelNode() - { - size_t count = m_children.GetCount(); - size_t i; - for (i = 0; i < count; i++) - { - wxGtkTreeModelNode *child = m_children[i]; - delete child; - } - } - - wxGtkTreeModelNode* GetParent() - { return m_parent; } - wxGtkTreeModelNodes &GetChildren() - { return m_children; } - wxGtkTreeModelNode* GetNthChild( unsigned int n ) - { return m_children.Item( n ); } - void Insert( wxGtkTreeModelNode* child, unsigned int n) - { m_children.Insert( child, n); } - void Append( wxGtkTreeModelNode* child ) - { m_children.Add( child ); } - - unsigned int GetChildCount() { return m_children.GetCount(); } - - wxDataViewItem &GetItem() { return m_item; } - - bool HasChildren() { return m_hasChildren; } - void SetHasChildren( bool has ) { m_hasChildren = has; } - -private: - wxGtkTreeModelNode *m_parent; - wxGtkTreeModelNodes m_children; - wxDataViewItem m_item; - bool m_hasChildren; -}; - extern "C" { typedef struct _GtkWxTreeModel GtkWxTreeModel; } +//----------------------------------------------------------------------------- +// wxDataViewCtrlInternal +//----------------------------------------------------------------------------- + +WX_DECLARE_LIST(wxDataViewItem, ItemList); +WX_DEFINE_LIST(ItemList); + class wxDataViewCtrlInternal { public: @@ -107,6 +66,7 @@ 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 ); @@ -115,15 +75,22 @@ public: gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child ); wxDataViewModel* GetDataViewModel() { return m_wx_model; } - GtkWxTreeModel* GetOwner() { return m_gtk_model; } + wxDataViewCtrl* GetOwner() { return m_owner; } + 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(); protected: void InitTree(); wxGtkTreeModelNode *FindNode( const wxDataViewItem &item ); wxGtkTreeModelNode *FindNode( GtkTreeIter *iter ); + wxGtkTreeModelNode *FindParentNode( const wxDataViewItem &item ); + wxGtkTreeModelNode *FindParentNode( GtkTreeIter *iter ); void BuildBranch( wxGtkTreeModelNode *branch ); private: @@ -133,6 +100,111 @@ private: wxDataViewCtrl *m_owner; }; + +//----------------------------------------------------------------------------- +// wxGtkTreeModelNode +//----------------------------------------------------------------------------- + +int LINKAGEMODE wxGtkTreeModelNodeCmp( void *id1, void *id2 ); + +WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes ); +WX_DEFINE_SORTED_ARRAY( void* , wxGtkTreeModelChildren ); + +class wxGtkTreeModelNode +{ +public: + wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item, + wxDataViewCtrlInternal *internal ) + { + 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 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() ); + } + + unsigned int AddLeave( void* id ) + { + g_model = m_internal->GetDataViewModel(); + return m_children->Add( id ); + } + + 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(); + for (pos = 0; pos < count; pos++) + { + wxGtkTreeModelNode *node = m_nodes.Item( pos ); + if (node->GetItem().GetID() == id) + { + m_nodes.RemoveAt( pos ); + delete node; + break; + } + } + + } + + wxGtkTreeModelNode* GetParent() + { return m_parent; } + wxGtkTreeModelNodes &GetNodes() + { return m_nodes; } + wxGtkTreeModelChildren &GetChildren() + { return *m_children; } + + unsigned int GetChildCount() { return m_children->GetCount(); } + unsigned int GetNodesCount() { return m_nodes.GetCount(); } + + wxDataViewItem &GetItem() { return m_item; } + wxDataViewCtrlInternal *GetInternal() { return m_internal; } + + void Resort(); + +private: + wxGtkTreeModelNode *m_parent; + wxGtkTreeModelNodes m_nodes; + wxGtkTreeModelChildren *m_children; + wxDataViewItem m_item; + wxDataViewCtrlInternal *m_internal; +}; + + +int LINKAGEMODE wxGtkTreeModelNodeCmp( void* id1, void* id2 ) +{ + return g_model->Compare( id1, id2 ); +} + //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- @@ -163,9 +235,6 @@ struct _GtkWxTreeModel /*< private >*/ gint stamp; wxDataViewCtrlInternal *internal; - - gint sort_column_id; - GtkSortType order; }; struct _GtkWxTreeModelClass @@ -188,6 +257,8 @@ 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, @@ -326,8 +397,6 @@ wxgtk_tree_model_init (GtkWxTreeModel *tree_model) { tree_model->internal = NULL; tree_model->stamp = g_random_int(); - tree_model->sort_column_id = -2; - tree_model->order = GTK_SORT_ASCENDING; } static void @@ -405,6 +474,17 @@ 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, @@ -509,14 +589,17 @@ 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->sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID) - return FALSE; - if (sort_column_id) - *sort_column_id = tree_model->sort_column_id; + *sort_column_id = tree_model->internal->GetDataViewModel()->GetSortingColumn(); if (order) - *order = tree_model->order; + { + bool ascending = tree_model->internal->GetDataViewModel()->GetSortOrderAscending(); + if (ascending) + *order = GTK_SORT_ASCENDING; + else + *order = GTK_SORT_DESCENDING; + } return TRUE; } @@ -526,20 +609,23 @@ void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortabl GtkSortType order) { GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; - g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); - if ((tree_model->sort_column_id == sort_column_id) && - (tree_model->order == order)) - return; - - tree_model->sort_column_id = sort_column_id; - tree_model->order = order; + 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())) + return; + + tree_model->internal->GetDataViewModel()->SetSortingColumn( sort_column_id ); + + tree_model->internal->GetDataViewModel()->SetSortOrderAscending( ascending ); + gtk_tree_sortable_sort_column_changed (sortable); - - wxPrintf( "wxgtk_tree_model_set_column_id, sort_column_id = %d, order = %d\n", sort_column_id, (int)order ); - // sort + + tree_model->internal->GetDataViewModel()->Resort(); } void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable, @@ -550,9 +636,6 @@ void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortabl { g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); g_return_if_fail (func != NULL); - - wxPrintf( "wxgtk_tree_model_set_sort_func, sort_column_id = %d\n", sort_column_id ); - // sort } void wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable, @@ -939,10 +1022,11 @@ 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(); + virtual void Resort(); GtkWxTreeModel *m_wxgtk_model; wxDataViewModel *m_wx_model; @@ -985,23 +1069,28 @@ 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( + GtkTreePath *path = wxgtk_tree_model_get_path_safe( 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; } +void wxGtkDataViewModelNotifier::Resort() +{ + m_owner->GtkGetInternal()->Resort(); +} + bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item ) { GtkTreeIter iter; @@ -1014,6 +1103,8 @@ bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item ) GTK_TREE_MODEL(m_wxgtk_model), path, &iter ); gtk_tree_path_free (path); + m_owner->GtkGetInternal()->ItemChanged( item ); + return true; } @@ -1047,14 +1138,22 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig // Redraw gtk_widget_queue_draw_area( GTK_WIDGET(widget), cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height ); + + m_owner->GtkGetInternal()->ValueChanged( item, model_col ); + + return true; } } - return true; + return false; } bool wxGtkDataViewModelNotifier::Cleared() { + // TODO: delete everything + + m_owner->GtkGetInternal()->Cleared(); + return false; } @@ -2047,6 +2146,88 @@ void wxDataViewColumn::SetWidth( int width ) } +//----------------------------------------------------------------------------- +// wxGtkTreeModelNode +//----------------------------------------------------------------------------- + +void wxGtkTreeModelNode::Resort() +{ + g_model = m_internal->GetDataViewModel(); + + 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 *new_array = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp ); + + size_t pos; + for (pos = 0; pos < child_count; pos++) + new_array->Add( m_children->Item( pos ) ); + + gint *new_order = new gint[child_count]; + + 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; + } + } + } + +// 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.stamp = m_internal->GetGtkModel()->stamp; + 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 //----------------------------------------------------------------------------- @@ -2066,6 +2247,14 @@ 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) @@ -2073,32 +2262,91 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node ) wxDataViewItem child = m_wx_model->GetFirstChild( node->GetItem() ); while (child.IsOk()) { - // wxPrintf( "AddItem %d\n", (int) child.GetID() ); - node->Append( new wxGtkTreeModelNode( node, child ) ); + 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 ); } } } +void wxDataViewCtrlInternal::Resort() +{ + m_root->Resort(); +} + bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ) { wxGtkTreeModelNode *parent_node = FindNode( parent ); - parent_node->Append( new wxGtkTreeModelNode( parent_node, item ) ); + if (m_wx_model->IsContainer( item )) + parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) ); + else + parent_node->AddLeave( item.GetID() ); + + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED, m_owner->GetId() ); + event.SetEventObject( m_owner ); + event.SetModel( m_owner->GetModel() ); + event.SetItem( item ); + m_owner->GetEventHandler()->ProcessEvent( event ); + return true; } -bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &item ) +bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ) { - wxGtkTreeModelNode *node = FindNode( item ); - wxGtkTreeModelNode *parent = node->GetParent(); - parent->GetChildren().Remove( node ); - delete node; + 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 ); + event.SetModel( m_owner->GetModel() ); + event.SetItem( item ); + m_owner->GetEventHandler()->ProcessEvent( event ); + + return true; +} +bool wxDataViewCtrlInternal::ItemChanged( const wxDataViewItem &item ) +{ + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_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_MODEL_VALUE_CHANGED, m_owner->GetId() ); + event.SetEventObject( m_owner ); + event.SetModel( m_owner->GetModel() ); + event.SetColumn( col ); + event.SetItem( item ); + m_owner->GetEventHandler()->ProcessEvent( event ); + + return true; +} + +bool wxDataViewCtrlInternal::Cleared() +{ + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED, m_owner->GetId() ); + event.SetEventObject( m_owner ); + event.SetModel( m_owner->GetModel() ); + m_owner->GetEventHandler()->ProcessEvent( event ); + return true; } 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; @@ -2112,28 +2360,73 @@ gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path if (pos < 0) return FALSE; if ((size_t)pos >= node->GetChildCount()) return FALSE; - node = node->GetChildren().Item( (size_t) pos ); - } + void* id = node->GetChildren().Item( (size_t) pos ); + + if (i == depth-1) + { + iter->stamp = m_gtk_model->stamp; + iter->user_data = id; + return TRUE; + } - iter->stamp = m_gtk_model->stamp; - iter->user_data = (gpointer) node->GetItem().GetID(); + 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 TRUE; + return FALSE; } GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) { + g_model = m_wx_model; + GtkTreePath *retval = gtk_tree_path_new (); + void *id = iter->user_data; - wxGtkTreeModelNode *node = FindNode( iter ); - while (node->GetParent()) + wxGtkTreeModelNode *node = FindParentNode( iter ); + while (node) { - wxGtkTreeModelNode *parent = node->GetParent(); - int pos = parent->GetChildren().Index( node ); - + int pos = node->GetChildren().Index( id ); gtk_tree_path_prepend_index( retval, pos ); + + id = node->GetItem().GetID(); + node = node->GetParent(); + } - node = parent; + 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; @@ -2141,82 +2434,104 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) { - wxDataViewItem item( (void*) iter->user_data ); - item = m_wx_model->GetNextSibling( item ); - if (!item.IsOk()) + g_model = m_wx_model; + + wxGtkTreeModelNode *parent = FindParentNode( iter ); + if( parent == NULL ) return FALSE; - iter->user_data = (gpointer) item.GetID(); + unsigned int pos = parent->GetChildren().Index( iter->user_data ); + + if (pos == 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 ) { + g_model = m_wx_model; + wxDataViewItem item( (void*) parent->user_data ); - if (!m_wx_model->HasChildren( item )) + if (!m_wx_model->IsContainer( item )) return FALSE; wxGtkTreeModelNode *parent_node = FindNode( parent ); BuildBranch( parent_node ); - - wxGtkTreeModelNode *first_child_node = parent_node->GetChildren().Item( 0 ); + if (parent_node->GetChildCount() == 0) + return FALSE; + iter->stamp = m_gtk_model->stamp; - iter->user_data = (gpointer) first_child_node->GetItem().GetID(); + iter->user_data = (gpointer) parent_node->GetChildren().Item( 0 ); return TRUE; } 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 ); - return m_wx_model->HasChildren( item ); + if (!is_container) + return FALSE; + + wxGtkTreeModelNode *node = FindNode( iter ); + BuildBranch( node ); + + return (node->GetChildCount() > 0); } gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) { + g_model = m_wx_model; + wxDataViewItem item( (void*) iter->user_data ); - if (!m_wx_model->HasChildren( item )) + 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 ) { + g_model = m_wx_model; + void* id = NULL; if (parent) id = (void*) parent->user_data; wxDataViewItem item( id ); - if (!m_wx_model->HasChildren( item )) + if (!m_wx_model->IsContainer( item )) return FALSE; wxGtkTreeModelNode *parent_node = FindNode( parent ); BuildBranch( parent_node ); - wxGtkTreeModelNode *child_node = parent_node->GetChildren().Item( (size_t) n ); - if (!child_node) - return FALSE; + // wxPrintf( "iter_nth_child %d\n", n ); iter->stamp = m_gtk_model->stamp; - iter->user_data = (gpointer) child_node->GetItem().GetID(); + iter->user_data = parent_node->GetChildren().Item( n ); return TRUE; } gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child ) { - wxDataViewItem item( (void*) child->user_data ); - - wxGtkTreeModelNode *node = FindNode( child ); - node = node->GetParent(); + g_model = m_wx_model; + + wxGtkTreeModelNode *node = FindParentNode( child ); if (!node) return FALSE; @@ -2226,33 +2541,49 @@ gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *ch return TRUE; } -void wxDataViewCtrlInternal::InitTree() -{ - wxDataViewItem item; - m_root = new wxGtkTreeModelNode( NULL, item ); - - BuildBranch( m_root ); -} - static wxGtkTreeModelNode* -wxDataViewCtrlInternal_FindNode( wxGtkTreeModelNode *node, const wxDataViewItem &item ) +wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item ) { - if (!node) return NULL; + if( model == NULL ) + return NULL; - size_t count = node->GetChildCount(); - size_t i; - for (i = 0; i < count; i++) + ItemList list; + list.DeleteContents( true ); + wxDataViewItem it( item ); + while( it.IsOk() ) { - wxGtkTreeModelNode *child = node->GetChildren().Item( i ); - if (child->GetItem().GetID() == item.GetID()) - return child; - - wxGtkTreeModelNode *node2 = wxDataViewCtrlInternal_FindNode( child, item ); - if (node2) - return node2; + wxDataViewItem * pItem = new wxDataViewItem( it ); + list.Insert( pItem ); + it = model->GetParent( it ); } - - return NULL; + + 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 ) @@ -2261,8 +2592,10 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) return m_root; wxDataViewItem item( (void*) iter->user_data ); + if (!item.IsOk()) + return m_root; - wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_root, item ); + wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item ); if (!result) { @@ -2276,7 +2609,10 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item ) { - wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_root, item ); + if (!item.IsOk()) + return m_root; + + wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item ); if (!result) { @@ -2288,6 +2624,80 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item 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 //----------------------------------------------------------------------------- @@ -2343,8 +2753,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();