#include <gdk/gdkkeysyms.h>
//-----------------------------------------------------------------------------
-// classes
//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// wxGtkTreeModelNode
-//-----------------------------------------------------------------------------
+wxDataViewModel *g_model = NULL;
class wxGtkTreeModelNode;
-int LINKAGEMODE wxGtkTreeModelNodeCmp( wxGtkTreeModelNode* node1, wxGtkTreeModelNode* node2 );
-
-WX_DEFINE_SORTED_ARRAY( wxGtkTreeModelNode*, wxGtkTreeModelNodes );
-
-class wxGtkTreeModelNode
-{
-public:
- wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item,
- wxDataViewModel *model )
- {
- m_parent = parent;
- m_item = item;
- m_model = model;
- m_children = new wxGtkTreeModelNodes( wxGtkTreeModelNodeCmp );
- }
-
- ~wxGtkTreeModelNode()
- {
- size_t count = m_children->GetCount();
- size_t i;
- for (i = 0; i < count; i++)
- {
- wxGtkTreeModelNode *child = m_children->Item( i );
- delete child;
- }
- delete m_children;
- }
-
- wxGtkTreeModelNode* GetParent()
- { return m_parent; }
- wxGtkTreeModelNodes &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(); }
-
- wxDataViewItem &GetItem() { return m_item; }
- wxDataViewModel *GetModel() { return m_model; }
-
- 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;
- wxDataViewModel *m_model;
-};
-
-int LINKAGEMODE wxGtkTreeModelNodeCmp( wxGtkTreeModelNode* node1, wxGtkTreeModelNode* node2 )
-{
- return node1->GetModel()->Compare( node1->GetItem(), node2->GetItem() );
-}
-
-
extern "C" {
typedef struct _GtkWxTreeModel GtkWxTreeModel;
}
+//-----------------------------------------------------------------------------
+// wxDataViewCtrlInternal
+//-----------------------------------------------------------------------------
+
class wxDataViewCtrlInternal
{
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 );
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:
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
//-----------------------------------------------------------------------------
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();
}
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();
}
}
void wxDataViewCtrlInternal::InitTree()
{
wxDataViewItem item;
- m_root = new wxGtkTreeModelNode( NULL, item, m_wx_model );
+ m_root = new wxGtkTreeModelNode( NULL, item, this );
BuildBranch( m_root );
}
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() );
child = m_wx_model->GetNextSibling( child );
}
}
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() );
return true;
}
bool wxDataViewCtrlInternal::ItemDeleted( 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 = FindParentNode( item );
+ parent->DeleteChild( item.GetID() );
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;
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;
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;
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 );
+ unsigned int pos = parent->GetChildren().Index( iter->user_data );
+
+ if (pos == parent->GetChildCount()-1)
return FALSE;
- node = parent->GetChildren().Item( pos+1 );
-
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 );
- 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 );
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;
{
if (!node) return NULL;
- size_t count = node->GetChildCount();
+ size_t count = node->GetNodesCount();
size_t i;
for (i = 0; i < count; i++)
{
- wxGtkTreeModelNode *child = node->GetChildren().Item( i );
+ wxGtkTreeModelNode *child = node->GetNodes().Item( i );
if (child->GetItem().GetID() == item.GetID())
{
// wxPrintf( "leave findnode at %d\n", i );
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)
return result;
}
+static wxGtkTreeModelNode*
+wxDataViewCtrlInternal_FindParentNode( wxGtkTreeModelNode *node, const wxDataViewItem &item )
+{
+ size_t child_count = node->GetChildCount();
+ void *id = item.GetID();
+ const wxGtkTreeModelChildren &children = node->GetChildren();
+ size_t pos;
+ for (pos = 0; pos < child_count; pos++)
+ {
+ if (children.Item( pos ) == id)
+ return node;
+ }
+
+ size_t node_count = node->GetNodesCount();
+ for (pos = 0; pos < node_count; pos++)
+ {
+ wxGtkTreeModelNode *child = node->GetNodes().Item( pos );
+
+ wxGtkTreeModelNode *node2 = wxDataViewCtrlInternal_FindParentNode( child, item );
+ if (node2)
+ {
+ // wxPrintf( "branch findnode at %d\n", i );
+ return node2;
+ }
+ }
+
+ 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_root, item );
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( const wxDataViewItem &item )
+{
+ if (!item.IsOk())
+ return NULL;
+
+ return wxDataViewCtrlInternal_FindParentNode( m_root, item );
+}
+
//-----------------------------------------------------------------------------
// wxDataViewCtrl signal callbacks
//-----------------------------------------------------------------------------