+void wxDataViewCtrlInternal::Resort()
+{
+ if (!m_wx_model->IsVirtualListModel())
+ m_root->Resort();
+
+ ScheduleRefresh();
+}
+
+bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+ if (!m_wx_model->IsVirtualListModel())
+ {
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ wxCHECK_MSG(parent_node, false,
+ "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
+
+ wxDataViewItemArray modelSiblings;
+ m_wx_model->GetChildren(parent, modelSiblings);
+ const int modelSiblingsSize = modelSiblings.size();
+
+ int posInModel = modelSiblings.Index(item, /*fromEnd=*/true);
+ wxCHECK_MSG( posInModel != wxNOT_FOUND, false, "adding non-existent item?" );
+
+ const wxGtkTreeModelChildren& nodeSiblings = parent_node->GetChildren();
+ const int nodeSiblingsSize = nodeSiblings.size();
+
+ int nodePos = 0;
+
+ if ( posInModel == modelSiblingsSize - 1 )
+ {
+ nodePos = nodeSiblingsSize;
+ }
+ else if ( modelSiblingsSize == nodeSiblingsSize + 1 )
+ {
+ // This is the simple case when our node tree already matches the
+ // model and only this one item is missing.
+ nodePos = posInModel;
+ }
+ else
+ {
+ // It's possible that a larger discrepancy between the model and
+ // our realization exists. This can happen e.g. when adding a bunch
+ // of items to the model and then calling ItemsAdded() just once
+ // afterwards. In this case, we must find the right position by
+ // looking at sibling items.
+
+ // append to the end if we won't find a better position:
+ nodePos = nodeSiblingsSize;
+
+ for ( int nextItemPos = posInModel + 1;
+ nextItemPos < modelSiblingsSize;
+ nextItemPos++ )
+ {
+ int nextNodePos = parent_node->FindChildByItem(modelSiblings[nextItemPos]);
+ if ( nextNodePos != wxNOT_FOUND )
+ {
+ nodePos = nextNodePos;
+ break;
+ }
+ }
+ }
+
+ if (m_wx_model->IsContainer( item ))
+ parent_node->InsertNode( new wxGtkTreeModelNode( parent_node, item, this ), nodePos );
+ else
+ parent_node->InsertLeaf( item.GetID(), nodePos );
+ }
+
+ ScheduleRefresh();
+
+ return true;
+}
+
+bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+ if (!m_wx_model->IsVirtualListModel())
+ {
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ wxASSERT_MSG(parent_node,
+ "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
+
+ parent_node->DeleteChild( item.GetID() );
+ }
+
+ ScheduleRefresh();
+
+ 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->HandleWindowEvent( event );
+
+ return true;
+}
+
+bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned int view_column )
+{
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() );
+ event.SetEventObject( m_owner );
+ event.SetModel( m_owner->GetModel() );
+ event.SetColumn( view_column );
+ event.SetDataViewColumn( GetOwner()->GetColumn(view_column) );
+ event.SetItem( item );
+ m_owner->HandleWindowEvent( event );
+
+ return true;
+}
+
+// GTK+ model iface
+
+GtkTreeModelFlags wxDataViewCtrlInternal::get_flags()
+{
+ int flags = 0;
+
+ if ( m_wx_model->IsListModel() )
+ flags |= GTK_TREE_MODEL_LIST_ONLY;
+
+ if ( !m_wx_model->IsVirtualListModel() )
+ flags |= GTK_TREE_MODEL_ITERS_PERSIST;
+
+ return GtkTreeModelFlags(flags);
+}
+
+gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path )
+{
+
+ if (m_wx_model->IsVirtualListModel())
+ {
+ wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model;
+
+ unsigned int i = (unsigned int)gtk_tree_path_get_indices (path)[0];
+
+ if (i >= wx_model->GetCount())
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ // user_data is just the index +1
+ iter->user_data = wxUIntToPtr(i+1);
+
+ return TRUE;
+ }
+ else
+ {
+ 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 )
+{
+ // When this is called from ItemDeleted(), the item is already
+ // deleted in the model.
+
+ GtkTreePath *retval = gtk_tree_path_new ();
+
+ if (m_wx_model->IsVirtualListModel())
+ {
+ // iter is root, add nothing
+ if (!iter->user_data)
+ return retval;
+
+ // user_data is just the index +1
+ int i = ( (wxUIntPtr) iter->user_data ) -1;
+ gtk_tree_path_append_index (retval, i);
+ }
+ else
+ {
+ 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 )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model;
+
+ // user_data is just the index +1
+ int n = ( (wxUIntPtr) iter->user_data ) -1;
+
+ if (n == -1)
+ {
+ iter->user_data = NULL;
+ return FALSE;
+ }
+
+ if (n >= (int) wx_model->GetCount()-1)
+ {
+ iter->user_data = NULL;
+ return FALSE;
+ }
+
+ // user_data is just the index +1 (+2 because we need the next)
+ iter->user_data = wxUIntToPtr(n+2);
+ }
+ else
+ {
+ wxGtkTreeModelNode *parent = FindParentNode( iter );
+ if( parent == NULL )
+ {
+ iter->user_data = NULL;
+ return FALSE;
+ }
+
+ int pos = parent->GetChildren().Index( iter->user_data );
+
+ if (pos == (int) parent->GetChildCount()-1)
+ {
+ iter->user_data = NULL;
+ return FALSE;
+ }
+
+ iter->user_data = parent->GetChildren().Item( pos+1 );
+ }
+
+ return TRUE;
+}
+
+gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ // this is a list, nodes have no children
+ if (parent)
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = (gpointer) 1;
+
+ return TRUE;
+ }
+ else
+ {
+ if (iter == NULL)
+ {
+ if (m_root->GetChildCount() == 0) return FALSE;
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = (gpointer) m_root->GetChildren().Item( 0 );
+ return TRUE;
+ }
+
+
+ wxDataViewItem item;
+ if (parent)
+ item = wxDataViewItem( (void*) parent->user_data );
+
+ if (!m_wx_model->IsContainer( item ))
+ return FALSE;
+
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ wxASSERT_MSG(parent_node,
+ "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
+
+ 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 )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model;
+
+ if (iter == NULL)
+ return (wx_model->GetCount() > 0);
+
+ // this is a list, nodes have no children
+ return FALSE;
+ }
+ else
+ {
+ if (iter == NULL)
+ return (m_root->GetChildCount() > 0);
+
+ wxDataViewItem item( (void*) iter->user_data );
+
+ bool is_container = m_wx_model->IsContainer( item );
+
+ if (!is_container)
+ return FALSE;
+
+ wxGtkTreeModelNode *node = FindNode( iter );
+ wxASSERT_MSG(node,
+ "Did you forget a call to ItemAdded()? The iterator is unknown to the wxGtkTreeModel");
+
+ BuildBranch( node );
+
+ return (node->GetChildCount() > 0);
+ }
+}
+
+gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model;
+
+ if (iter == NULL)
+ return (gint) wx_model->GetCount();
+
+ return 0;
+ }
+ else
+ {
+ if (iter == NULL)
+ return m_root->GetChildCount();
+
+ wxDataViewItem item( (void*) iter->user_data );
+
+ if (!m_wx_model->IsContainer( item ))
+ return 0;
+
+ wxGtkTreeModelNode *parent_node = FindNode( iter );
+ wxASSERT_MSG(parent_node,
+ "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
+
+ BuildBranch( parent_node );
+
+ return parent_node->GetChildCount();
+ }
+}
+
+gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model;
+
+ if (parent)
+ return FALSE;
+
+ if (n < 0)
+ return FALSE;
+
+ if (n >= (gint) wx_model->GetCount())
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ // user_data is just the index +1
+ iter->user_data = wxUIntToPtr(n+1);
+
+ return TRUE;
+ }
+ else
+ {
+ 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 );
+ wxASSERT_MSG(parent_node,
+ "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
+
+ BuildBranch( parent_node );
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = parent_node->GetChildren().Item( n );
+
+ return TRUE;
+ }
+}
+
+gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ return FALSE;
+ }
+ else
+ {
+ wxGtkTreeModelNode *node = FindParentNode( child );
+ if (!node)
+ return FALSE;
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = (gpointer) node->GetItem().GetID();
+
+ return TRUE;
+ }
+}
+
+// item can be deleted already in the model
+int wxDataViewCtrlInternal::GetIndexOf( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+ if (m_wx_model->IsVirtualListModel())
+ {
+ return wxPtrToUInt(item.GetID()) - 1;
+ }
+ else
+ {
+ wxGtkTreeModelNode *parent_node = FindNode( parent );
+ wxGtkTreeModelChildren &children = parent_node->GetChildren();
+ size_t j;
+ for (j = 0; j < children.GetCount(); j++)
+ {
+ if (children[j] == item.GetID())
+ return j;
+ }
+ }
+ return -1;
+}
+
+