]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/dataview.cpp
added wxUTF8StringBuffer for writing UTF8 data into wxString efficiently, similarly...
[wxWidgets.git] / src / gtk / dataview.cpp
index e9ad3b983df1b94799348b0f0a4e0be13ab7f050..c74207cd42464426eea0a1d9b67566afeb78a4d3 100644 (file)
@@ -43,7 +43,9 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
-wxDataViewModel *g_model = NULL;
+class wxDataViewCtrlInternal;
+
+wxDataViewCtrlInternal *g_internal = NULL;
 
 class wxGtkTreeModelNode;
 
@@ -85,6 +87,12 @@ public:
     bool Cleared();
     void Resort();
     
+    void SetSortOrder( GtkSortType sort_order ) { m_sort_order = sort_order; }
+    GtkSortType GetSortOrder()                  { return m_sort_order; }
+
+    void SetSortColumn( unsigned int column )   { m_sort_column = column; }
+    unsigned int GetSortColumn()                { return m_sort_column; }
+    
 protected:
     void InitTree();
     wxGtkTreeModelNode *FindNode( const wxDataViewItem &item );
@@ -98,6 +106,8 @@ private:
     wxDataViewModel      *m_wx_model;
     GtkWxTreeModel       *m_gtk_model;
     wxDataViewCtrl       *m_owner;
+    GtkSortType           m_sort_order;
+    unsigned int          m_sort_column;
 };
 
 
@@ -119,13 +129,13 @@ public:
         m_parent = parent; 
         m_item = item;
         m_internal = internal;
-        g_model = internal->GetDataViewModel();
+        g_internal = internal;
         m_children = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp );
     }
     
     ~wxGtkTreeModelNode()
     { 
-        g_model = m_internal->GetDataViewModel();
+        g_internal = m_internal;
         size_t count = m_children->GetCount();
         size_t i;
         for (i = 0; i < count; i++)
@@ -138,20 +148,20 @@ public:
 
     unsigned int AddNode( wxGtkTreeModelNode* child ) 
         { 
-            g_model = m_internal->GetDataViewModel();
+            g_internal = m_internal;
             m_nodes.Add( child );
             return m_children->Add( child->GetItem().GetID() );
         }
         
     unsigned int AddLeave( void* id )
         {
-            g_model = m_internal->GetDataViewModel();
+            g_internal = m_internal;
             return m_children->Add( id );
         }
         
     void DeleteChild( void* id )
         {
-            g_model = m_internal->GetDataViewModel();
+            g_internal = m_internal;
             size_t pos;
             size_t count = m_children->GetCount();
             for (pos = 0; pos < count; pos++)
@@ -202,7 +212,10 @@ private:
 
 int LINKAGEMODE wxGtkTreeModelNodeCmp( void* id1, void* id2 )
 {
-    return g_model->Compare( id1, id2 );
+    int ret = g_internal->GetDataViewModel()->Compare( id1, id2, 
+        g_internal->GetSortColumn(), (g_internal->GetSortOrder() == GTK_SORT_ASCENDING) );
+        
+    return ret;
 }
 
 //-----------------------------------------------------------------------------
@@ -590,42 +603,38 @@ gboolean wxgtk_tree_model_get_sort_column_id    (GtkTreeSortable        *sortabl
     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE);
 
     if (sort_column_id)
-        *sort_column_id = tree_model->internal->GetDataViewModel()->GetSortingColumn();
+        *sort_column_id = tree_model->internal->GetSortColumn();
         
     if (order)
-    {
-        bool ascending = tree_model->internal->GetDataViewModel()->GetSortOrderAscending();
-        if (ascending)
-            *order = GTK_SORT_ASCENDING;
-        else
-            *order = GTK_SORT_DESCENDING;
-    }
+        *order = tree_model->internal->GetSortOrder();
         
     return TRUE;
 }
 
-void     wxgtk_tree_model_set_sort_column_id    (GtkTreeSortable        *sortable,
+void     wxgtk_tree_model_set_sort_column_id  (GtkTreeSortable        *sortable,
                                                      gint                      sort_column_id,
                                                      GtkSortType               order)
 {
     GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable;
     g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
 
-    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()))
+    if ((sort_column_id == (gint) tree_model->internal->GetSortColumn()) &&
+        (order == tree_model->internal->GetSortOrder()))
         return;
     
-    tree_model->internal->GetDataViewModel()->SetSortingColumn( sort_column_id );
+    tree_model->internal->SetSortColumn( sort_column_id );
     
-    tree_model->internal->GetDataViewModel()->SetSortOrderAscending( ascending );
+    tree_model->internal->SetSortOrder( order );
     
     gtk_tree_sortable_sort_column_changed (sortable);
     
     tree_model->internal->GetDataViewModel()->Resort();
+
+    wxDataViewCtrl *dv = tree_model->internal->GetOwner();    
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, dv->GetId() );
+    // TODO event.SetDataViewColumn( column );
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
 }
 
 void     wxgtk_tree_model_set_sort_func         (GtkTreeSortable        *sortable,
@@ -1839,7 +1848,7 @@ gtk_dataview_header_button_press_callback( GtkWidget *widget,
         event.SetDataViewColumn( column );
         event.SetModel( dv->GetModel() );
         if (dv->GetEventHandler()->ProcessEvent( event ))
-            return TRUE;
+            return FALSE;
     }
 
     return FALSE;
@@ -2152,7 +2161,7 @@ void wxDataViewColumn::SetWidth( int width )
 
 void wxGtkTreeModelNode::Resort()
 {
-    g_model = m_internal->GetDataViewModel();
+    g_internal = m_internal;
     
     size_t child_count = GetChildCount();
     if (child_count == 0)
@@ -2239,6 +2248,8 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
     m_wx_model = wx_model; 
     m_gtk_model = gtk_model; 
     m_root = NULL; 
+    m_sort_order = GTK_SORT_ASCENDING;
+    m_sort_column = 0;
     InitTree();
 }
     
@@ -2345,7 +2356,7 @@ bool wxDataViewCtrlInternal::Cleared()
 
 gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     int depth = gtk_tree_path_get_depth( path );
 
@@ -2387,7 +2398,7 @@ gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path
 
 GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     GtkTreePath *retval = gtk_tree_path_new ();
     void *id = iter->user_data;    
@@ -2407,7 +2418,7 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
 
 GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     GtkTreePath *retval = gtk_tree_path_new ();
     void *id = iter->user_data;    
@@ -2434,7 +2445,7 @@ GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter )
 
 gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     wxGtkTreeModelNode *parent = FindParentNode( iter );
     if( parent == NULL )
@@ -2453,7 +2464,7 @@ gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
 
 gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     wxDataViewItem item( (void*) parent->user_data );
     
@@ -2474,7 +2485,7 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *
 
 gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     wxDataViewItem item( (void*) iter->user_data );
     bool is_container = m_wx_model->IsContainer( item );
@@ -2490,7 +2501,7 @@ gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter )
 
 gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     wxDataViewItem item( (void*) iter->user_data );
     
@@ -2507,7 +2518,7 @@ gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
 
 gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n )
 {
-    g_model = m_wx_model;
+    g_internal = this;
     
     void* id = NULL;
     if (parent) id = (void*) parent->user_data;
@@ -2529,7 +2540,7 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter
 
 gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child )
 {
-    g_model = m_wx_model;
+    g_internal = this;
 
     wxGtkTreeModelNode *node = FindParentNode( child );
     if (!node)
@@ -2709,7 +2720,7 @@ wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCt
         return;
 
     wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED, dv->GetId() );
-    // TODO: item
+    event.SetItem( dv->GetSelection() );
     event.SetModel( dv->GetModel() );
     dv->GetEventHandler()->ProcessEvent( event );
 }
@@ -2728,8 +2739,60 @@ wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path,
     dv->GetEventHandler()->ProcessEvent( event );
 }
 
+static gboolean
+wxdataview_test_expand_row_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+                                     GtkTreePath *path, wxDataViewCtrl *dv )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, dv->GetId() );
+
+    wxDataViewItem item( (void*) iter->user_data );;
+    event.SetItem( item );
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
+  
+    return !event.IsAllowed();
+}
+
+static void
+wxdataview_row_expanded_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+                                  GtkTreePath *path, wxDataViewCtrl *dv )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, dv->GetId() );
+
+    wxDataViewItem item( (void*) iter->user_data );;
+    event.SetItem( item );
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
+}
+
+static gboolean
+wxdataview_test_collapse_row_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+                                       GtkTreePath *path, wxDataViewCtrl *dv )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, dv->GetId() );
+
+    wxDataViewItem item( (void*) iter->user_data );;
+    event.SetItem( item );
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
+    
+    return !event.IsAllowed();
+}
+
+static void
+wxdataview_row_collapsed_callback( GtkTreeView* treeview, GtkTreeIter* iter,
+                                   GtkTreePath *path, wxDataViewCtrl *dv )
+{
+    wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, dv->GetId() );
+
+    wxDataViewItem item( (void*) iter->user_data );;
+    event.SetItem( item );
+    event.SetModel( dv->GetModel() );
+    dv->GetEventHandler()->ProcessEvent( event );
+}
+
 //-----------------------------------------------------------------------------
-// wxDataViewCtrl
+    // wxDataViewCtrl
 //-----------------------------------------------------------------------------
 
 //-----------------------------------------------------------------------------
@@ -2862,9 +2925,21 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
 
     GtkEnableSelectionEvents();
 
-    g_signal_connect_after (m_treeview, "row_activated",
+    g_signal_connect_after (m_treeview, "row-activated",
                             G_CALLBACK (wxdataview_row_activated_callback), this);
 
+    g_signal_connect (m_treeview, "test-collapse-row",
+                            G_CALLBACK (wxdataview_test_collapse_row_callback), this);
+
+    g_signal_connect_after (m_treeview, "row-collapsed",
+                            G_CALLBACK (wxdataview_row_collapsed_callback), this);
+
+    g_signal_connect (m_treeview, "test-expand-row",
+                            G_CALLBACK (wxdataview_test_expand_row_callback), this);
+                            
+    g_signal_connect_after (m_treeview, "row-expanded",
+                            G_CALLBACK (wxdataview_row_expanded_callback), this);
+
     return true;
 }
 
@@ -2920,6 +2995,22 @@ wxDataViewItem wxDataViewCtrl::GetSelection()
     
     if (m_windowStyle & wxDV_MULTIPLE)
     {
+        // Report the first one
+        GtkTreeModel *model;
+        GList *list = gtk_tree_selection_get_selected_rows( selection, &model );
+    
+        if (list)
+        {
+            GtkTreePath *path = (GtkTreePath*) list->data;
+            GtkTreeIter iter;
+            m_internal->get_iter( &iter, path );
+            
+            // delete list
+            g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL );
+            g_list_free( list );
+            
+            return wxDataViewItem( (void*) iter.user_data );
+        }
     }
     else
     {
@@ -2934,6 +3025,137 @@ wxDataViewItem wxDataViewCtrl::GetSelection()
     return wxDataViewItem(0);
 }
 
+int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const
+{
+    sel.Clear();
+
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+    if (HasFlag(wxDV_MULTIPLE))
+    {
+        GtkTreeModel *model;
+        GList *list = gtk_tree_selection_get_selected_rows( selection, &model );
+
+        int count = 0;
+        while (list)
+        {
+            GtkTreePath *path = (GtkTreePath*) list->data;
+            
+            GtkTreeIter iter;
+            m_internal->get_iter( &iter, path );
+
+            sel.Add( wxDataViewItem( (void*) iter.user_data ) );
+
+            list = g_list_next( list );
+            count++;
+        }
+
+        // delete list
+        g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL );
+        g_list_free( list );
+
+        return count;
+    }
+    else
+    {
+        GtkTreeModel *model;
+        GtkTreeIter iter;
+        gboolean has_selection = gtk_tree_selection_get_selected( selection, &model, &iter );
+        if (has_selection)
+        {
+            sel.Add( wxDataViewItem( (void*) iter.user_data) );
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )
+{
+    GtkDisableSelectionEvents();
+    
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+
+    gtk_tree_selection_unselect_all( selection );
+    
+    size_t i;
+    for (i = 0; i < sel.GetCount(); i++)
+    {
+        GtkTreeIter iter;
+        iter.user_data = (gpointer) sel[i].GetID();
+        gtk_tree_selection_select_iter( selection, &iter );
+    }
+    
+    GtkEnableSelectionEvents();
+}
+
+void wxDataViewCtrl::Select( const wxDataViewItem & item )
+{
+    GtkDisableSelectionEvents();
+
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+
+    GtkTreeIter iter;
+    iter.user_data = (gpointer) item.GetID();
+    gtk_tree_selection_select_iter( selection, &iter );
+
+    GtkEnableSelectionEvents();
+}
+
+void wxDataViewCtrl::Unselect( const wxDataViewItem & item )
+{
+    GtkDisableSelectionEvents();
+
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+
+    GtkTreeIter iter;
+    iter.user_data = (gpointer) item.GetID();
+    gtk_tree_selection_unselect_iter( selection, &iter );
+
+    GtkEnableSelectionEvents();
+}
+
+bool wxDataViewCtrl::IsSelected( const wxDataViewItem & item ) const
+{
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+
+    GtkTreeIter iter;
+    iter.user_data = (gpointer) item.GetID();
+    
+    return gtk_tree_selection_iter_is_selected( selection, &iter );
+}
+
+void wxDataViewCtrl::SelectAll()
+{
+    GtkDisableSelectionEvents();
+    
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+    
+    gtk_tree_selection_select_all( selection );
+    
+    GtkEnableSelectionEvents();
+}
+
+void wxDataViewCtrl::UnselectAll()
+{
+    GtkDisableSelectionEvents();
+    
+    GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
+    
+    gtk_tree_selection_unselect_all( selection );
+    
+    GtkEnableSelectionEvents();
+}
+
+void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, wxDataViewColumn *column )
+{
+    GtkTreeIter iter;
+    iter.user_data = (gpointer) item.GetID();
+    GtkTreePath *path = m_internal->get_path( &iter );
+    gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(m_treeview), path, NULL, false, 0.0, 0.0 );
+    gtk_tree_path_free( path );
+}
+
 void wxDataViewCtrl::DoSetExpanderColumn()
 {
 }
@@ -2945,15 +3167,15 @@ void wxDataViewCtrl::DoSetIndent()
 void wxDataViewCtrl::GtkDisableSelectionEvents()
 {
     GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
-    g_signal_connect_after (selection, "changed",
-                            G_CALLBACK (wxdataview_selection_changed_callback), this);
+    g_signal_handlers_disconnect_by_func( selection,
+                            (gpointer) (wxdataview_selection_changed_callback), this);
 }
 
 void wxDataViewCtrl::GtkEnableSelectionEvents()
 {
     GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
-    g_signal_handlers_disconnect_by_func( selection,
-                            (gpointer) (wxdataview_selection_changed_callback), this);
+    g_signal_connect_after (selection, "changed",
+                            G_CALLBACK (wxdataview_selection_changed_callback), this);
 }
 
 // static