]> git.saurik.com Git - wxWidgets.git/commitdiff
More patches from Bo, reduced wxDataViewModel, more sorting preps
authorRobert Roebling <robert@roebling.de>
Fri, 13 Jul 2007 00:35:39 +0000 (00:35 +0000)
committerRobert Roebling <robert@roebling.de>
Fri, 13 Jul 2007 00:35:39 +0000 (00:35 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@47410 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/dataview.h
samples/dataview/dataview.cpp
src/common/datavcmn.cpp
src/generic/datavgen.cpp
src/gtk/dataview.cpp

index 459885406b8b6f13c834952d33b03ffda82ea9ed..e96135b52618d0cb7540e3603a34bda358786146 100644 (file)
@@ -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 );
index 8a0670f35ba49d0fbf18263a5859304a8d678b7a..a6259d29b1b5ec7d6785cd4f5428b6b346fc81e7 100644 (file)
@@ -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);
-    }
 };
 
 // -------------------------------------
index 9cd318eb0f58f4c8f6070ea35b1f1155fe07d7e8..f8f5154fa29e1aba0be610690944d2089c118bc0 100644 (file)
 const wxChar wxDataViewCtrlNameStr[] = wxT("dataviewCtrl");
 
 
+bool operator == (const wxDataViewItem &left, const wxDataViewItem &right)
+{
+    return (left.GetID() == right.GetID() );
+}
+
+
 // ---------------------------------------------------------
-// wxDataViewListModel
+// wxDataViewModel
 // ---------------------------------------------------------
 
 wxDataViewModel::wxDataViewModel()
index e590c950fa9d458c4415bbb2ac3c578984149def..92414ec47d2282e3443c2d265acc7ca5d8e299bf 100644 (file)
@@ -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())
+        ifnode->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 )
index 20eccb9d2204e412eaeeeaf581fbb2733e32f35f..f1f6d5a26a1b69e1803b7277d8e0f23ef75a61bb 100644 (file)
@@ -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;
 }