From: Robert Roebling Date: Fri, 13 Jul 2007 00:35:39 +0000 (+0000) Subject: More patches from Bo, reduced wxDataViewModel, more sorting preps X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/d5025dc00f43ed893d06f512368402aef50408d9 More patches from Bo, reduced wxDataViewModel, more sorting preps git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@47410 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/dataview.h b/include/wx/dataview.h index 459885406b..e96135b526 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -24,7 +24,7 @@ #if defined(__WXGTK20__) // for testing - // #define wxUSE_GENERICDATAVIEWCTRL 1 + #define wxUSE_GENERICDATAVIEWCTRL 1 #elif defined(__WXMAC__) #else #define wxUSE_GENERICDATAVIEWCTRL 1 @@ -83,7 +83,7 @@ private: wxUint32 m_id; }; -bool operator == ( const wxDataViewItem& left, const wxDataViewItem& right ); +bool operator == (const wxDataViewItem &left, const wxDataViewItem &right); // --------------------------------------------------------- // wxDataViewModel @@ -112,11 +112,8 @@ public: // define hierachy virtual bool HasChildren( const wxDataViewItem &item ) const = 0; - virtual int GetChildCount( const wxDataViewItem &item ) const = 0; - virtual wxDataViewItem GetParent( const wxDataViewItem &child ) const = 0; virtual wxDataViewItem GetFirstChild( const wxDataViewItem &parent ) const = 0; virtual wxDataViewItem GetNextSibling( const wxDataViewItem &item ) const = 0; - virtual wxDataViewItem GetNthChild( const wxDataViewItem &parent, unsigned int n ) const = 0; // delegated notifiers virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ); diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 8a0670f35b..a6259d29b1 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -145,33 +145,6 @@ public: return ((ID == 1) || (ID == 2) || (ID == 5) || (ID == 0)); } - virtual int GetChildCount( const wxDataViewItem &item ) const - { - int ID = item.GetID(); - switch (ID) - { - case 0: return 1; - case 1: return 2; - case 2: return 2; - case 5: return 2; - } - return 0; - } - virtual wxDataViewItem GetParent( const wxDataViewItem &child ) const - { - int ID = child.GetID(); - switch (ID) - { - case 2: - case 5: return wxDataViewItem( 1 ); - case 3: - case 4: return wxDataViewItem( 2 ); - case 6: - case 7: return wxDataViewItem( 5 ); - } - - return wxDataViewItem(0); - } virtual wxDataViewItem GetFirstChild( const wxDataViewItem &parent ) const { int ID = parent.GetID(); @@ -197,42 +170,6 @@ public: return wxDataViewItem(0); } - virtual wxDataViewItem GetNthChild( const wxDataViewItem &parent, unsigned int n ) const - { - if (!parent.IsOk()) - { - // root node - if (n == 0) - return wxDataViewItem( 1 ); - - return wxDataViewItem( 0 ); - } - - int ID = parent.GetID(); - switch (ID) - { - case 1: - { - if (n == 0) return wxDataViewItem( 2 ); - else if (n == 1) return wxDataViewItem( 5 ); - } - break; - case 2: - { - if (n == 0) return wxDataViewItem( 3 ); - else if (n == 1) return wxDataViewItem( 4 ); - } - break; - case 5: - { - if (n == 0) return wxDataViewItem( 6 ); - else if (n == 1) return wxDataViewItem( 7 ); - } - break; - } - - return wxDataViewItem(0); - } }; // ------------------------------------- diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index 9cd318eb0f..f8f5154fa2 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -26,8 +26,14 @@ const wxChar wxDataViewCtrlNameStr[] = wxT("dataviewCtrl"); +bool operator == (const wxDataViewItem &left, const wxDataViewItem &right) +{ + return (left.GetID() == right.GetID() ); +} + + // --------------------------------------------------------- -// wxDataViewListModel +// wxDataViewModel // --------------------------------------------------------- wxDataViewModel::wxDataViewModel() diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index e590c950fa..92414ec47d 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -60,11 +60,6 @@ static const int PADDING_TOPBOTTOM = 1; // the expander space margin static const int EXPANDER_MARGIN = 4; -bool operator == ( const wxDataViewItem & left, const wxDataViewItem & right ) -{ - return left.GetID() == right.GetID(); -} - //----------------------------------------------------------------------------- // wxDataViewHeaderWindow //----------------------------------------------------------------------------- @@ -393,7 +388,7 @@ public: void DestroyTree(); private: wxDataViewTreeNode * GetTreeNodeByRow( unsigned int row ); - wxDataViewTreeNode * GetTreeNodeByItem( const wxDataViewItem & item ) { return NULL; } + wxDataViewTreeNode * GetTreeNodeByItem( const wxDataViewItem & item ){}; int RecalculateCount() ; @@ -1690,34 +1685,41 @@ void wxDataViewMainWindow::OnRenameTimer() m_currentCol->GetRenderer()->StartEditing( m_currentRow, labelRect ); } +//------------------------------------------------------------------ +// Helper class for do operation on the tree node +//------------------------------------------------------------------ class DoJob { public: DoJob(){}; - virtual ~DoJob() { } - - virtual bool operator() ( wxDataViewTreeNode * node ) = 0 ; + virtual ~DoJob(){}; + + //The return value control how the tree-walker tranverse the tree + // 0: Job done, stop tranverse and return + // 1: Ignore the current node's subtree and continue + // 2: Job not done, continue + enum { OK = 0 , IGR = 1, CONT = 2 }; + virtual int operator() ( wxDataViewTreeNode * node ) = 0 ; }; class ItemAddJob: public DoJob { public: ItemAddJob( const wxDataViewItem & parent, const wxDataViewItem & item ) - { this->parent = parent ; this->item = item; } - virtual ~ItemAddJob() { } + { this->parent = parent ; this->item = item ; } + virtual ~ItemAddJob(){}; - virtual bool operator() ( wxDataViewTreeNode * node ) + virtual int operator() ( wxDataViewTreeNode * node ) { if( node->GetItem() == parent ) { wxDataViewTreeNode * newnode = new wxDataViewTreeNode( node ); newnode->SetItem(item); node->AppendChild( newnode); - return true; + return OK; } - return false; + return CONT; } - private: wxDataViewItem parent, item; }; @@ -1733,15 +1735,25 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func ) for( ; i < len ; i ++ ) { wxDataViewTreeNode * n = nodes[i]; - if( func( n ) ) - return true; - if( Walker( n , func ) ) - return true; + switch( func( n ) ) + { + case DoJob::OK : + return true ; + case DoJob::IGR: + continue; + case DoJob::CONT: + default: + ; + } + + if( Walker( n , func ) ) + return true; } return false; } + bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxDataViewItem & item) { ItemAddJob job( parent, item); @@ -1971,35 +1983,37 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if( col->GetModelColumn() == GetOwner()->GetExpanderColumn() ) { //Calculate the indent first - indent = cell_rect.x + GetOwner()->GetIndent() * indent; - + indent = cell_rect.x + GetOwner()->GetIndent() * indent; + int expander_width = m_lineHeight - 2*EXPANDER_MARGIN; - // change the cell_rect.x to the appropriate pos - int expander_x = indent + EXPANDER_MARGIN , expander_y = cell_rect.y + EXPANDER_MARGIN ; + // change the cell_rect.x to the appropriate pos + int expander_x = indent + EXPANDER_MARGIN , expander_y = cell_rect.y + EXPANDER_MARGIN ; indent = indent + m_lineHeight ; //try to use the m_lineHeight as the expander space dc.SetPen( m_penExpander ); - dc.SetBrush( wxNullBrush ); - if( node->HasChildren() ) - { - dc.DrawRoundedRectangle( expander_x,expander_y,expander_width,expander_width, 1.0); - dc.DrawLine( expander_x + 2 , expander_y + expander_width/2, expander_x + expander_width - 2, expander_y + expander_width/2 ); - - if( !node->IsOpen() ) - dc.DrawLine( expander_x + expander_width/2, expander_y + 2, expander_x + expander_width/2, expander_y + expander_width -2 ); - } - else - { - // I am wandering whether we should draw dot lines between tree nodes - } - - //force the expander column to left-center align - cell->SetAlignment( wxALIGN_CENTER_VERTICAL ); + dc.SetBrush( wxNullBrush ); + if( node->HasChildren() ) + { + //dc.DrawRoundedRectangle( expander_x,expander_y,expander_width,expander_width, 1.0); + //dc.DrawLine( expander_x + 2 , expander_y + expander_width/2, expander_x + expander_width - 2, expander_y + expander_width/2 ); + wxRect rect( expander_x , expander_y, expander_width, expander_width); + if( node->IsOpen() ) + wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, wxCONTROL_EXPANDED ); + else + wxRendererNative::Get().DrawTreeItemButton( this, dc, rect ); + } + else + { + // I am wandering whether we should draw dot lines between tree nodes + } + + //force the expander column to left-center align + cell->SetAlignment( wxALIGN_CENTER_VERTICAL ); } // cannot be bigger than allocated space wxSize size = cell->GetSize(); - // Because of the tree structure indent, here we should minus the width of the cell for drawing + // Because of the tree structure indent, here we should minus the width of the cell for drawing size.x = wxMin( size.x + 2*PADDING_RIGHTLEFT, cell_rect.width - indent ); size.y = wxMin( size.y + 2*PADDING_TOPBOTTOM, cell_rect.height ); @@ -2095,8 +2109,8 @@ unsigned int wxDataViewMainWindow::GetRowCount() if ( m_count == -1 ) { m_count = RecalculateCount(); - int width, height; - GetVirtualSize( &width, &height ); + int width, height; + GetVirtualSize( &width, &height ); height = m_count * m_lineHeight; SetVirtualSize( width, height ); @@ -2320,19 +2334,21 @@ public: RowToItemJob( unsigned int row , int current ) { this->row = row; this->current = current ;} virtual ~RowToItemJob(){}; - virtual bool operator() ( wxDataViewTreeNode * node ) + virtual int operator() ( wxDataViewTreeNode * node ) { - if ( current == row) - { - ret = node->GetItem() ; - return true; - } - current ++; - return false; - } - - wxDataViewItem GetResult() { return ret; } - + if( current == row) + { + ret = node->GetItem() ; + return DoJob::OK; + } + current ++; + if ( node->IsOpen()) + return DoJob::CONT; + else + return DoJob::IGR; + } + + wxDataViewItem GetResult(){ return ret; } private: unsigned int row; int current ; @@ -2349,23 +2365,22 @@ wxDataViewItem wxDataViewMainWindow::GetItemByRow(unsigned int row) class RowToTreeNodeJob: public DoJob { public: - RowToTreeNodeJob( unsigned int row , int current ) - { this->row = row; this->current = current ; ret = NULL ; } - virtual ~RowToTreeNodeJob() { } + RowToTreeNodeJob( unsigned int row , int current ) { this->row = row; this->current = current ; ret = NULL ; } + virtual ~RowToTreeNodeJob(){}; virtual int operator() ( wxDataViewTreeNode * node ) - { - if( current == row) - { - ret = node ; - return DoJob::OK; - } - current ++; - if ( node->IsOpen()) - return DoJob::CONT; - else - return DoJob::IGR; + { + if( current == row) + { + ret = node ; + return DoJob::OK; } + current ++; + if ( node->IsOpen()) + return DoJob::CONT; + else + return DoJob::IGR; + } wxDataViewTreeNode * GetResult(){ return ret; } private: @@ -2386,15 +2401,15 @@ class CountJob : public DoJob { public: CountJob(){ count = 0 ; } - virtual ~CountJob() { } + virtual ~CountJob(){}; virtual int operator () ( wxDataViewTreeNode * node ) { - count ++; - if (node->IsOpen()) - return DoJob::CONT; - else - return DoJob::IGR; + count ++; + if ( node->IsOpen()) + return DoJob::CONT; + else + return DoJob::IGR; } unsigned int GetResult() @@ -2410,13 +2425,13 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row ) wxDataViewTreeNode * node = GetTreeNodeByRow(row); if( node != NULL ) { - if (node->HasChildren()) - if (!node->IsOpen()) + if( node->HasChildren()) + if( !node->IsOpen()) { - node->ToggleOpen(); - m_count = -1; - Refresh(); - // RefreshRows(row,GetLastVisibleRow()); + node->ToggleOpen(); + m_count = -1; + Refresh(); + //RefreshRows(row,GetLastVisibleRow()); } } } @@ -2424,7 +2439,7 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row ) void wxDataViewMainWindow::OnCollapsing(unsigned int row) { wxDataViewTreeNode * node = GetTreeNodeByRow(row); - if (node != NULL) + if( node != NULL ) { if( node->HasChildren() && node->IsOpen() ) { @@ -2432,18 +2447,18 @@ void wxDataViewMainWindow::OnCollapsing(unsigned int row) m_count = -1; Refresh(); //RefreshRows(row,GetLastVisibleRow()); - } - else - { - node = node->GetParent(); - if( node != NULL ) - { - int parent = GetRowByItem( node->GetItem()) ; - SelectRow( row, false); - SelectRow(parent , true ); - ChangeCurrentRow( parent ); - } - } + } + else + { + node = node->GetParent(); + if( node != NULL ) + { + int parent = GetRowByItem( node->GetItem()) ; + SelectRow( row, false); + SelectRow(parent , true ); + ChangeCurrentRow( parent ); + } + } } } @@ -2460,13 +2475,17 @@ public: ItemToRowJob(const wxDataViewItem & item){ this->item = item ; ret = 0 ; } virtual ~ItemToRowJob(){}; - virtual bool operator() ( wxDataViewTreeNode * node) - { - ret ++; - if( node->GetItem() == item ) - return true; - return false; - } + virtual int operator() ( wxDataViewTreeNode * node) + { + ret ++; + if( node->GetItem() == item ) + return DoJob::OK; + + if( node->IsOpen()) + return DoJob::CONT; + else + return DoJob::IGR; + } //the row number is begin from zero int GetResult(){ return ret -1 ; } @@ -2723,24 +2742,24 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event ) } //Process the event of user clicking the expander - bool expander = false; - wxDataViewTreeNode * node = GetTreeNodeByRow(current); - if( node!=NULL && node->HasChildren() ) - { - int indent = node->GetIndentLevel(); - indent = GetOwner()->GetIndent()*indent; - wxRect rect( xpos + indent + EXPANDER_MARGIN, current * m_lineHeight + EXPANDER_MARGIN, m_lineHeight-2*EXPANDER_MARGIN,m_lineHeight-2*EXPANDER_MARGIN); - if( rect.Contains( x, y) ) - { - expander = true; - node->ToggleOpen(); - m_count = -1; //make the current row number fail + bool expander = false; + wxDataViewTreeNode * node = GetTreeNodeByRow(current); + if( node!=NULL && node->HasChildren() ) + { + int indent = node->GetIndentLevel(); + indent = GetOwner()->GetIndent()*indent; + wxRect rect( xpos + indent + EXPANDER_MARGIN, current * m_lineHeight + EXPANDER_MARGIN, m_lineHeight-2*EXPANDER_MARGIN,m_lineHeight-2*EXPANDER_MARGIN); + if( rect.Contains( x, y) ) + { + expander = true; + node->ToggleOpen(); + m_count = -1; //make the current row number fail - Refresh(); - //int last_row = GetLastVisibleRow(); - //RefreshRows( current, last_row ); - } - } + Refresh(); + //int last_row = GetLastVisibleRow(); + //RefreshRows( current, last_row ); + } + } //If the user click the expander, we do not do editing even if the column with expander are editable if (m_lastOnSame && !expander ) diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 20eccb9d22..f1f6d5a26a 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -52,9 +52,10 @@ WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes ); class wxGtkTreeModelNode { public: - wxGtkTreeModelNode( wxGtkTreeModelNode* parent ) + wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item ) { m_parent = parent; + m_item = item; } ~wxGtkTreeModelNode() @@ -82,7 +83,6 @@ public: unsigned int GetChildCount() { return m_children.GetCount(); } wxDataViewItem &GetItem() { return m_item; } - void SetItem( wxDataViewItem& item ) { m_item = item; } bool HasChildren() { return m_hasChildren; } void SetHasChildren( bool has ) { m_hasChildren = has; } @@ -102,14 +102,7 @@ typedef struct _GtkWxTreeModel GtkWxTreeModel; class wxGtkTreeModel { public: - wxGtkTreeModel( wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model ) - { - m_wx_model = wx_model; - m_gtk_model = gtk_model; - m_root = NULL; - InitTree(); - } - + wxGtkTreeModel( wxDataViewModel *wx_model, GtkWxTreeModel *owner ); ~wxGtkTreeModel(); gboolean get_iter( GtkTreeIter *iter, GtkTreePath *path ); @@ -121,14 +114,18 @@ public: 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_owner; } + protected: void InitTree(); wxGtkTreeModelNode *FindNode( GtkTreeIter *iter ); + void BuildBranch( wxGtkTreeModelNode *branch ); private: wxGtkTreeModelNode *m_root; wxDataViewModel *m_wx_model; - GtkWxTreeModel *m_gtk_model; + GtkWxTreeModel *m_owner; }; //----------------------------------------------------------------------------- @@ -160,12 +157,10 @@ struct _GtkWxTreeModel /*< private >*/ gint stamp; - wxDataViewModel *model; + wxGtkTreeModel *model; gint sort_column_id; GtkSortType order; - GtkTreeIterCompareFunc default_sort_func; - GtkTreeIterCompareFunc sort_func; }; struct _GtkWxTreeModelClass @@ -328,17 +323,15 @@ wxgtk_tree_model_init (GtkWxTreeModel *tree_model) tree_model->stamp = g_random_int(); tree_model->sort_column_id = -2; tree_model->order = GTK_SORT_ASCENDING; - tree_model->sort_func = NULL; - tree_model->default_sort_func = NULL; } static void wxgtk_tree_model_finalize (GObject *object) { - /* GtkWxTreeModel *tree_model = GTK_WX_LIST_STORE (object); */ + GtkWxTreeModel *tree_model = GTK_WX_TREE_MODEL(object); /* we need to sort out, which class deletes what */ - /* delete tree_model->model; */ + delete tree_model->model; /* must chain up */ (* list_parent_class->finalize) (object); @@ -365,7 +358,7 @@ wxgtk_tree_model_get_n_columns (GtkTreeModel *tree_model) GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), 0); - return wxtree_model->model->GetColumnCount(); + return wxtree_model->model->GetDataViewModel()->GetColumnCount(); } static GType @@ -377,7 +370,7 @@ wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model, GType gtype = G_TYPE_INVALID; - wxString wxtype = wxtree_model->model->GetColumnType( (unsigned int) index ); + wxString wxtype = wxtree_model->model->GetDataViewModel()->GetColumnType( (unsigned int) index ); if (wxtype == wxT("string")) gtype = G_TYPE_STRING; @@ -398,26 +391,7 @@ wxgtk_tree_model_get_iter (GtkTreeModel *tree_model, g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); - wxDataViewModel *model = wxtree_model->model; - - int depth = gtk_tree_path_get_depth( path ); - - wxDataViewItem item; - - int i; - for (i = 0; i < depth; i++) - { - gint pos = gtk_tree_path_get_indices (path)[i]; - item = model->GetNthChild( item, (unsigned int) pos ); - - if (!item.IsOk()) - return FALSE; - } - - iter->stamp = wxtree_model->stamp; - iter->user_data = (gpointer) item.GetID(); - - return TRUE; + return wxtree_model->model->get_iter( iter, path ); } static GtkTreePath * @@ -428,37 +402,7 @@ wxgtk_tree_model_get_path (GtkTreeModel *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); - GtkTreePath *retval = gtk_tree_path_new (); - wxDataViewItem item( (wxUint32) iter->user_data ); - - wxDataViewModel *model = wxtree_model->model; - - while (item.IsOk()) - { - int n = 0; - wxDataViewItem parent = model->GetParent( item ); - - if (!parent.IsOk()) - wxPrintf( wxT("wrong parent\n") ); - - wxDataViewItem node = model->GetFirstChild( parent ); - - while (node.GetID() != item.GetID()) - { - node = model->GetNextSibling( node ); - - if (!node.IsOk()) - wxPrintf( wxT("wrong node\n") ); - - n++; - } - - gtk_tree_path_prepend_index( retval, n ); - - item = model->GetParent( item ); - } - - return retval; + return wxtree_model->model->get_path( iter ); } static void @@ -470,7 +414,7 @@ wxgtk_tree_model_get_value (GtkTreeModel *tree_model, GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model) ); - wxDataViewModel *model = wxtree_model->model; + wxDataViewModel *model = wxtree_model->model->GetDataViewModel(); wxString mtype = model->GetColumnType( (unsigned int) column ); if (mtype == wxT("string")) { @@ -493,19 +437,9 @@ wxgtk_tree_model_iter_next (GtkTreeModel *tree_model, { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE); - wxDataViewModel *model = wxtree_model->model; - - wxDataViewItem item( (wxUint32) iter->user_data ); - item = model->GetNextSibling( item ); - if (!item.IsOk()) - return FALSE; - - iter->user_data = (gpointer) item.GetID(); - - return TRUE; + return wxtree_model->model->iter_next( iter ); } static gboolean @@ -515,20 +449,9 @@ wxgtk_tree_model_iter_children (GtkTreeModel *tree_model, { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - g_return_val_if_fail (wxtree_model->stamp == parent->stamp, FALSE); - - wxDataViewModel *model = wxtree_model->model; - - wxDataViewItem item( (wxUint32) parent->user_data ); - item = model->GetFirstChild( item ); - if (!item.IsOk()) - return FALSE; - iter->stamp = wxtree_model->stamp; - iter->user_data = (gpointer) item.GetID(); - - return TRUE; + return wxtree_model->model->iter_children( iter, parent ); } static gboolean @@ -537,14 +460,9 @@ wxgtk_tree_model_iter_has_child (GtkTreeModel *tree_model, { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE); - - wxDataViewModel *model = wxtree_model->model; - - wxDataViewItem item( (wxUint32) iter->user_data ); - - return model->HasChildren( item ); + + return wxtree_model->model->iter_has_child( iter ); } static gint @@ -553,14 +471,9 @@ wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model, { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - g_return_val_if_fail (wxtree_model->stamp == iter->stamp, 0); - - wxDataViewModel *model = wxtree_model->model; - - wxDataViewItem item( (wxUint32) iter->user_data ); - - return model->GetChildCount( item ); + + return wxtree_model->model->iter_n_children( iter ); } static gboolean @@ -572,34 +485,7 @@ wxgtk_tree_model_iter_nth_child (GtkTreeModel *tree_model, GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - wxDataViewModel *model = wxtree_model->model; - - if (!parent) - { - wxDataViewItem item; - item = model->GetNthChild( item, n ); - - if (!item.IsOk()) - return FALSE; - - iter->stamp = wxtree_model->stamp; - iter->user_data = (gpointer) item.GetID(); - } - else - { - g_return_val_if_fail (wxtree_model->stamp == parent->stamp, FALSE); - - wxDataViewItem item( (wxUint32) parent->user_data ); - item = model->GetNthChild( item, n ); - - if (!item.IsOk()) - return FALSE; - - iter->stamp = wxtree_model->stamp; - iter->user_data = (gpointer) item.GetID(); - } - - return TRUE; + return wxtree_model->model->iter_nth_child( iter, parent, n ); } static gboolean @@ -609,21 +495,9 @@ wxgtk_tree_model_iter_parent (GtkTreeModel *tree_model, { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - g_return_val_if_fail (wxtree_model->stamp == child->stamp, FALSE); - wxDataViewModel *model = wxtree_model->model; - - wxDataViewItem item( (wxUint32) child->user_data ); - item = model->GetParent( item ); - - if (!item.IsOk()) - return FALSE; - - iter->stamp = wxtree_model->stamp; - iter->user_data = (gpointer) item.GetID(); - - return TRUE; + return wxtree_model->model->iter_parent( iter, child ); } /* sortable */ @@ -659,11 +533,6 @@ void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortabl (tree_model->order == order)) return; - if (sort_column_id == GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID) - { - g_return_if_fail (tree_model->default_sort_func != NULL); - } - tree_model->sort_column_id = sort_column_id; tree_model->order = order; @@ -679,13 +548,9 @@ void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortabl gpointer data, GtkDestroyNotify destroy) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; - g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); g_return_if_fail (func != NULL); - tree_model->sort_func = func; - wxPrintf( "wxgtk_tree_model_set_sort_func, sort_column_id = %d\n", sort_column_id ); // sort } @@ -695,14 +560,9 @@ void wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortabl gpointer data, GtkDestroyNotify destroy) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; - g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); - g_return_if_fail (func != NULL); - tree_model->default_sort_func = func; - wxPrintf( "wxgtk_tree_model_set_default_sort_func\n" ); } @@ -711,6 +571,214 @@ gboolean wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortabl return FALSE; } + +//----------------------------------------------------------------------------- +// wxGtkTreeModel +//----------------------------------------------------------------------------- + +wxGtkTreeModel::wxGtkTreeModel( wxDataViewModel *wx_model, GtkWxTreeModel *owner ) +{ + m_wx_model = wx_model; + m_owner = owner; + m_root = NULL; + InitTree(); +} + +wxGtkTreeModel::~wxGtkTreeModel() +{ +} + +void wxGtkTreeModel::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 ) ); + child = m_wx_model->GetNextSibling( child ); + } + } +} + +gboolean wxGtkTreeModel::get_iter( GtkTreeIter *iter, GtkTreePath *path ) +{ + 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; + + node = node->GetChildren().Item( (size_t) pos ); + } + + iter->stamp = m_owner->stamp; + iter->user_data = (gpointer) node->GetItem().GetID(); + + return TRUE; +} + +GtkTreePath *wxGtkTreeModel::get_path( GtkTreeIter *iter ) +{ + GtkTreePath *retval = gtk_tree_path_new (); + + wxGtkTreeModelNode *node = FindNode( iter ); + while (node->GetParent()) + { + wxGtkTreeModelNode *parent = node->GetParent(); + int pos = parent->GetChildren().Index( parent ); + + gtk_tree_path_prepend_index( retval, pos ); + + node = parent; + } + + return retval; +} + +gboolean wxGtkTreeModel::iter_next( GtkTreeIter *iter ) +{ + wxDataViewItem item( (wxUint32) iter->user_data ); + item = m_wx_model->GetNextSibling( item ); + if (!item.IsOk()) + return FALSE; + + iter->user_data = (gpointer) item.GetID(); + + return TRUE; +} + +gboolean wxGtkTreeModel::iter_children( GtkTreeIter *iter, GtkTreeIter *parent ) +{ + wxDataViewItem item( (wxUint32) parent->user_data ); + + if (!m_wx_model->HasChildren( item )) + return FALSE; + + wxGtkTreeModelNode *parent_node = FindNode( parent ); + BuildBranch( parent_node ); + + wxGtkTreeModelNode *first_child_node = parent_node->GetChildren().Item( 0 ); + + iter->stamp = m_owner->stamp; + iter->user_data = (gpointer) first_child_node->GetItem().GetID(); + + return TRUE; +} + +gboolean wxGtkTreeModel::iter_has_child( GtkTreeIter *iter ) +{ + wxDataViewItem item( (wxUint32) iter->user_data ); + + return m_wx_model->HasChildren( item ); +} + +gint wxGtkTreeModel::iter_n_children( GtkTreeIter *iter ) +{ + wxDataViewItem item( (wxUint32) iter->user_data ); + + if (!m_wx_model->HasChildren( item )) + return 0; + + wxGtkTreeModelNode *parent_node = FindNode( iter ); + BuildBranch( parent_node ); + + return parent_node->GetChildCount(); +} + +gboolean wxGtkTreeModel::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ) +{ + wxUint32 id = 0; + if (parent) id = (wxUint32) parent->user_data; + wxDataViewItem item( id ); + + if (!m_wx_model->HasChildren( 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; + + iter->stamp = m_owner->stamp; + iter->user_data = (gpointer) child_node->GetItem().GetID(); + + return TRUE; +} + +gboolean wxGtkTreeModel::iter_parent( GtkTreeIter *iter, GtkTreeIter *child ) +{ + wxDataViewItem item( (wxUint32) child->user_data ); + + wxGtkTreeModelNode *node = FindNode( child ); + node = node->GetParent(); + if (!node) + return FALSE; + + iter->stamp = m_owner->stamp; + iter->user_data = (gpointer) node->GetItem().GetID(); + + return TRUE; +} + +void wxGtkTreeModel::InitTree() +{ + wxDataViewItem item; + m_root = new wxGtkTreeModelNode( NULL, item ); + + BuildBranch( m_root ); +} + +static wxGtkTreeModelNode* +wxGtkTreeModel_FindNode( wxGtkTreeModelNode *node, const wxDataViewItem &item ) +{ + if (!node) return NULL; + + size_t count = node->GetChildCount(); + size_t i; + for (i = 0; i < count; i++) + { + wxGtkTreeModelNode *child = node->GetChildren().Item( i ); + if (child->GetItem().GetID() == item.GetID()) + return child; + + wxGtkTreeModelNode *node2 = wxGtkTreeModel_FindNode( child, item ); + if (node2) + return node2; + } + + return NULL; +} + +wxGtkTreeModelNode *wxGtkTreeModel::FindNode( GtkTreeIter *iter ) +{ + if (!iter) + return m_root; + + wxDataViewItem item( (wxUint32) iter->user_data ); + + wxGtkTreeModelNode *result = wxGtkTreeModel_FindNode( m_root, item ); + + if (!result) + { + wxPrintf( "Not found %d\n", (int) iter->user_data ); + char *crash = NULL; + *crash = 0; + } + + return result; +} + //----------------------------------------------------------------------------- // define new GTK+ class wxGtkRendererRenderer //----------------------------------------------------------------------------- @@ -1900,7 +1968,7 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, wxDataViewItem item( (wxUint32) iter->user_data ); wxVariant value; - tree_model->model->GetValue( value, item, cell->GetOwner()->GetModelColumn() ); + tree_model->model->GetDataViewModel()->GetValue( value, item, cell->GetOwner()->GetModelColumn() ); if (value.GetType() != cell->GetVariantType()) wxLogError( wxT("Wrong type, required: %s but: %s"), @@ -2361,15 +2429,17 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model ) if (!wxDataViewCtrlBase::AssociateModel( model )) return false; - GtkWxTreeModel *gtk_store = wxgtk_tree_model_new(); - gtk_store->model = model; + GtkWxTreeModel *gtkwx_tree_model = wxgtk_tree_model_new(); + wxGtkTreeModel *wxgtk_tree_model = new wxGtkTreeModel( model, gtkwx_tree_model ); + + gtkwx_tree_model->model = wxgtk_tree_model; - m_notifier = new wxGtkDataViewModelNotifier( gtk_store, model, this ); + m_notifier = new wxGtkDataViewModelNotifier( gtkwx_tree_model, model, this ); model->AddNotifier( m_notifier ); - gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_store) ); - g_object_unref( gtk_store ); + gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtkwx_tree_model) ); + g_object_unref( gtkwx_tree_model ); return true; }