]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/dataview.cpp
Preserve original menu label for later retrieval
[wxWidgets.git] / src / gtk / dataview.cpp
index d0de7177ec3bc49a7c979c67e3750da52523e3d3..e9ad3b983df1b94799348b0f0a4e0be13ab7f050 100644 (file)
@@ -26,6 +26,8 @@
 #include "wx/calctrl.h"
 #include "wx/popupwin.h"
 #include "wx/icon.h"
+#include "wx/list.h"
+#include "wx/listimpl.cpp"
 
 
 #include "wx/gtk/private.h"
 #include <gdk/gdkkeysyms.h>
 
 //-----------------------------------------------------------------------------
-// classes
 //-----------------------------------------------------------------------------
 
-//-----------------------------------------------------------------------------
-// wxGtkTreeModelNode
-//-----------------------------------------------------------------------------
+wxDataViewModel *g_model = NULL;
 
 class wxGtkTreeModelNode;
-WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes );
-
-class wxGtkTreeModelNode
-{
-public:
-    wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item )
-    { 
-        m_parent = parent; 
-        m_item = item;
-    }
-    
-    ~wxGtkTreeModelNode()
-    { 
-        size_t count = m_children.GetCount();
-        size_t i;
-        for (i = 0; i < count; i++)
-        {
-            wxGtkTreeModelNode *child = m_children[i];
-            delete child;
-        }
-    }
-
-    wxGtkTreeModelNode* GetParent() 
-        { return m_parent; }
-    wxGtkTreeModelNodes &GetChildren() 
-        { 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(); }
-
-    wxDataViewItem &GetItem() { return m_item; }
-
-    bool HasChildren() { return m_hasChildren; }
-    void SetHasChildren( bool has ) { m_hasChildren = has; }
-    
-private:
-    wxGtkTreeModelNode  *m_parent;
-    wxGtkTreeModelNodes  m_children; 
-    wxDataViewItem       m_item; 
-    bool                 m_hasChildren;
-};
-
 
 extern "C" {
 typedef struct _GtkWxTreeModel       GtkWxTreeModel;
 }
 
-class wxGtkTreeModel
+//-----------------------------------------------------------------------------
+// wxDataViewCtrlInternal
+//-----------------------------------------------------------------------------
+
+WX_DECLARE_LIST(wxDataViewItem, ItemList);
+WX_DEFINE_LIST(ItemList);
+
+class wxDataViewCtrlInternal
 {
 public:
-    wxGtkTreeModel( wxDataViewModel *wx_model, GtkWxTreeModel *owner );
-    ~wxGtkTreeModel();
+    wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *owner );
+    ~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 );
@@ -115,23 +75,136 @@ public:
     gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child );
     
     wxDataViewModel* GetDataViewModel() { return m_wx_model; }
-    GtkWxTreeModel* GetOwner()          { return m_owner; }
+    wxDataViewCtrl* GetOwner()          { return m_owner; }
+    GtkWxTreeModel* GetGtkModel()       { return m_gtk_model; }
 
     bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
-    bool ItemDeleted( const wxDataViewItem &item );
+    bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item );
+    bool ItemChanged( const wxDataViewItem &item );
+    bool ValueChanged( const wxDataViewItem &item, unsigned int col );
+    bool Cleared();
+    void Resort();
     
 protected:
     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:
     wxGtkTreeModelNode   *m_root;
     wxDataViewModel      *m_wx_model;
-    GtkWxTreeModel       *m_owner;
+    GtkWxTreeModel       *m_gtk_model;
+    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
 //-----------------------------------------------------------------------------
@@ -161,10 +234,7 @@ struct _GtkWxTreeModel
 
   /*< private >*/
   gint stamp;
-  wxGtkTreeModel *model;
-  
-  gint sort_column_id;
-  GtkSortType order;
+  wxDataViewCtrlInternal *internal;
 };
 
 struct _GtkWxTreeModelClass
@@ -187,6 +257,8 @@ static gboolean     wxgtk_tree_model_get_iter        (GtkTreeModel      *tree_mo
                                                       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,
@@ -323,20 +395,13 @@ wxgtk_tree_model_sortable_init (GtkTreeSortableIface *iface)
 static void
 wxgtk_tree_model_init (GtkWxTreeModel *tree_model)
 {
-    tree_model->model = NULL;
+    tree_model->internal = NULL;
     tree_model->stamp = g_random_int();
-    tree_model->sort_column_id = -2;
-    tree_model->order = GTK_SORT_ASCENDING;
 }
 
 static void
 wxgtk_tree_model_finalize (GObject *object)
 {
-    GtkWxTreeModel *tree_model = GTK_WX_TREE_MODEL(object);
-
-    /* we need to sort out, which class deletes what */
-    delete tree_model->model;
-
     /* must chain up */
     (* list_parent_class->finalize) (object);
 }
@@ -362,7 +427,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->GetDataViewModel()->GetColumnCount();
+    return wxtree_model->internal->GetDataViewModel()->GetColumnCount();
 }
 
 static GType
@@ -374,7 +439,7 @@ wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
 
     GType gtype = G_TYPE_INVALID;
 
-    wxString wxtype = wxtree_model->model->GetDataViewModel()->GetColumnType( (unsigned int) index );
+    wxString wxtype = wxtree_model->internal->GetDataViewModel()->GetColumnType( (unsigned int) index );
 
     if (wxtype == wxT("string"))
         gtype = G_TYPE_STRING;
@@ -395,7 +460,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);
 
-    return wxtree_model->model->get_iter( iter, path );
+    return wxtree_model->internal->get_iter( iter, path );
 }
 
 static GtkTreePath *
@@ -406,7 +471,18 @@ 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);
 
-    return wxtree_model->model->get_path( iter );
+    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
@@ -418,7 +494,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->GetDataViewModel();
+    wxDataViewModel *model = wxtree_model->internal->GetDataViewModel();
     wxString mtype = model->GetColumnType( (unsigned int) column );
     if (mtype == wxT("string"))
     {
@@ -443,7 +519,7 @@ wxgtk_tree_model_iter_next (GtkTreeModel  *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);
 
-    return wxtree_model->model->iter_next( iter );
+    return wxtree_model->internal->iter_next( iter );
 }
 
 static gboolean
@@ -455,7 +531,7 @@ wxgtk_tree_model_iter_children (GtkTreeModel *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);
 
-    return wxtree_model->model->iter_children( iter, parent );
+    return wxtree_model->internal->iter_children( iter, parent );
 }
 
 static gboolean
@@ -466,7 +542,7 @@ wxgtk_tree_model_iter_has_child (GtkTreeModel *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);
 
-    return wxtree_model->model->iter_has_child( iter );
+    return wxtree_model->internal->iter_has_child( iter );
 }
 
 static gint
@@ -477,7 +553,7 @@ wxgtk_tree_model_iter_n_children (GtkTreeModel *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);
 
-    return wxtree_model->model->iter_n_children( iter );
+    return wxtree_model->internal->iter_n_children( iter );
 }
 
 static gboolean
@@ -489,7 +565,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);
 
-    return wxtree_model->model->iter_nth_child( iter, parent, n );
+    return wxtree_model->internal->iter_nth_child( iter, parent, n );
 }
 
 static gboolean
@@ -501,7 +577,7 @@ wxgtk_tree_model_iter_parent (GtkTreeModel *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);
     
-    return wxtree_model->model->iter_parent( iter, child );
+    return wxtree_model->internal->iter_parent( iter, child );
 }
 
 /* sortable */
@@ -513,14 +589,17 @@ gboolean wxgtk_tree_model_get_sort_column_id    (GtkTreeSortable        *sortabl
 
     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;
 }
@@ -530,20 +609,23 @@ void     wxgtk_tree_model_set_sort_column_id    (GtkTreeSortable        *sortabl
                                                      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 == (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);
-
-    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,
@@ -554,9 +636,6 @@ void     wxgtk_tree_model_set_sort_func         (GtkTreeSortable        *sortabl
 {
     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,
@@ -575,359 +654,120 @@ gboolean wxgtk_tree_model_has_default_sort_func (GtkTreeSortable        *sortabl
     return FALSE;
 }
 
-
 //-----------------------------------------------------------------------------
-// wxGtkTreeModel
+// define new GTK+ class wxGtkRendererRenderer
 //-----------------------------------------------------------------------------
 
-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 );
-        }
-    }
-}
+extern "C" {
 
-bool wxGtkTreeModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
-{
-    wxGtkTreeModelNode *parent_node = FindNode( parent );
-    parent_node->Append( new wxGtkTreeModelNode( parent_node, item ) );
-    return true;
-}
+#define GTK_TYPE_WX_CELL_RENDERER               (gtk_wx_cell_renderer_get_type ())
+#define GTK_WX_CELL_RENDERER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer))
+#define GTK_WX_CELL_RENDERER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
+#define GTK_IS_WX_CELL_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER))
+#define GTK_IS_WX_CELL_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER))
+#define GTK_WX_CELL_RENDERER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
+
+GType            gtk_wx_cell_renderer_get_type (void);
+
+typedef struct _GtkWxCellRenderer GtkWxCellRenderer;
+typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass;
 
-bool wxGtkTreeModel::ItemDeleted( const wxDataViewItem &item )
+struct _GtkWxCellRenderer
 {
-    wxGtkTreeModelNode *node = FindNode( item );
-    wxGtkTreeModelNode *parent = node->GetParent();
-    parent->GetChildren().Remove( node );
-    delete node;
+  GtkCellRenderer parent;
 
-    return true;
-}
+  /*< private >*/
+  wxDataViewCustomRenderer *cell;
+  guint32 last_click;
+};
 
-gboolean wxGtkTreeModel::get_iter( GtkTreeIter *iter, GtkTreePath *path )
+struct _GtkWxCellRendererClass
 {
-    int depth = gtk_tree_path_get_depth( path );
+  GtkCellRendererClass cell_parent_class;
+};
 
-    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 );
-    }
+static GtkCellRenderer *gtk_wx_cell_renderer_new   (void);
+static void gtk_wx_cell_renderer_init (
+                        GtkWxCellRenderer      *cell );
+static void gtk_wx_cell_renderer_class_init(
+                        GtkWxCellRendererClass *klass );
+static void gtk_wx_cell_renderer_finalize (
+                        GObject                *object );
+static void gtk_wx_cell_renderer_get_size (
+                        GtkCellRenderer         *cell,
+                        GtkWidget               *widget,
+                        GdkRectangle            *rectangle,
+                        gint                    *x_offset,
+                        gint                    *y_offset,
+                        gint                    *width,
+                        gint                    *height );
+static void gtk_wx_cell_renderer_render (
+                        GtkCellRenderer         *cell,
+                        GdkWindow               *window,
+                        GtkWidget               *widget,
+                        GdkRectangle            *background_area,
+                        GdkRectangle            *cell_area,
+                        GdkRectangle            *expose_area,
+                        GtkCellRendererState     flags );
+static gboolean gtk_wx_cell_renderer_activate(
+                        GtkCellRenderer         *cell,
+                        GdkEvent                *event,
+                        GtkWidget               *widget,
+                        const gchar             *path,
+                        GdkRectangle            *background_area,
+                        GdkRectangle            *cell_area,
+                        GtkCellRendererState     flags );
+static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
+                        GtkCellRenderer         *cell,
+                        GdkEvent                *event,
+                        GtkWidget               *widget,
+                        const gchar             *path,
+                        GdkRectangle            *background_area,
+                        GdkRectangle            *cell_area,
+                        GtkCellRendererState     flags );
 
-    iter->stamp = m_owner->stamp;
-    iter->user_data = (gpointer) node->GetItem().GetID();
 
-    return TRUE;
-}
+static GObjectClass *cell_parent_class = NULL;
 
-GtkTreePath *wxGtkTreeModel::get_path( GtkTreeIter *iter )
+}  // extern "C"
+
+GType
+gtk_wx_cell_renderer_get_type (void)
 {
-    GtkTreePath *retval = gtk_tree_path_new ();
-    
-    wxGtkTreeModelNode *node = FindNode( iter );
-    while (node->GetParent())
+    static GType cell_wx_type = 0;
+
+    if (!cell_wx_type)
     {
-        wxGtkTreeModelNode *parent = node->GetParent();
-        int pos = parent->GetChildren().Index( node );
-        
-        gtk_tree_path_prepend_index( retval, pos );
+        const GTypeInfo cell_wx_info =
+        {
+            sizeof (GtkWxCellRendererClass),
+            NULL, /* base_init */
+            NULL, /* base_finalize */
+            (GClassInitFunc) gtk_wx_cell_renderer_class_init,
+            NULL, /* class_finalize */
+            NULL, /* class_data */
+            sizeof (GtkWxCellRenderer),
+            0,          /* n_preallocs */
+            (GInstanceInitFunc) gtk_wx_cell_renderer_init,
+        };
 
-        node = parent;
+        cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
+            "GtkWxCellRenderer", &cell_wx_info, (GTypeFlags)0 );
     }
 
-    return retval;
+    return cell_wx_type;
 }
 
-gboolean wxGtkTreeModel::iter_next( GtkTreeIter *iter )
+static void
+gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell)
 {
-    wxDataViewItem item( (void*) iter->user_data );
-    item = m_wx_model->GetNextSibling( item );
-    if (!item.IsOk())
-        return FALSE;
-
-    iter->user_data = (gpointer) item.GetID();
-
-    return TRUE;
+    cell->cell = NULL;
+    cell->last_click = 0;
 }
 
-gboolean wxGtkTreeModel::iter_children( GtkTreeIter *iter, GtkTreeIter *parent )
-{
-    wxDataViewItem item( (void*) 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( (void*) iter->user_data );
-    
-    return m_wx_model->HasChildren( item );
-}
-
-gint wxGtkTreeModel::iter_n_children( GtkTreeIter *iter )
-{
-    wxDataViewItem item( (void*) 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 )
-{
-    void* id = NULL;
-    if (parent) id = (void*) 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( (void*) 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( (void*) 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;
-}
-
-wxGtkTreeModelNode *wxGtkTreeModel::FindNode( const wxDataViewItem &item )
-{
-    wxGtkTreeModelNode *result = wxGtkTreeModel_FindNode( m_root, item );
-    
-    if (!result)
-    {
-        wxPrintf( "Not found %d\n", (int) item.GetID() );
-        char *crash = NULL;
-        *crash = 0;
-    }
-    
-    return result;
-}
-
-//-----------------------------------------------------------------------------
-// define new GTK+ class wxGtkRendererRenderer
-//-----------------------------------------------------------------------------
-
-extern "C" {
-
-#define GTK_TYPE_WX_CELL_RENDERER               (gtk_wx_cell_renderer_get_type ())
-#define GTK_WX_CELL_RENDERER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer))
-#define GTK_WX_CELL_RENDERER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
-#define GTK_IS_WX_CELL_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER))
-#define GTK_IS_WX_CELL_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER))
-#define GTK_WX_CELL_RENDERER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
-
-GType            gtk_wx_cell_renderer_get_type (void);
-
-typedef struct _GtkWxCellRenderer GtkWxCellRenderer;
-typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass;
-
-struct _GtkWxCellRenderer
-{
-  GtkCellRenderer parent;
-
-  /*< private >*/
-  wxDataViewCustomRenderer *cell;
-  guint32 last_click;
-};
-
-struct _GtkWxCellRendererClass
-{
-  GtkCellRendererClass cell_parent_class;
-};
-
-
-static GtkCellRenderer *gtk_wx_cell_renderer_new   (void);
-static void gtk_wx_cell_renderer_init (
-                        GtkWxCellRenderer      *cell );
-static void gtk_wx_cell_renderer_class_init(
-                        GtkWxCellRendererClass *klass );
-static void gtk_wx_cell_renderer_finalize (
-                        GObject                *object );
-static void gtk_wx_cell_renderer_get_size (
-                        GtkCellRenderer         *cell,
-                        GtkWidget               *widget,
-                        GdkRectangle            *rectangle,
-                        gint                    *x_offset,
-                        gint                    *y_offset,
-                        gint                    *width,
-                        gint                    *height );
-static void gtk_wx_cell_renderer_render (
-                        GtkCellRenderer         *cell,
-                        GdkWindow               *window,
-                        GtkWidget               *widget,
-                        GdkRectangle            *background_area,
-                        GdkRectangle            *cell_area,
-                        GdkRectangle            *expose_area,
-                        GtkCellRendererState     flags );
-static gboolean gtk_wx_cell_renderer_activate(
-                        GtkCellRenderer         *cell,
-                        GdkEvent                *event,
-                        GtkWidget               *widget,
-                        const gchar             *path,
-                        GdkRectangle            *background_area,
-                        GdkRectangle            *cell_area,
-                        GtkCellRendererState     flags );
-static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
-                        GtkCellRenderer         *cell,
-                        GdkEvent                *event,
-                        GtkWidget               *widget,
-                        const gchar             *path,
-                        GdkRectangle            *background_area,
-                        GdkRectangle            *cell_area,
-                        GtkCellRendererState     flags );
-
-
-static GObjectClass *cell_parent_class = NULL;
-
-}  // extern "C"
-
-GType
-gtk_wx_cell_renderer_get_type (void)
-{
-    static GType cell_wx_type = 0;
-
-    if (!cell_wx_type)
-    {
-        const GTypeInfo cell_wx_info =
-        {
-            sizeof (GtkWxCellRendererClass),
-            NULL, /* base_init */
-            NULL, /* base_finalize */
-            (GClassInitFunc) gtk_wx_cell_renderer_class_init,
-            NULL, /* class_finalize */
-            NULL, /* class_data */
-            sizeof (GtkWxCellRenderer),
-            0,          /* n_preallocs */
-            (GInstanceInitFunc) gtk_wx_cell_renderer_init,
-        };
-
-        cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
-            "GtkWxCellRenderer", &cell_wx_info, (GTypeFlags)0 );
-    }
-
-    return cell_wx_type;
-}
-
-static void
-gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell)
-{
-    cell->cell = NULL;
-    cell->last_click = 0;
-}
-
-static void
-gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass *klass)
+static void
+gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
     GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
@@ -986,11 +826,10 @@ static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
 //    wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
     wxRect renderrect( cell_area->x, cell_area->y, cell_area->width, cell_area->height );
 
-    // wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
-
     GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
-    // TODO
-    wxDataViewItem item;
+    GtkTreeIter iter;
+    cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, treepath );
+    wxDataViewItem item( (void*) iter.user_data );
     gtk_tree_path_free( treepath );
 
     cell->StartEditing( item, renderrect );
@@ -1183,10 +1022,11 @@ public:
     ~wxGtkDataViewModelNotifier();
 
     virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
-    virtual bool ItemDeleted( const wxDataViewItem &item );
+    virtual bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item );
     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;
@@ -1214,7 +1054,7 @@ wxGtkDataViewModelNotifier::~wxGtkDataViewModelNotifier()
 
 bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
 {
-    m_wxgtk_model->model->ItemAdded( parent, item );
+    m_owner->GtkGetInternal()->ItemAdded( parent, item );
 
     GtkTreeIter iter;
     iter.stamp = m_wxgtk_model->stamp;
@@ -1229,23 +1069,28 @@ bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const
     return true;
 }
 
-bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &item )
+bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
 {
     GtkTreeIter iter;
     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 );
     gtk_tree_path_free (path);
 
-    m_wxgtk_model->model->ItemDeleted( item );
+    m_owner->GtkGetInternal()->ItemDeleted( parent, item );
     
     return true;
 }
 
+void wxGtkDataViewModelNotifier::Resort()
+{
+    m_owner->GtkGetInternal()->Resort();
+}
+
 bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item )
 {
     GtkTreeIter iter;
@@ -1258,6 +1103,8 @@ bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item )
         GTK_TREE_MODEL(m_wxgtk_model), path, &iter );
     gtk_tree_path_free (path);
 
+    m_owner->GtkGetInternal()->ItemChanged( item );
+    
     return true;
 }
 
@@ -1291,14 +1138,22 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig
             // Redraw
             gtk_widget_queue_draw_area( GTK_WIDGET(widget),
                 cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height );
+                
+            m_owner->GtkGetInternal()->ValueChanged( item, model_col );
+            
+            return true;
         }
     }
 
-    return true;
+    return false;
 }
 
 bool wxGtkDataViewModelNotifier::Cleared()
 {
+    // TODO: delete everything
+
+    m_owner->GtkGetInternal()->Cleared();
+    
     return false;
 }
 
@@ -1455,8 +1310,8 @@ static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
 
     GtkTreePath *path = gtk_tree_path_new_from_string( arg1 );
     GtkTreeIter iter;
-    // TODO    
-    wxDataViewItem item;
+    cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, path );
+    wxDataViewItem item( (void*) iter.user_data );;
     gtk_tree_path_free( path );
 
     unsigned int model_col = cell->GetOwner()->GetModelColumn();
@@ -1628,8 +1483,9 @@ static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
     wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
 
     GtkTreePath *gtk_path = gtk_tree_path_new_from_string( path );
-    // TODO
-    wxDataViewItem item;
+    GtkTreeIter iter;
+    cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, gtk_path );
+    wxDataViewItem item( (void*) iter.user_data );;
     gtk_tree_path_free( gtk_path );
 
     unsigned int model_col = cell->GetOwner()->GetModelColumn();
@@ -2012,7 +1868,7 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
     wxDataViewItem item( (void*) iter->user_data );
 
     wxVariant value;
-    tree_model->model->GetDataViewModel()->GetValue( value, item, cell->GetOwner()->GetModelColumn() );
+    tree_model->internal->GetDataViewModel()->GetValue( value, item, cell->GetOwner()->GetModelColumn() );
 
     if (value.GetType() != cell->GetVariantType())
         wxLogError( wxT("Wrong type, required: %s but: %s"),
@@ -2291,34 +2147,590 @@ void wxDataViewColumn::SetWidth( int width )
 
 
 //-----------------------------------------------------------------------------
-// wxDataViewCtrl signal callbacks
+// wxGtkTreeModelNode
 //-----------------------------------------------------------------------------
 
-static void
-wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCtrl *dv )
+void wxGtkTreeModelNode::Resort()
 {
-    if (!GTK_WIDGET_REALIZED(dv->m_widget))
+    g_model = m_internal->GetDataViewModel();
+    
+    size_t child_count = GetChildCount();
+    if (child_count == 0)
         return;
 
-    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED, dv->GetId() );
-    // TODO: item
-    event.SetModel( dv->GetModel() );
-    dv->GetEventHandler()->ProcessEvent( event );
-}
+    size_t node_count = GetNodesCount();
 
-static void
-wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path,
-                                   GtkTreeViewColumn *column, wxDataViewCtrl *dv )
-{
-    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, dv->GetId() );
-    // TODO: item
-    event.SetModel( dv->GetModel() );
-    dv->GetEventHandler()->ProcessEvent( event );
-}
+    if (child_count == 1)
+    {
+        if (node_count == 1)
+        {
+            wxGtkTreeModelNode *node = m_nodes.Item( 0 );
+            node->Resort();
+        }
+        return;
+    }
 
-//-----------------------------------------------------------------------------
-// wxDataViewCtrl
-//-----------------------------------------------------------------------------
+    wxGtkTreeModelChildren *new_array = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp );
+
+    size_t pos;
+    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 < child_count; pos++)
+    {
+        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;
+    
+    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)
+    {
+        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();
+    }
+}
+
+//-----------------------------------------------------------------------------
+// wxDataViewCtrlInternal
+//-----------------------------------------------------------------------------
+
+wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, 
+    wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model )
+{ 
+    m_owner = owner;
+    m_wx_model = wx_model; 
+    m_gtk_model = gtk_model; 
+    m_root = NULL; 
+    InitTree();
+}
+    
+wxDataViewCtrlInternal::~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())
+        {
+            if (m_wx_model->IsContainer( child ))
+                node->AddNode( new wxGtkTreeModelNode( node, child, this ) );
+            else
+                node->AddLeave( child.GetID() );
+    
+            // Don't send any events here
+    
+            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 );
+    if (m_wx_model->IsContainer( item ))
+        parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) );
+    else
+        parent_node->AddLeave( item.GetID() );
+        
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetModel( m_owner->GetModel() );
+    event.SetItem( item );
+    m_owner->GetEventHandler()->ProcessEvent( event );
+
+    return true;
+}
+
+bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+    wxGtkTreeModelNode *parent_node = FindNode( parent );
+    parent_node->DeleteChild( item.GetID() );
+    
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetModel( m_owner->GetModel() );
+    event.SetItem( item );
+    m_owner->GetEventHandler()->ProcessEvent( event );
+
+    return true;
+}
+
+bool wxDataViewCtrlInternal::ItemChanged( const wxDataViewItem &item )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetModel( m_owner->GetModel() );
+    event.SetItem( item );
+    m_owner->GetEventHandler()->ProcessEvent( event );
+    
+    return true;
+}
+
+bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned int col )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetModel( m_owner->GetModel() );
+    event.SetColumn( col );
+    event.SetItem( item );
+    m_owner->GetEventHandler()->ProcessEvent( event );
+    
+    return true;
+}
+
+bool wxDataViewCtrlInternal::Cleared()
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED, m_owner->GetId() );
+    event.SetEventObject( m_owner );
+    event.SetModel( m_owner->GetModel() );
+    m_owner->GetEventHandler()->ProcessEvent( event );
+    
+    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;
+
+    int i;
+    for (i = 0; i < depth; i++)    
+    {
+        BuildBranch( node );
+        
+        gint pos = gtk_tree_path_get_indices (path)[i];
+        if (pos < 0) return FALSE;
+        if ((size_t)pos >= node->GetChildCount()) return FALSE;
+        
+        void* id = node->GetChildren().Item( (size_t) pos );
+        
+        if (i == depth-1)
+        {
+            iter->stamp = m_gtk_model->stamp;
+            iter->user_data = id;
+            return TRUE;
+        }
+
+        size_t count = node->GetNodes().GetCount();
+        size_t pos2;
+        for (pos2 = 0; pos2 < count; pos2++)
+        {
+            wxGtkTreeModelNode *child_node = node->GetNodes().Item( pos2 );
+            if (child_node->GetItem().GetID() == id)
+            {
+                node = child_node;
+                break;
+            }
+        }        
+    }
+
+    return FALSE;
+}
+
+GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
+{
+    g_model = m_wx_model;
+    
+    GtkTreePath *retval = gtk_tree_path_new ();
+    void *id = iter->user_data;    
+    
+    wxGtkTreeModelNode *node = FindParentNode( iter );
+    while (node)
+    {
+        int pos = node->GetChildren().Index( id );
+        gtk_tree_path_prepend_index( retval, pos );
+        
+        id = node->GetItem().GetID();
+        node = node->GetParent();
+    }
+
+    return retval;
+}
+
+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 = FindParentNode( iter );
+    while (node)
+    {
+        size_t pos;
+        for (pos = 0; pos < node->GetChildren().GetCount(); pos++)
+        {
+            if (id == node->GetChildren().Item( pos ))
+            {
+                gtk_tree_path_prepend_index( retval, (int) pos );
+                continue;
+            }
+        }
+
+        id = node->GetItem().GetID();
+        node = node->GetParent();
+    }
+
+    return retval;
+}
+
+gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
+{
+    g_model = m_wx_model;
+    
+    wxGtkTreeModelNode *parent = FindParentNode( iter );
+    if( parent == NULL )
+        return FALSE;
+
+    unsigned int pos = parent->GetChildren().Index( iter->user_data );
+    
+    if (pos == parent->GetChildCount()-1)
+        return FALSE;
+        
+    iter->stamp = m_gtk_model->stamp;
+    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->IsContainer( item ))
+        return FALSE;
+        
+    wxGtkTreeModelNode *parent_node = FindNode( parent );
+    BuildBranch( parent_node );
+    
+    if (parent_node->GetChildCount() == 0)
+        return FALSE;
+        
+    iter->stamp = m_gtk_model->stamp;
+    iter->user_data = (gpointer) parent_node->GetChildren().Item( 0 );
+
+    return TRUE;
+}
+
+gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter )
+{
+    g_model = m_wx_model;
+    
+    wxDataViewItem item( (void*) iter->user_data );
+    bool is_container = m_wx_model->IsContainer( 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->IsContainer( item ))
+        return 0;
+    
+    wxGtkTreeModelNode *parent_node = FindNode( iter );
+    BuildBranch( parent_node );
+
+    // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() );
+    
+    return parent_node->GetChildCount();
+}
+
+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->IsContainer( item ))
+        return FALSE;
+    
+    wxGtkTreeModelNode *parent_node = FindNode( parent );
+    BuildBranch( parent_node );
+
+    // wxPrintf( "iter_nth_child %d\n", n );
+    
+    iter->stamp = m_gtk_model->stamp;
+    iter->user_data = parent_node->GetChildren().Item( n );
+
+    return TRUE;
+}
+
+gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child )
+{
+    g_model = m_wx_model;
+
+    wxGtkTreeModelNode *node = FindParentNode( child );
+    if (!node)
+        return FALSE;
+    
+    iter->stamp = m_gtk_model->stamp;
+    iter->user_data = (gpointer) node->GetItem().GetID();
+
+    return TRUE;
+}
+    
+static wxGtkTreeModelNode*
+wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
+{
+    if( model == NULL )
+        return NULL;
+
+    ItemList list;
+    list.DeleteContents( true );
+    wxDataViewItem it( item );
+    while( it.IsOk() )
+    {
+        wxDataViewItem * pItem = new wxDataViewItem( it );
+        list.Insert( pItem );
+        it = model->GetParent( it );
+    }
+
+    wxGtkTreeModelNode * node = treeNode;
+    for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
+    {
+        if( node && node->GetNodes().GetCount() != 0 )
+        {
+            int len = node->GetNodes().GetCount();
+            wxGtkTreeModelNodes nodes = node->GetNodes();
+            int j = 0;
+            for( ; j < len; j ++)
+            {
+                if( nodes[j]->GetItem() == *(n->GetData()))
+                {
+                    node = nodes[j];
+                    break;
+                }    
+            }
+
+            if( j == len )
+            {
+                return NULL;
+            }
+        }
+        else
+            return NULL;
+    }
+    return node;
+
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter )
+{
+    if (!iter)
+        return m_root;
+
+    wxDataViewItem item( (void*) iter->user_data );
+    if (!item.IsOk())
+        return m_root;
+    
+    wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
+    
+    if (!result)
+    {
+        wxPrintf( "Not found %d\n", (int) iter->user_data );
+        char *crash = NULL;
+        *crash = 0;
+    }
+    
+    return result;
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item )
+{
+    if (!item.IsOk())
+        return m_root;
+
+    wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
+    
+    if (!result)
+    {
+        wxPrintf( "Not found %d\n", (int) item.GetID() );
+        char *crash = NULL;
+        *crash = 0;
+    }
+    
+    return result;
+}
+
+static wxGtkTreeModelNode*
+wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
+{
+    if( model == NULL )
+        return NULL;
+
+    ItemList list;
+    list.DeleteContents( true );
+    if( !item.IsOk() )
+        return NULL;
+
+    wxDataViewItem it( model->GetParent( item ) );
+    while( it.IsOk() )
+    {
+        wxDataViewItem * pItem = new wxDataViewItem( it );
+        list.Insert( pItem );
+        it = model->GetParent( it );
+    }
+
+    wxGtkTreeModelNode * node = treeNode;
+    for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
+    {
+        if( node && node->GetNodes().GetCount() != 0 )
+        {
+            int len = node->GetNodes().GetCount();
+            wxGtkTreeModelNodes nodes = node->GetNodes();
+            int j = 0;
+            for( ; j < len; j ++)
+            {
+                if( nodes[j]->GetItem() == *(n->GetData()))
+                {
+                    node = nodes[j];
+                    break;
+                }    
+            }
+
+            if( j == len )
+            {
+                return NULL;
+            }
+        }
+        else
+            return NULL;
+    }
+    //Examine whether the node is item's parent node
+    int len = node->GetChildCount();
+    for( int i = 0; i < len ; i ++ )
+    {
+        if( node->GetChildren().Item( i ) == item.GetID() )
+            return node;
+    }
+    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_wx_model, m_root, item );
+}
+
+wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( const wxDataViewItem &item )
+{
+    if (!item.IsOk())
+        return NULL;
+
+    return wxDataViewCtrlInternal_FindParentNode( m_wx_model, m_root, item );
+}
+
+//-----------------------------------------------------------------------------
+// wxDataViewCtrl signal callbacks
+//-----------------------------------------------------------------------------
+
+static void
+wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCtrl *dv )
+{
+    if (!GTK_WIDGET_REALIZED(dv->m_widget))
+        return;
+
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED, dv->GetId() );
+    // TODO: item
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
+}
+
+static void
+wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path,
+                                   GtkTreeViewColumn *column, wxDataViewCtrl *dv )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, dv->GetId() );
+
+    GtkTreeIter iter;
+    dv->GtkGetInternal()->get_iter( &iter, path );
+    wxDataViewItem item( (void*) iter.user_data );;
+    event.SetItem( item );
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
+}
+
+//-----------------------------------------------------------------------------
+// wxDataViewCtrl
+//-----------------------------------------------------------------------------
 
 //-----------------------------------------------------------------------------
 // InsertChild for wxDataViewCtrl
@@ -2341,8 +2753,7 @@ void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget),
                                      GtkAllocation *alloc,
                                      wxDataViewCtrl *win )
 {
-
-    wxWindowList::Node *node = win->GetChildren().GetFirst();
+    wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
     while (node)
     {
         wxWindow *child = node->GetData();
@@ -2373,6 +2784,8 @@ wxDataViewCtrl::~wxDataViewCtrl()
     // remove the model from the GtkTreeView before it gets destroyed by the
     // wxDataViewCtrlBase's dtor
     gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), NULL );
+    
+    delete m_internal;
 }
 
 void wxDataViewCtrl::Init()
@@ -2473,17 +2886,18 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
     if (!wxDataViewCtrlBase::AssociateModel( model ))
         return false;
 
-    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;
+    GtkWxTreeModel *gtk_model = wxgtk_tree_model_new();
+    m_internal = new wxDataViewCtrlInternal( this, model, gtk_model );
+    gtk_model->internal = m_internal;
 
-    m_notifier = new wxGtkDataViewModelNotifier( gtkwx_tree_model, model, this );
+    m_notifier = new wxGtkDataViewModelNotifier( gtk_model, model, this );
 
     model->AddNotifier( m_notifier );
 
-    gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtkwx_tree_model) );
-    g_object_unref( gtkwx_tree_model );
+    gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_model) );
+    
+    // unref in wxDataViewCtrlInternal
+    // g_object_unref( gtk_model );
 
     return true;
 }