X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/62265c2c67bd9ee1c78e57700277dc0baf2f14d6..5d7792236f7e4fcbb94cdc2a5213e0c5788e8c28:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 26a3f53f28..02423c65eb 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -33,6 +33,9 @@ #include "wx/gtk/dc.h" #include "wx/gtk/dcclient.h" +#include "wx/gtk/private/gdkconv.h" +using namespace wxGTKImpl; + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -108,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 ); @@ -539,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; @@ -1150,8 +1156,8 @@ static GtkCellEditable *gtk_wx_cell_renderer_start_editing( // rect.width -= renderer->xpad * 2; // rect.height -= renderer->ypad * 2; -// wxRect renderrect( rect.x, rect.y, rect.width, rect.height ); - wxRect renderrect( cell_area->x, cell_area->y, cell_area->width, cell_area->height ); +// wxRect renderrect(wxRectFromGDKRect(&rect)); + wxRect renderrect(wxRectFromGDKRect(cell_area)); GtkTreePath *treepath = gtk_tree_path_new_from_string( path ); GtkTreeIter iter; @@ -1222,54 +1228,36 @@ gtk_wx_cell_renderer_render (GtkCellRenderer *renderer, GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer; wxDataViewCustomRenderer *cell = wxrenderer->cell; - cell->window = window; - cell->widget = widget; - cell->background_area = (void*) background_area; - cell->cell_area = (void*) cell_area; - cell->expose_area = (void*) expose_area; - cell->flags = (int) flags; + cell->GTKStashRenderParams(window, widget, + background_area, expose_area, flags); - GdkRectangle rect; - gtk_wx_cell_renderer_get_size (renderer, widget, cell_area, - &rect.x, - &rect.y, - &rect.width, - &rect.height); + wxRect rect(wxRectFromGDKRect(cell_area)); + rect = rect.Deflate(renderer->xpad, renderer->ypad); - rect.x += cell_area->x; - rect.y += cell_area->y; - rect.width -= renderer->xpad * 2; - rect.height -= renderer->ypad * 2; + wxWindowDC* dc = (wxWindowDC*) cell->GetDC(); + wxWindowDCImpl *impl = (wxWindowDCImpl *) dc->GetImpl(); - GdkRectangle dummy; - if (gdk_rectangle_intersect (expose_area, &rect, &dummy)) + // Reinitialize wxWindowDC's GDK window if drawing occurs into a different + // window such as a DnD drop window. + if (window != impl->m_gdkwindow) { - wxRect renderrect( rect.x, rect.y, rect.width, rect.height ); - wxWindowDC* dc = (wxWindowDC*) cell->GetDC(); - wxWindowDCImpl *impl = (wxWindowDCImpl *) dc->GetImpl(); - - // Reinitialize wxWindowDC's GDK window if drawing occurs into a different - // window such as a DnD drop window. - if (window != impl->m_gdkwindow) - { - impl->Destroy(); - impl->m_gdkwindow = window; - impl->SetUpDC(); - } - - int state = 0; - if (flags & GTK_CELL_RENDERER_SELECTED) - state |= wxDATAVIEW_CELL_SELECTED; - if (flags & GTK_CELL_RENDERER_PRELIT) - state |= wxDATAVIEW_CELL_PRELIT; - if (flags & GTK_CELL_RENDERER_INSENSITIVE) - state |= wxDATAVIEW_CELL_INSENSITIVE; - if (flags & GTK_CELL_RENDERER_INSENSITIVE) - state |= wxDATAVIEW_CELL_INSENSITIVE; - if (flags & GTK_CELL_RENDERER_FOCUSED) - state |= wxDATAVIEW_CELL_FOCUSED; - cell->WXCallRender( renderrect, dc, state ); + impl->Destroy(); + impl->m_gdkwindow = window; + impl->SetUpDC(); } + + int state = 0; + if (flags & GTK_CELL_RENDERER_SELECTED) + state |= wxDATAVIEW_CELL_SELECTED; + if (flags & GTK_CELL_RENDERER_PRELIT) + state |= wxDATAVIEW_CELL_PRELIT; + if (flags & GTK_CELL_RENDERER_INSENSITIVE) + state |= wxDATAVIEW_CELL_INSENSITIVE; + if (flags & GTK_CELL_RENDERER_INSENSITIVE) + state |= wxDATAVIEW_CELL_INSENSITIVE; + if (flags & GTK_CELL_RENDERER_FOCUSED) + state |= wxDATAVIEW_CELL_FOCUSED; + cell->WXCallRender( rect, dc, state ); } static gboolean @@ -1297,7 +1285,7 @@ gtk_wx_cell_renderer_activate( rect.width -= renderer->xpad * 2; rect.height -= renderer->ypad * 2; - wxRect renderrect( rect.x, rect.y, rect.width, rect.height ); + wxRect renderrect(wxRectFromGDKRect(&rect)); wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel(); @@ -1409,12 +1397,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); @@ -1693,31 +1695,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(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(g_value_get_enum( &gvalue )); g_value_unset( &gvalue ); return mode; +#else // GTK < 2.6 + return wxELLIPSIZE_NONE; +#endif // GTK 2.6/before } void @@ -1763,6 +1781,102 @@ static void wxGtkTextRendererEditedCallback( GtkCellRendererText *WXUNUSED(rende } +namespace +{ + +// helper function used by wxDataViewTextRenderer and +// wxDataViewCustomRenderer::RenderText(): it applies the attributes to the +// given text renderer and returns true if anything was done +bool GtkApplyAttr(GtkCellRendererText *renderer, const wxDataViewItemAttr& attr) +{ + bool usingDefaultAttrs = true; + if (attr.HasColour()) + { + const GdkColor * const gcol = attr.GetColour().GetColor(); + + GValue gvalue = { 0, }; + g_value_init( &gvalue, GDK_TYPE_COLOR ); + g_value_set_boxed( &gvalue, gcol ); + g_object_set_property( G_OBJECT(renderer), "foreground_gdk", &gvalue ); + g_value_unset( &gvalue ); + + usingDefaultAttrs = false; + } + else + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "foreground-set", &gvalue ); + g_value_unset( &gvalue ); + } + + if (attr.GetItalic()) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, PANGO_TYPE_STYLE ); + g_value_set_enum( &gvalue, PANGO_STYLE_ITALIC ); + g_object_set_property( G_OBJECT(renderer), "style", &gvalue ); + g_value_unset( &gvalue ); + + usingDefaultAttrs = false; + } + else + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "style-set", &gvalue ); + g_value_unset( &gvalue ); + } + + + if (attr.GetBold()) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, PANGO_TYPE_WEIGHT ); + g_value_set_enum( &gvalue, PANGO_WEIGHT_BOLD ); + g_object_set_property( G_OBJECT(renderer), "weight", &gvalue ); + g_value_unset( &gvalue ); + + usingDefaultAttrs = false; + } + else + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "weight-set", &gvalue ); + g_value_unset( &gvalue ); + } + +#if 0 + if (attr.HasBackgroundColour()) + { + wxColour colour = attr.GetBackgroundColour(); + const GdkColor * const gcol = colour.GetColor(); + + GValue gvalue = { 0, }; + g_value_init( &gvalue, GDK_TYPE_COLOR ); + g_value_set_boxed( &gvalue, gcol ); + g_object_set_property( G_OBJECT(renderer), "cell-background_gdk", &gvalue ); + g_value_unset( &gvalue ); + } + else + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "cell-background-set", &gvalue ); + g_value_unset( &gvalue ); + } +#endif + + return !usingDefaultAttrs; +} + +} // anonymous namespace + IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewRenderer) wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxDataViewCellMode mode, @@ -1833,6 +1947,16 @@ void wxDataViewTextRenderer::SetAlignment( int align ) g_value_unset( &gvalue ); } +bool wxDataViewTextRenderer::GtkSetAttr(const wxDataViewItemAttr& attr) +{ + return GtkApplyAttr(GtkGetTextRenderer(), attr); +} + +GtkCellRendererText *wxDataViewTextRenderer::GtkGetTextRenderer() const +{ + return GTK_CELL_RENDERER_TEXT(m_renderer); +} + // --------------------------------------------------------- // wxDataViewBitmapRenderer // --------------------------------------------------------- @@ -2044,40 +2168,47 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, Init(mode, align); } -void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, - wxRect WXUNUSED(cell), wxDC *WXUNUSED(dc), int WXUNUSED(state) ) +GtkCellRendererText *wxDataViewCustomRenderer::GtkGetTextRenderer() const { -#if 0 - wxDataViewCtrl *view = GetOwner()->GetOwner(); - wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ? - wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) : - view->GetForegroundColour(); - dc->SetTextForeground(col); - dc->DrawText( text, cell.x + xoffset, cell.y + ((cell.height - dc->GetCharHeight()) / 2)); -#else - if (!m_text_renderer) - m_text_renderer = gtk_cell_renderer_text_new(); + if ( !m_text_renderer ) + { + // we create it on demand so need to do it even from a const function + const_cast(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) ) +{ + + 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 ); - ((GdkRectangle*) cell_area)->x += xoffset; - ((GdkRectangle*) cell_area)->width -= xoffset; + GtkApplyAttr(textRenderer, GetAttr()); - gtk_cell_renderer_render( m_text_renderer, - window, - widget, - (GdkRectangle*) background_area, - (GdkRectangle*) cell_area, - (GdkRectangle*) expose_area, - (GtkCellRendererState) flags ); + GdkRectangle cell_area; + wxRectToGDKRect(cell, cell_area); + cell_area.x += xoffset; + cell_area.width -= xoffset; - ((GdkRectangle*) cell_area)->x -= xoffset; - ((GdkRectangle*) cell_area)->width += xoffset; -#endif + gtk_cell_renderer_render( GTK_CELL_RENDERER(textRenderer), + m_renderParams.window, + m_renderParams.widget, + m_renderParams.background_area, + &cell_area, + m_renderParams.expose_area, + (GtkCellRendererState) m_renderParams.flags ); } bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode, int align) @@ -2587,100 +2718,21 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column), cell->SetValue( value ); - // deal with attributes - wxDataViewItemAttr attr; - if ( !wx_model->GetAttr( item, cell->GetOwner()->GetModelColumn(), attr ) - && cell->GtkIsUsingDefaultAttrs() ) - { - // no custom attributes specified and we're already using the default - // ones -- nothing to do + // deal with attributes: if the renderer doesn't support them at all, we + // don't even need to query the model for them + if ( !cell->GtkSupportsAttrs() ) return; - } - - bool usingDefaultAttrs = true; - if (attr.HasColour()) - { - const GdkColor * const gcol = attr.GetColour().GetColor(); - - GValue gvalue = { 0, }; - g_value_init( &gvalue, GDK_TYPE_COLOR ); - g_value_set_boxed( &gvalue, gcol ); - g_object_set_property( G_OBJECT(renderer), "foreground_gdk", &gvalue ); - g_value_unset( &gvalue ); - - usingDefaultAttrs = false; - } - else - { - GValue gvalue = { 0, }; - g_value_init( &gvalue, G_TYPE_BOOLEAN ); - g_value_set_boolean( &gvalue, FALSE ); - g_object_set_property( G_OBJECT(renderer), "foreground-set", &gvalue ); - g_value_unset( &gvalue ); - } - - if (attr.GetItalic()) - { - GValue gvalue = { 0, }; - g_value_init( &gvalue, PANGO_TYPE_STYLE ); - g_value_set_enum( &gvalue, PANGO_STYLE_ITALIC ); - g_object_set_property( G_OBJECT(renderer), "style", &gvalue ); - g_value_unset( &gvalue ); - - usingDefaultAttrs = false; - } - else - { - GValue gvalue = { 0, }; - g_value_init( &gvalue, G_TYPE_BOOLEAN ); - g_value_set_boolean( &gvalue, FALSE ); - g_object_set_property( G_OBJECT(renderer), "style-set", &gvalue ); - g_value_unset( &gvalue ); - } - - - if (attr.GetBold()) - { - GValue gvalue = { 0, }; - g_value_init( &gvalue, PANGO_TYPE_WEIGHT ); - g_value_set_enum( &gvalue, PANGO_WEIGHT_BOLD ); - g_object_set_property( G_OBJECT(renderer), "weight", &gvalue ); - g_value_unset( &gvalue ); - - usingDefaultAttrs = false; - } - else - { - GValue gvalue = { 0, }; - g_value_init( &gvalue, G_TYPE_BOOLEAN ); - g_value_set_boolean( &gvalue, FALSE ); - g_object_set_property( G_OBJECT(renderer), "weight-set", &gvalue ); - g_value_unset( &gvalue ); - } -#if 0 - if (attr.HasBackgroundColour()) + // it can support attributes so check if this item has any + wxDataViewItemAttr attr; + if ( wx_model->GetAttr( item, cell->GetOwner()->GetModelColumn(), attr ) + || !cell->GtkIsUsingDefaultAttrs() ) { - wxColour colour = attr.GetBackgroundColour(); - const GdkColor * const gcol = colour.GetColor(); - - GValue gvalue = { 0, }; - g_value_init( &gvalue, GDK_TYPE_COLOR ); - g_value_set_boxed( &gvalue, gcol ); - g_object_set_property( G_OBJECT(renderer), "cell-background_gdk", &gvalue ); - g_value_unset( &gvalue ); + bool usingDefaultAttrs = !cell->GtkSetAttr(attr); + cell->GtkSetUsingDefaultAttrs(usingDefaultAttrs); } - else - { - GValue gvalue = { 0, }; - g_value_init( &gvalue, G_TYPE_BOOLEAN ); - g_value_set_boolean( &gvalue, FALSE ); - g_object_set_property( G_OBJECT(renderer), "cell-background-set", &gvalue ); - g_value_unset( &gvalue ); - } -#endif - - cell->GtkSetUsingDefaultAttrs(usingDefaultAttrs); + // else: no custom attributes specified and we're already using the default + // ones -- nothing to do } } // extern "C" @@ -3467,6 +3519,9 @@ 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()) @@ -3712,6 +3767,21 @@ 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 ) +{ + 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 ) { @@ -3735,7 +3805,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 ++) {