]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/dataview.cpp
Fix activation handling in generic wxDataViewCtrl renderers.
[wxWidgets.git] / src / gtk / dataview.cpp
index f77f50d776fc7315854b91ee7d514a930074a22a..bc3f27ad3571b9b8816b767e655b7bb8e4fe3655 100644 (file)
@@ -111,6 +111,9 @@ public:
     wxDataViewCtrl* GetOwner()          { return m_owner; }
     GtkWxTreeModel* GetGtkModel()       { return m_gtk_model; }
 
+    // item can be deleted already in the model
+    int GetIndexOf( const wxDataViewItem &parent, const wxDataViewItem &item );
+
 protected:
     void InitTree();
     wxGtkTreeModelNode *FindNode( const wxDataViewItem &item );
@@ -542,8 +545,8 @@ wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
         gtype = G_TYPE_STRING;
     else
     {
-        gtype = G_TYPE_STRING;
-        // wxFAIL_MSG( wxT("non-string columns not supported yet") );
+        gtype = G_TYPE_POINTER;
+        // wxFAIL_MSG( wxT("non-string columns not supported for searching yet") );
     }
 
     return gtype;
@@ -620,7 +623,10 @@ 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);
+    if (parent)
+    {
+        g_return_val_if_fail (wxtree_model->stamp == parent->stamp, FALSE);
+    }
 
     return wxtree_model->internal->iter_children( iter, parent );
 }
@@ -1394,12 +1400,26 @@ bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const
 
 bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
 {
+#if 0
+    // using _get_path for a deleted item cannot be
+    // a good idea
     GtkTreeIter iter;
     iter.stamp = m_wxgtk_model->stamp;
     iter.user_data = (gpointer) item.GetID();
-
     GtkTreePath *path = wxgtk_tree_model_get_path(
         GTK_TREE_MODEL(m_wxgtk_model), &iter );
+#else
+    // so get the path from the parent
+    GtkTreeIter iter;
+    iter.stamp = m_wxgtk_model->stamp;
+    iter.user_data = (gpointer) parent.GetID();
+    GtkTreePath *path = wxgtk_tree_model_get_path(
+        GTK_TREE_MODEL(m_wxgtk_model), &iter );
+    // and add the final index ourselves
+    int index = m_owner->GtkGetInternal()->GetIndexOf( parent, item );
+    gtk_tree_path_append_index( path, index );
+#endif
+
     gtk_tree_model_row_deleted(
         GTK_TREE_MODEL(m_wxgtk_model), path );
     gtk_tree_path_free (path);
@@ -1678,31 +1698,47 @@ int wxDataViewRenderer::GetAlignment() const
 
 void wxDataViewRenderer::EnableEllipsize(wxEllipsizeMode mode)
 {
+#ifdef __WXGTK26__
     if ( gtk_check_version(2, 6, 0) != NULL )
         return;
 
+    GtkCellRendererText * const rend = GtkGetTextRenderer();
+    if ( !rend )
+        return;
+
     // we use the same values in wxEllipsizeMode as PangoEllipsizeMode so we
     // can just cast between them
     GValue gvalue = { 0, };
     g_value_init( &gvalue, PANGO_TYPE_ELLIPSIZE_MODE );
     g_value_set_enum( &gvalue, static_cast<PangoEllipsizeMode>(mode) );
-    g_object_set_property( G_OBJECT(m_renderer), "ellipsize", &gvalue );
+    g_object_set_property( G_OBJECT(rend), "ellipsize", &gvalue );
     g_value_unset( &gvalue );
+#else // GTK < 2.6
+    wxUnusedVar(mode);
+#endif // GTK 2.6/before
 }
 
 wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
 {
+#ifdef __WXGTK26__
     if ( gtk_check_version(2, 6, 0) != NULL )
         return wxELLIPSIZE_NONE;
 
+    GtkCellRendererText * const rend = GtkGetTextRenderer();
+    if ( !rend )
+        return wxELLIPSIZE_NONE;
+
     GValue gvalue = { 0, };
     g_value_init( &gvalue, PANGO_TYPE_ELLIPSIZE_MODE );
-    g_object_get_property( G_OBJECT(m_renderer), "ellipsize", &gvalue );
+    g_object_get_property( G_OBJECT(rend), "ellipsize", &gvalue );
     wxEllipsizeMode
         mode = static_cast<wxEllipsizeMode>(g_value_get_enum( &gvalue ));
     g_value_unset( &gvalue );
 
     return mode;
+#else // GTK < 2.6
+    return wxELLIPSIZE_NONE;
+#endif // GTK 2.6/before
 }
 
 void
@@ -1916,7 +1952,12 @@ void wxDataViewTextRenderer::SetAlignment( int align )
 
 bool wxDataViewTextRenderer::GtkSetAttr(const wxDataViewItemAttr& attr)
 {
-    return GtkApplyAttr(GTK_CELL_RENDERER_TEXT(m_renderer), attr);
+    return GtkApplyAttr(GtkGetTextRenderer(), attr);
+}
+
+GtkCellRendererText *wxDataViewTextRenderer::GtkGetTextRenderer() const
+{
+    return GTK_CELL_RENDERER_TEXT(m_renderer);
 }
 
 // ---------------------------------------------------------
@@ -2130,29 +2171,41 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
         Init(mode, align);
 }
 
+GtkCellRendererText *wxDataViewCustomRenderer::GtkGetTextRenderer() const
+{
+    if ( !m_text_renderer )
+    {
+        // we create it on demand so need to do it even from a const function
+        const_cast<wxDataViewCustomRenderer *>(this)->
+        m_text_renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
+    }
+
+    return m_text_renderer;
+}
+
 void wxDataViewCustomRenderer::RenderText( const wxString &text,
                                            int xoffset,
                                            wxRect cell,
                                            wxDC *WXUNUSED(dc),
                                            int WXUNUSED(state) )
 {
-    if (!m_text_renderer)
-        m_text_renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
+
+    GtkCellRendererText * const textRenderer = GtkGetTextRenderer();
 
     GValue gvalue = { 0, };
     g_value_init( &gvalue, G_TYPE_STRING );
     g_value_set_string( &gvalue, wxGTK_CONV_FONT( text, GetOwner()->GetOwner()->GetFont() ) );
-    g_object_set_property( G_OBJECT(m_text_renderer), "text", &gvalue );
+    g_object_set_property( G_OBJECT(textRenderer), "text", &gvalue );
     g_value_unset( &gvalue );
 
-    GtkApplyAttr(m_text_renderer, GetAttr());
+    GtkApplyAttr(textRenderer, GetAttr());
 
     GdkRectangle cell_area;
     wxRectToGDKRect(cell, cell_area);
     cell_area.x += xoffset;
     cell_area.width -= xoffset;
 
-    gtk_cell_renderer_render( GTK_CELL_RENDERER(m_text_renderer),
+    gtk_cell_renderer_render( GTK_CELL_RENDERER(textRenderer),
         m_renderParams.window,
         m_renderParams.widget,
         m_renderParams.background_area,
@@ -2354,7 +2407,9 @@ bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value )
     {
         GValue gvalue = { 0, };
         g_value_init( &gvalue, G_TYPE_STRING );
-        g_value_set_string( &gvalue, wxGTK_CONV_FONT( value.GetString(), GetOwner()->GetOwner()->GetFont() ) );
+        g_value_set_string(&gvalue,
+                           wxGTK_CONV_FONT(value.GetString(),
+                                           GetOwner()->GetOwner()->GetFont()));
         g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
         g_value_unset( &gvalue );
     }
@@ -2373,8 +2428,8 @@ bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const
         GValue gvalue = { 0, };
         g_value_init( &gvalue, G_TYPE_STRING );
         g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
-        wxString temp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ),
-                const_cast<wxDataViewChoiceRenderer*>(this)->GetOwner()->GetOwner()->GetFont() );
+        wxString temp = wxGTK_CONV_BACK_FONT(g_value_get_string(&gvalue),
+                                             GetOwner()->GetOwner()->GetFont());
         g_value_unset( &gvalue );
         value = temp;
 
@@ -2409,6 +2464,48 @@ void wxDataViewChoiceRenderer::SetAlignment( int align )
     g_value_unset( &gvalue );
 }
 
+// ----------------------------------------------------------------------------
+// wxDataViewChoiceByIndexRenderer
+// ----------------------------------------------------------------------------
+
+wxDataViewChoiceByIndexRenderer::wxDataViewChoiceByIndexRenderer( const wxArrayString &choices,
+                              wxDataViewCellMode mode, int alignment ) :
+      wxDataViewChoiceRenderer( choices, mode, alignment )
+{
+}
+                            
+void wxDataViewChoiceByIndexRenderer::GtkOnTextEdited(const gchar *itempath, const wxString& str)
+{
+    wxVariant value( (long) GetChoices().Index( str ) );
+
+    if (!Validate( value ))
+        return;
+
+    GtkTreePath *path = gtk_tree_path_new_from_string( itempath );
+    GtkTreeIter iter;
+    GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, path );
+    wxDataViewItem item( (void*) iter.user_data );;
+    gtk_tree_path_free( path );
+
+    GtkOnCellChanged(value, item, GetOwner()->GetModelColumn());
+}
+
+bool wxDataViewChoiceByIndexRenderer::SetValue( const wxVariant &value )
+{
+    wxVariant string_value = GetChoice( value.GetLong() );
+    return wxDataViewChoiceRenderer::SetValue( string_value );
+}
+    
+bool wxDataViewChoiceByIndexRenderer::GetValue( wxVariant &value ) const
+{
+    wxVariant string_value;
+    if (!wxDataViewChoiceRenderer::GetValue( string_value ))
+         return false;
+            
+    value = (long) GetChoices().Index( string_value.GetString() );
+    return true;
+}
+
 // ---------------------------------------------------------
 // wxDataViewDateRenderer
 // ---------------------------------------------------------
@@ -2745,7 +2842,7 @@ void wxDataViewColumn::OnInternalIdle()
 {
     if (m_isConnected)
         return;
-
+               
     if (GTK_WIDGET_REALIZED(GetOwner()->m_treeview))
     {
         GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
@@ -2754,6 +2851,9 @@ void wxDataViewColumn::OnInternalIdle()
             g_signal_connect(column->button, "button_press_event",
                       G_CALLBACK (gtk_dataview_header_button_press_callback), this);
 
+            // otherwise the event will be blocked by GTK+
+            gtk_tree_view_column_set_clickable( column, TRUE ); 
+            
             m_isConnected = true;
         }
     }
@@ -3469,10 +3569,17 @@ gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path
 
 GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
 {
+    // When this is called from ItemDeleted(), the item is already
+    // deleted in the model.
+
     GtkTreePath *retval = gtk_tree_path_new ();
 
     if (m_wx_model->IsVirtualListModel())
     {
+        // iter is root, add nothing
+        if (!iter->user_data)
+           return retval;
+
         // user_data is just the index +1
         int i = ( (wxUIntPtr) iter->user_data ) -1;
         gtk_tree_path_append_index (retval, i);
@@ -3566,7 +3673,10 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *
             return TRUE;
         }
 
-        wxDataViewItem item( (void*) parent->user_data );
+
+        wxDataViewItem item;
+        if (parent)
+            item = wxDataViewItem( (void*) parent->user_data );
 
         if (!m_wx_model->IsContainer( item ))
             return FALSE;
@@ -3714,6 +3824,28 @@ gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *ch
     }
 }
 
+// item can be deleted already in the model
+int wxDataViewCtrlInternal::GetIndexOf( const wxDataViewItem &parent, const wxDataViewItem &item )
+{
+    if (m_wx_model->IsVirtualListModel())
+    {
+        return wxPtrToUInt(item.GetID()) - 1;
+    }
+    else
+    {
+        wxGtkTreeModelNode *parent_node = FindNode( parent );
+        wxGtkTreeModelChildren &children = parent_node->GetChildren();
+        size_t j;
+        for (j = 0; j < children.GetCount(); j++)
+        {
+            if (children[j] == item.GetID())
+               return j;
+        }
+    }
+    return -1;
+}
+
+
 static wxGtkTreeModelNode*
 wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
 {
@@ -3737,7 +3869,7 @@ wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *tr
         if( node && node->GetNodes().GetCount() != 0 )
         {
             int len = node->GetNodes().GetCount();
-            wxGtkTreeModelNodes nodes = node->GetNodes();
+            wxGtkTreeModelNodes &nodes = node->GetNodes();
             int j = 0;
             for( ; j < len; j ++)
             {