#include "wx/gtk/dc.h"
#include "wx/gtk/dcclient.h"
+#include "wx/gtk/private/gdkconv.h"
+using namespace wxGTKImpl;
+
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
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 );
// 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;
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
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();
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);
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 );
}
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 );
}
+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,
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
// ---------------------------------------------------------
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<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) )
+{
+
+ 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)
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())
- {
- 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
+ // it can support attributes so check if this item has any
+ wxDataViewItemAttr attr;
+ if ( wx_model->GetAttr( item, cell->GetOwner()->GetModelColumn(), attr )
+ || !cell->GtkIsUsingDefaultAttrs() )
{
- 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 );
+ bool usingDefaultAttrs = !cell->GtkSetAttr(attr);
+ cell->GtkSetUsingDefaultAttrs(usingDefaultAttrs);
}
-#endif
-
- cell->GtkSetUsingDefaultAttrs(usingDefaultAttrs);
+ // else: no custom attributes specified and we're already using the default
+ // ones -- nothing to do
}
} // extern "C"
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())
}
}
+// 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 )
{
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 ++)
{