Add support for HiDPI bitmaps to wxDataViewBitmapRenderer with GTK3

This commit is contained in:
Paul Cornett
2020-09-16 11:33:13 -07:00
parent 85d63c3150
commit b376d1402b

View File

@@ -2464,28 +2464,126 @@ GtkCellRendererText *wxDataViewTextRenderer::GtkGetTextRenderer() const
// wxDataViewBitmapRenderer // wxDataViewBitmapRenderer
// --------------------------------------------------------- // ---------------------------------------------------------
namespace #ifdef __WXGTK3__
{ // Derive a type from GtkCellRendererPixbuf to allow drawing HiDPI bitmaps
// set "pixbuf" property on the given renderer extern "C" {
void SetPixbufProp(GtkCellRenderer *renderer, GdkPixbuf *pixbuf) static void wxCellRendererPixbufClassInit(void* g_class, void* class_data);
{
GValue gvalue = G_VALUE_INIT;
g_value_init( &gvalue, G_TYPE_OBJECT );
g_value_set_object( &gvalue, pixbuf );
g_object_set_property( G_OBJECT(renderer), "pixbuf", &gvalue );
g_value_unset( &gvalue );
} }
#define WX_CELL_RENDERER_PIXBUF(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, wxCellRendererPixbuf::Type(), wxCellRendererPixbuf)
namespace
{
class wxCellRendererPixbuf: GtkCellRendererPixbuf
{
public:
static GType Type();
static GtkCellRenderer* New();
void Set(const wxBitmap& bitmap);
wxBitmap* m_bitmap;
wxDECLARE_NO_COPY_CLASS(wxCellRendererPixbuf);
wxCellRendererPixbuf() wxMEMBER_DELETE;
~wxCellRendererPixbuf() wxMEMBER_DELETE;
};
GtkCellRendererClass* wxCellRendererPixbufParentClass;
GType wxCellRendererPixbuf::Type()
{
static GType type;
if (type == 0)
{
type = g_type_register_static_simple(
GTK_TYPE_CELL_RENDERER_PIXBUF,
"wxCellRendererPixbuf",
sizeof(GtkCellRendererPixbufClass),
wxCellRendererPixbufClassInit,
sizeof(wxCellRendererPixbuf),
NULL, GTypeFlags(0));
}
return type;
}
GtkCellRenderer* wxCellRendererPixbuf::New()
{
wxCellRendererPixbuf* crp = WX_CELL_RENDERER_PIXBUF(g_object_new(Type(), NULL));
crp->m_bitmap = new wxBitmap;
return GTK_CELL_RENDERER(crp);
}
void wxCellRendererPixbuf::Set(const wxBitmap& bitmap)
{
*m_bitmap = bitmap;
GdkPixbuf* pixbuf = NULL;
GdkPixbuf* pixbufNew = NULL;
if (bitmap.IsOk())
{
if (bitmap.GetScaleFactor() <= 1)
{
pixbuf = bitmap.GetPixbuf();
m_bitmap->UnRef();
}
else
{
pixbufNew =
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8,
int(bitmap.GetScaledWidth()), int(bitmap.GetScaledHeight()));
}
}
g_object_set(G_OBJECT(this), "pixbuf", pixbuf, NULL);
if (pixbufNew)
g_object_unref(pixbufNew);
}
} // anonymous namespace } // anonymous namespace
extern "C" {
static void
wxCellRendererPixbufRender(GtkCellRenderer* cell, cairo_t* cr, GtkWidget* widget,
const GdkRectangle* background_area, const GdkRectangle* cell_area, GtkCellRendererState flags)
{
const wxBitmap& bitmap = *WX_CELL_RENDERER_PIXBUF(cell)->m_bitmap;
if (!bitmap.IsOk())
wxCellRendererPixbufParentClass->render(cell, cr, widget, background_area, cell_area, flags);
else
{
const int x = (cell_area->width - int(bitmap.GetScaledWidth() )) / 2;
const int y = (cell_area->height - int(bitmap.GetScaledHeight())) / 2;
bitmap.Draw(cr, cell_area->x + x, cell_area->y + y);
}
}
static void wxCellRendererPixbufFinalize(GObject* object)
{
wxCellRendererPixbuf* crp = WX_CELL_RENDERER_PIXBUF(object);
delete crp->m_bitmap;
crp->m_bitmap = NULL;
G_OBJECT_CLASS(wxCellRendererPixbufParentClass)->finalize(object);
}
static void wxCellRendererPixbufClassInit(void* g_class, void* /*class_data*/)
{
GTK_CELL_RENDERER_CLASS(g_class)->render = wxCellRendererPixbufRender;
G_OBJECT_CLASS(g_class)->finalize = wxCellRendererPixbufFinalize;
wxCellRendererPixbufParentClass = GTK_CELL_RENDERER_CLASS(g_type_class_peek_parent(g_class));
}
} // extern "C"
#endif // __WXGTK3__
wxIMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer); wxIMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer);
wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode, wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode,
int align ) : int align ) :
wxDataViewRenderer( varianttype, mode, align ) wxDataViewRenderer( varianttype, mode, align )
{ {
#ifdef __WXGTK3__
m_renderer = wxCellRendererPixbuf::New();
#else
m_renderer = gtk_cell_renderer_pixbuf_new(); m_renderer = gtk_cell_renderer_pixbuf_new();
#endif
SetMode(mode); SetMode(mode);
SetAlignment(align); SetAlignment(align);
@@ -2493,26 +2591,15 @@ wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype,
bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value ) bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value )
{ {
if (value.GetType() == wxT("wxBitmap")) wxBitmap bitmap;
{ if (value.GetType() == wxS("wxBitmap") || value.GetType() == wxS("wxIcon"))
wxBitmap bitmap;
bitmap << value; bitmap << value;
// GetPixbuf() may create a Pixbuf representation in the wxBitmap #ifdef __WXGTK3__
// object (and it will stay there and remain owned by wxBitmap) WX_CELL_RENDERER_PIXBUF(m_renderer)->Set(bitmap);
SetPixbufProp(m_renderer, bitmap.IsOk() ? bitmap.GetPixbuf() : NULL); #else
} g_object_set(G_OBJECT(m_renderer), "pixbuf", bitmap.IsOk() ? bitmap.GetPixbuf() : NULL, NULL);
else if (value.GetType() == wxT("wxIcon")) #endif
{
wxIcon icon;
icon << value;
SetPixbufProp(m_renderer, icon.IsOk() ? icon.GetPixbuf() : NULL);
}
else
{
SetPixbufProp(m_renderer, NULL);
}
return true; return true;
} }
@@ -3033,7 +3120,11 @@ wxDataViewIconTextRenderer::wxDataViewIconTextRenderer
) )
: wxDataViewTextRenderer(varianttype, mode, align) : wxDataViewTextRenderer(varianttype, mode, align)
{ {
#ifdef __WXGTK3__
m_rendererIcon = wxCellRendererPixbuf::New();
#else
m_rendererIcon = gtk_cell_renderer_pixbuf_new(); m_rendererIcon = gtk_cell_renderer_pixbuf_new();
#endif
} }
wxDataViewIconTextRenderer::~wxDataViewIconTextRenderer() wxDataViewIconTextRenderer::~wxDataViewIconTextRenderer()
@@ -3056,7 +3147,11 @@ bool wxDataViewIconTextRenderer::SetValue( const wxVariant &value )
SetTextValue(m_value.GetText()); SetTextValue(m_value.GetText());
const wxIcon& icon = m_value.GetIcon(); const wxIcon& icon = m_value.GetIcon();
SetPixbufProp(m_rendererIcon, icon.IsOk() ? icon.GetPixbuf() : NULL); #ifdef __WXGTK3__
WX_CELL_RENDERER_PIXBUF(m_rendererIcon)->Set(icon);
#else
g_object_set(G_OBJECT(m_rendererIcon), "pixbuf", icon.IsOk() ? icon.GetPixbuf() : NULL, NULL);
#endif
return true; return true;
} }