X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4508fcd20aa15964291b7c9def941b2a6dc55445..94f6d685cb30a8e62d21254bbf19902b48eb2443:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index db04032719..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,116 +41,169 @@ #include //----------------------------------------------------------------------------- -// classes //----------------------------------------------------------------------------- +wxDataViewModel *g_model = NULL; + +class wxGtkTreeModelNode; + +extern "C" { +typedef struct _GtkWxTreeModel GtkWxTreeModel; +} + //----------------------------------------------------------------------------- -// wxGtkTreeModelNode +// wxDataViewCtrlInternal //----------------------------------------------------------------------------- -class wxGtkTreeModelNode; +WX_DECLARE_LIST(wxDataViewItem, ItemList); +WX_DEFINE_LIST(ItemList); + +class wxDataViewCtrlInternal +{ +public: + wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *owner ); + ~wxDataViewCtrlInternal(); + + 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 ); + gint iter_n_children( GtkTreeIter *iter ); + gboolean iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ); + gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child ); + + wxDataViewModel* GetDataViewModel() { return m_wx_model; } + wxDataViewCtrl* GetOwner() { return m_owner; } + GtkWxTreeModel* GetGtkModel() { return m_gtk_model; } + + bool ItemAdded( const wxDataViewItem &parent, 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: + wxGtkTreeModelNode *m_root; + wxDataViewModel *m_wx_model; + GtkWxTreeModel *m_gtk_model; + wxDataViewCtrl *m_owner; +}; + -int LINKAGEMODE wxGtkTreeModelNodeCmp( wxGtkTreeModelNode* node1, wxGtkTreeModelNode* node2 ); +//----------------------------------------------------------------------------- +// wxGtkTreeModelNode +//----------------------------------------------------------------------------- -WX_DEFINE_SORTED_ARRAY( wxGtkTreeModelNode*, wxGtkTreeModelNodes ); +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, - wxDataViewModel *model ) + wxDataViewCtrlInternal *internal ) { m_parent = parent; m_item = item; - m_model = model; - m_children = new wxGtkTreeModelNodes( wxGtkTreeModelNodeCmp ); + 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_children->Item( 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 &GetChildren() + wxGtkTreeModelNodes &GetNodes() + { return m_nodes; } + wxGtkTreeModelChildren &GetChildren() { return *m_children; } - wxGtkTreeModelNode* GetNthChild( unsigned int n ) - { return m_children->Item( n ); } - unsigned int Add( wxGtkTreeModelNode* child ) - { return m_children->Add( child ); } unsigned int GetChildCount() { return m_children->GetCount(); } + unsigned int GetNodesCount() { return m_nodes.GetCount(); } wxDataViewItem &GetItem() { return m_item; } - wxDataViewModel *GetModel() { return m_model; } - - bool HasChildren() { return m_hasChildren; } - void SetHasChildren( bool has ) { m_hasChildren = has; } + wxDataViewCtrlInternal *GetInternal() { return m_internal; } void Resort(); private: - wxGtkTreeModelNode *m_parent; - wxGtkTreeModelNodes *m_children; - wxDataViewItem m_item; - bool m_hasChildren; - wxDataViewModel *m_model; + wxGtkTreeModelNode *m_parent; + wxGtkTreeModelNodes m_nodes; + wxGtkTreeModelChildren *m_children; + wxDataViewItem m_item; + wxDataViewCtrlInternal *m_internal; }; -int LINKAGEMODE wxGtkTreeModelNodeCmp( wxGtkTreeModelNode* node1, wxGtkTreeModelNode* node2 ) -{ - return node1->GetModel()->Compare( node1->GetItem(), node2->GetItem() ); -} - -extern "C" { -typedef struct _GtkWxTreeModel GtkWxTreeModel; -} - -class wxDataViewCtrlInternal +int LINKAGEMODE wxGtkTreeModelNodeCmp( void* id1, void* id2 ) { -public: - wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *owner ); - ~wxDataViewCtrlInternal(); - - 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 ); - gint iter_n_children( GtkTreeIter *iter ); - gboolean iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ); - gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child ); - - wxDataViewModel* GetDataViewModel() { return m_wx_model; } - GtkWxTreeModel* GetOwner() { return m_gtk_model; } - - bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ); - bool ItemDeleted( const wxDataViewItem &item ); - - void Resort(); - -protected: - void InitTree(); - wxGtkTreeModelNode *FindNode( const wxDataViewItem &item ); - wxGtkTreeModelNode *FindNode( GtkTreeIter *iter ); - void BuildBranch( wxGtkTreeModelNode *branch ); - -private: - wxGtkTreeModelNode *m_root; - wxDataViewModel *m_wx_model; - GtkWxTreeModel *m_gtk_model; - wxDataViewCtrl *m_owner; -}; + return g_model->Compare( id1, id2 ); +} //----------------------------------------------------------------------------- // data @@ -556,17 +611,20 @@ void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortabl GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); - // TODO check for equality - - gtk_tree_sortable_sort_column_changed (sortable); - - tree_model->internal->GetDataViewModel()->SetSortingColumn( sort_column_id ); - 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); + tree_model->internal->GetDataViewModel()->Resort(); } @@ -964,7 +1022,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(); @@ -1011,7 +1069,7 @@ 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; @@ -1023,7 +1081,7 @@ bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &item ) 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; } @@ -1045,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; } @@ -1078,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; } @@ -2084,23 +2152,78 @@ void wxDataViewColumn::SetWidth( int width ) void wxGtkTreeModelNode::Resort() { - wxGtkTreeModelNodes *new_array = new wxGtkTreeModelNodes( wxGtkTreeModelNodeCmp ); + 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; - size_t count = m_children->GetCount(); + 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 < count; pos++) + for (pos = 0; pos < child_count; pos++) { - new_array->Add( m_children->Item( 0 ) ); - m_children->RemoveAt( 0 ); + 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; - for (pos = 0; pos < count; pos++) + 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) { - wxGtkTreeModelNode *node = m_children->Item( pos ); + 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(); } } @@ -2127,7 +2250,7 @@ wxDataViewCtrlInternal::~wxDataViewCtrlInternal() void wxDataViewCtrlInternal::InitTree() { wxDataViewItem item; - m_root = new wxGtkTreeModelNode( NULL, item, m_wx_model ); + m_root = new wxGtkTreeModelNode( NULL, item, this ); BuildBranch( m_root ); } @@ -2139,7 +2262,13 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node ) wxDataViewItem child = m_wx_model->GetFirstChild( node->GetItem() ); while (child.IsOk()) { - node->Add( new wxGtkTreeModelNode( node, child, node->GetModel() ) ); + 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 ); } } @@ -2153,29 +2282,71 @@ void wxDataViewCtrlInternal::Resort() bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ) { wxGtkTreeModelNode *parent_node = FindNode( parent ); - parent_node->Add( new wxGtkTreeModelNode( parent_node, item, parent_node->GetModel() ) ); + 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(); - size_t pos; - for (pos = 0; pos < parent->GetChildren().GetCount(); pos++) - { - if (node == parent->GetChildren().Item( pos )) - { - parent->GetChildren().RemoveAt( pos ); - continue; - } - } + 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; @@ -2189,28 +2360,46 @@ 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 ); - - node = parent; + + id = node->GetItem().GetID(); + node = node->GetParent(); } return retval; @@ -2218,23 +2407,26 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) 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 = FindNode( iter ); - while (node->GetParent()) + wxGtkTreeModelNode *node = FindParentNode( iter ); + while (node) { - wxGtkTreeModelNode *parent = node->GetParent(); size_t pos; - for (pos = 0; pos < parent->GetChildren().GetCount(); pos++) + for (pos = 0; pos < node->GetChildren().GetCount(); pos++) { - if (node == parent->GetChildren().Item( pos )) + if (id == node->GetChildren().Item( pos )) { gtk_tree_path_prepend_index( retval, (int) pos ); continue; } } - node = parent; + id = node->GetItem().GetID(); + node = node->GetParent(); } return retval; @@ -2242,51 +2434,67 @@ GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) { - wxGtkTreeModelNode *node = FindNode( iter ); - wxGtkTreeModelNode *parent = node->GetParent(); - unsigned int pos = parent->GetChildren().Index( node ); + g_model = m_wx_model; - if (pos == parent->GetChildren().GetCount()-1) + wxGtkTreeModelNode *parent = FindParentNode( iter ); + if( parent == NULL ) return FALSE; - - node = parent->GetChildren().Item( pos+1 ); + + 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 = (gpointer) node->GetItem().GetID(); + 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 ); + + if (!is_container) + return FALSE; + + wxGtkTreeModelNode *node = FindNode( iter ); + BuildBranch( node ); - return m_wx_model->HasChildren( item ); + 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 ); @@ -2299,34 +2507,31 @@ 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 ); - 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; @@ -2337,30 +2542,48 @@ gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *ch } 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()) - { - // wxPrintf( "leave findnode at %d\n", i ); - return child; - } - - wxGtkTreeModelNode *node2 = wxDataViewCtrlInternal_FindNode( child, item ); - if (node2) + 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 ) { - // wxPrintf( "branch findnode at %d\n", i ); - return node2; + 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 NULL; + return node; + } wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) @@ -2369,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) { @@ -2384,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) { @@ -2396,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 //----------------------------------------------------------------------------- @@ -2451,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();