//-----------------------------------------------------------------------------
class wxGtkTreeModelNode;
-WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes );
+
+extern "C" {
+typedef struct _GtkWxTreeModel GtkWxTreeModel;
+}
+
+int LINKAGEMODE wxGtkTreeModelNodeCmp( wxGtkTreeModelNode* node1, wxGtkTreeModelNode* node2 );
+
+WX_DEFINE_SORTED_ARRAY( wxGtkTreeModelNode*, wxGtkTreeModelNodes );
class wxGtkTreeModelNode
{
public:
- wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item )
+ wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item,
+ wxDataViewCtrlInternal *internal )
{
m_parent = parent;
m_item = item;
+ m_internal = internal;
+ m_children = new wxGtkTreeModelNodes( wxGtkTreeModelNodeCmp );
}
~wxGtkTreeModelNode()
{
- size_t count = m_children.GetCount();
+ size_t count = m_children->GetCount();
size_t i;
for (i = 0; i < count; i++)
{
- wxGtkTreeModelNode *child = m_children[i];
+ wxGtkTreeModelNode *child = m_children->Item( i );
delete child;
}
+ delete m_children;
}
wxGtkTreeModelNode* GetParent()
{ return m_parent; }
wxGtkTreeModelNodes &GetChildren()
- { return m_children; }
+ { 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(); }
+ { return m_children->Item( n ); }
+ unsigned int Add( wxGtkTreeModelNode* child )
+ { return m_children->Add( child ); }
+
+ unsigned int GetChildCount() { return m_children->GetCount(); }
wxDataViewItem &GetItem() { return m_item; }
+ wxDataViewCtrlInternal *GetInternal() { return m_internal; }
bool HasChildren() { return m_hasChildren; }
void SetHasChildren( bool has ) { m_hasChildren = has; }
+ void Resort();
+
private:
- wxGtkTreeModelNode *m_parent;
- wxGtkTreeModelNodes m_children;
- wxDataViewItem m_item;
- bool m_hasChildren;
+ wxGtkTreeModelNode *m_parent;
+ wxGtkTreeModelNodes *m_children;
+ wxDataViewItem m_item;
+ bool m_hasChildren;
+ wxDataViewCtrlInternal *m_internal;
};
-extern "C" {
-typedef struct _GtkWxTreeModel GtkWxTreeModel;
-}
class 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 );
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 );
+ void Resort();
+
protected:
void InitTree();
wxGtkTreeModelNode *FindNode( const wxDataViewItem &item );
wxDataViewCtrl *m_owner;
};
+
+int LINKAGEMODE wxGtkTreeModelNodeCmp( wxGtkTreeModelNode* node1, wxGtkTreeModelNode* node2 )
+{
+ return node1->GetInternal()->GetDataViewModel()->Compare( node1->GetItem(), node2->GetItem() );
+}
+
//-----------------------------------------------------------------------------
// data
//-----------------------------------------------------------------------------
/*< private >*/
gint stamp;
wxDataViewCtrlInternal *internal;
-
- gint sort_column_id;
- GtkSortType order;
};
struct _GtkWxTreeModelClass
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,
{
tree_model->internal = NULL;
tree_model->stamp = g_random_int();
- tree_model->sort_column_id = -2;
- tree_model->order = GTK_SORT_ASCENDING;
}
static void
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,
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;
}
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 == 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,
{
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,
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;
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 );
return true;
}
+void wxGtkDataViewModelNotifier::Resort()
+{
+ m_owner->GtkGetInternal()->Resort();
+}
+
bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item )
{
GtkTreeIter iter;
}
+//-----------------------------------------------------------------------------
+// wxGtkTreeModelNode
+//-----------------------------------------------------------------------------
+
+void wxGtkTreeModelNode::Resort()
+{
+ size_t count = m_children->GetCount();
+ if (count == 0)
+ return;
+
+ if (count == 1)
+ {
+ wxGtkTreeModelNode *node = m_children->Item( 0 );
+ node->Resort();
+ return;
+ }
+
+ wxGtkTreeModelNodes *new_array = new wxGtkTreeModelNodes( wxGtkTreeModelNodeCmp );
+
+ size_t pos;
+
+ for (pos = 0; pos < count; pos++)
+ new_array->Add( m_children->Item( pos ) );
+
+
+ gint *new_order = new gint[count];
+
+ for (pos = 0; pos < count; pos++)
+ {
+ wxGtkTreeModelNode *node = new_array->Item( pos );
+ size_t old_pos;
+ for (old_pos = 0; old_pos < count; old_pos++)
+ {
+ if (node == 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() );
+
+ GtkTreeIter iter;
+ iter.user_data = (gpointer) GetItem().GetID();
+ iter.stamp = m_internal->GetGtkModel()->stamp;
+ GtkTreePath *path = wxgtk_tree_model_get_path( gtk_tree_model, &iter );
+
+ gtk_tree_model_rows_reordered( gtk_tree_model, path, &iter, new_order );
+
+ gtk_tree_path_free (path);
+
+ delete [] new_order;
+
+ for (pos = 0; pos < count; pos++)
+ {
+ wxGtkTreeModelNode *node = m_children->Item( pos );
+ node->Resort();
+ }
+}
+
//-----------------------------------------------------------------------------
// 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)
wxDataViewItem child = m_wx_model->GetFirstChild( node->GetItem() );
while (child.IsOk())
{
- // wxPrintf( "AddItem %d\n", (int) child.GetID() );
- node->Append( new wxGtkTreeModelNode( node, child ) );
+ node->Add( new wxGtkTreeModelNode( node, child, this ) );
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 ) );
+ parent_node->Add( new wxGtkTreeModelNode( parent_node, item, this ) );
return true;
}
{
wxGtkTreeModelNode *node = FindNode( item );
wxGtkTreeModelNode *parent = node->GetParent();
- parent->GetChildren().Remove( node );
- delete node;
+ size_t pos;
+ for (pos = 0; pos < parent->GetChildren().GetCount(); pos++)
+ {
+ if (node == parent->GetChildren().Item( pos ))
+ {
+ parent->GetChildren().RemoveAt( pos );
+ continue;
+ }
+ }
return true;
}
return retval;
}
+GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter )
+{
+ GtkTreePath *retval = gtk_tree_path_new ();
+
+ wxGtkTreeModelNode *node = FindNode( iter );
+ while (node->GetParent())
+ {
+ wxGtkTreeModelNode *parent = node->GetParent();
+ size_t pos;
+ for (pos = 0; pos < parent->GetChildren().GetCount(); pos++)
+ {
+ if (node == parent->GetChildren().Item( pos ))
+ {
+ gtk_tree_path_prepend_index( retval, (int) pos );
+ continue;
+ }
+ }
+
+ node = parent;
+ }
+
+ return retval;
+}
+
gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
{
- wxDataViewItem item( (void*) iter->user_data );
- item = m_wx_model->GetNextSibling( item );
- if (!item.IsOk())
+ wxGtkTreeModelNode *node = FindNode( iter );
+ wxGtkTreeModelNode *parent = node->GetParent();
+ unsigned int pos = parent->GetChildren().Index( node );
+
+ if (pos == parent->GetChildren().GetCount()-1)
return FALSE;
-
- iter->user_data = (gpointer) item.GetID();
+
+ node = parent->GetChildren().Item( pos+1 );
+
+ iter->stamp = m_gtk_model->stamp;
+ iter->user_data = (gpointer) node->GetItem().GetID();
return TRUE;
}
wxGtkTreeModelNode *parent_node = FindNode( iter );
BuildBranch( parent_node );
+
+ // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() );
return parent_node->GetChildCount();
}
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();
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 )
{
{
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)
+ {
+ // wxPrintf( "branch findnode at %d\n", i );
return node2;
+ }
}
return NULL;
return m_root;
wxDataViewItem item( (void*) iter->user_data );
+ if (!item.IsOk())
+ return m_root;
wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_root, item );
wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item )
{
+ if (!item.IsOk())
+ return m_root;
+
wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_root, item );
if (!result)