Merge branch 'gtk-image-bundle'
Use wxBitmapBundle in wxGtkImage and select the appropriately-sized bitmaps depending on DPI in wxGTK wxToolBar. See https://github.com/wxWidgets/wxWidgets/pull/2547
This commit is contained in:
@@ -5,6 +5,9 @@
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/bmpbndl.h"
|
||||
#include "wx/math.h"
|
||||
|
||||
// Class that can be used in place of GtkImage, to allow drawing of alternate
|
||||
// bitmaps, such as HiDPI or disabled.
|
||||
|
||||
@@ -14,18 +17,34 @@ public:
|
||||
struct BitmapProvider
|
||||
{
|
||||
virtual ~BitmapProvider() { }
|
||||
|
||||
virtual double GetScale() const = 0;
|
||||
virtual wxBitmap Get() const = 0;
|
||||
virtual void Set(const wxBitmap&) { }
|
||||
virtual void Set(const wxBitmapBundle&) { }
|
||||
|
||||
// Simple helpers used in implementation.
|
||||
bool IsScaled() const { return !wxIsSameDouble(GetScale(), 1); }
|
||||
wxBitmap GetAtScale(const wxBitmapBundle& b) const
|
||||
{
|
||||
return b.GetBitmap(b.GetDefaultSize()*GetScale());
|
||||
}
|
||||
};
|
||||
|
||||
static GType Type();
|
||||
static GtkWidget* New(BitmapProvider* provider);
|
||||
static GtkWidget* New(wxWindow* win = NULL);
|
||||
void Set(const wxBitmap& bitmap);
|
||||
|
||||
// Use bitmaps from the given bundle, the logical bitmap size is the
|
||||
// default size of the bundle.
|
||||
void Set(const wxBitmapBundle& bitmapBundle);
|
||||
|
||||
// This pointer is never null and is owned by this class.
|
||||
BitmapProvider* m_provider;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxGtkImage);
|
||||
|
||||
// This class is constructed by New() and destroyed by its GObject
|
||||
// finalizer, so neither its ctor nor dtor can ever be used.
|
||||
wxGtkImage() wxMEMBER_DELETE;
|
||||
~wxGtkImage() wxMEMBER_DELETE;
|
||||
};
|
||||
|
@@ -146,6 +146,9 @@ public:
|
||||
{ return m_kind == wxITEM_CHECK || m_kind == wxITEM_RADIO; }
|
||||
|
||||
// attributes
|
||||
wxBitmapBundle GetNormalBitmapBundle() const { return m_bmpNormal; }
|
||||
wxBitmapBundle GetDisabledBitmapBundle() const { return m_bmpDisabled; }
|
||||
|
||||
wxBitmap GetNormalBitmap(const wxSize& size = wxDefaultSize) const
|
||||
{ return m_bmpNormal.GetBitmap(size); }
|
||||
wxBitmap GetDisabledBitmap(const wxSize& size = wxDefaultSize) const
|
||||
|
@@ -112,6 +112,26 @@ public:
|
||||
bool IsToggled() const;
|
||||
bool CanBeToggled() const;
|
||||
|
||||
/**
|
||||
Return the bundle containing normal tool bitmaps.
|
||||
|
||||
This bundle may be invalid if the tool doesn't show a bitmap.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
wxBitmapBundle GetNormalBitmapBundle() const;
|
||||
|
||||
/**
|
||||
Return the bundle containing disabled tool bitmaps.
|
||||
|
||||
This bundle may be invalid if the tool doesn't show a bitmap or doesn't
|
||||
have a specific disabled bitmap creates one automatically from the
|
||||
normal bitmap.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
wxBitmapBundle GetDisabledBitmapBundle() const;
|
||||
|
||||
wxBitmap GetNormalBitmap() const;
|
||||
wxBitmap GetDisabledBitmap() const;
|
||||
|
||||
|
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include "wx/bitmap.h"
|
||||
#include "wx/window.h"
|
||||
|
||||
#include "wx/gtk/private/wrapgtk.h"
|
||||
@@ -15,40 +14,70 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
|
||||
// Default provider for HiDPI common case
|
||||
struct BitmapProviderDefault: wxGtkImage::BitmapProvider
|
||||
{
|
||||
#ifdef __WXGTK3__
|
||||
BitmapProviderDefault(wxWindow* win) : m_win(win) { }
|
||||
|
||||
virtual double GetScale() const wxOVERRIDE;
|
||||
virtual wxBitmap Get() const wxOVERRIDE;
|
||||
virtual void Set(const wxBitmap& bitmap) wxOVERRIDE;
|
||||
virtual void Set(const wxBitmapBundle& bitmap) wxOVERRIDE;
|
||||
|
||||
|
||||
// This pointer can be null if there is no associated window.
|
||||
wxWindow* const m_win;
|
||||
wxBitmap m_bitmap;
|
||||
wxBitmap m_bitmapDisabled;
|
||||
#else
|
||||
BitmapProviderDefault(wxWindow*) { }
|
||||
virtual wxBitmap Get() const wxOVERRIDE { return wxBitmap(); }
|
||||
#endif
|
||||
|
||||
// All the bitmaps we use.
|
||||
wxBitmapBundle m_bitmapBundle;
|
||||
|
||||
// This bitmap is created on demand from m_bitmapBundle when necessary (and
|
||||
// is mutable because this is done in const Get()).
|
||||
mutable wxBitmap m_bitmapDisabled;
|
||||
};
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
wxBitmap BitmapProviderDefault::Get() const
|
||||
double BitmapProviderDefault::GetScale() const
|
||||
{
|
||||
return (m_win == NULL || m_win->IsEnabled()) ? m_bitmap : m_bitmapDisabled;
|
||||
return m_win ? m_win->GetDPIScaleFactor() : 1.0;
|
||||
}
|
||||
|
||||
void BitmapProviderDefault::Set(const wxBitmap& bitmap)
|
||||
wxBitmap BitmapProviderDefault::Get() const
|
||||
{
|
||||
m_bitmap.UnRef();
|
||||
m_bitmapDisabled.UnRef();
|
||||
if (bitmap.IsOk() && bitmap.GetScaleFactor() > 1)
|
||||
if ( m_win && !m_win->IsEnabled() )
|
||||
{
|
||||
m_bitmap = bitmap;
|
||||
if (m_win)
|
||||
m_bitmapDisabled = bitmap.CreateDisabled();
|
||||
if ( !m_bitmapDisabled.IsOk() && m_bitmapBundle.IsOk() )
|
||||
m_bitmapDisabled = GetAtScale(m_bitmapBundle).CreateDisabled();
|
||||
|
||||
return m_bitmapDisabled;
|
||||
}
|
||||
|
||||
// We currently don't return the bitmap we use from here when scale is 1,
|
||||
// as then we can just let GtkImage draw the bitmap it has.
|
||||
return IsScaled() ? GetAtScale(m_bitmapBundle) : wxBitmap();
|
||||
}
|
||||
#endif // __WXGTK3__
|
||||
|
||||
void BitmapProviderDefault::Set(const wxBitmapBundle& bitmapBundle)
|
||||
{
|
||||
m_bitmapBundle = bitmapBundle;
|
||||
|
||||
// Ensure it's recreated if needed later.
|
||||
m_bitmapDisabled.UnRef();
|
||||
}
|
||||
|
||||
#else // !__WXGTK3__
|
||||
|
||||
// Trivial version for GTK < 3 which doesn't provide any high DPI support.
|
||||
struct BitmapProviderDefault: wxGtkImage::BitmapProvider
|
||||
{
|
||||
BitmapProviderDefault(wxWindow*) { }
|
||||
virtual double GetScale() const wxOVERRIDE { return 1.0; }
|
||||
virtual wxBitmap Get() const wxOVERRIDE { return wxBitmap(); }
|
||||
};
|
||||
|
||||
#endif // __WXGTK3__/!__WXGTK3__
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
@@ -85,27 +114,20 @@ GtkWidget* wxGtkImage::New(wxWindow* win)
|
||||
return New(new BitmapProviderDefault(win));
|
||||
}
|
||||
|
||||
void wxGtkImage::Set(const wxBitmap& bitmap)
|
||||
void wxGtkImage::Set(const wxBitmapBundle& bitmapBundle)
|
||||
{
|
||||
m_provider->Set(bitmap);
|
||||
m_provider->Set(bitmapBundle);
|
||||
|
||||
// Always set the default bitmap to use the correct size, even if we draw a
|
||||
// different bitmap below.
|
||||
wxBitmap bitmap = bitmapBundle.GetBitmap(wxDefaultSize);
|
||||
|
||||
GdkPixbuf* pixbuf = NULL;
|
||||
GdkPixbuf* pixbufNew = NULL;
|
||||
if (bitmap.IsOk())
|
||||
{
|
||||
if (bitmap.GetScaleFactor() <= 1)
|
||||
pixbuf = bitmap.GetPixbuf();
|
||||
else
|
||||
{
|
||||
// Placeholder pixbuf for correct size
|
||||
pixbufNew =
|
||||
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8,
|
||||
int(bitmap.GetScaledWidth()), int(bitmap.GetScaledHeight()));
|
||||
}
|
||||
pixbuf = bitmap.GetPixbuf();
|
||||
}
|
||||
gtk_image_set_from_pixbuf(GTK_IMAGE(this), pixbuf);
|
||||
if (pixbufNew)
|
||||
g_object_unref(pixbufNew);
|
||||
}
|
||||
|
||||
static GtkWidgetClass* wxGtkImageParentClass;
|
||||
@@ -119,9 +141,13 @@ static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event)
|
||||
#endif
|
||||
{
|
||||
wxGtkImage* image = WX_GTK_IMAGE(widget);
|
||||
|
||||
const wxBitmap bitmap(image->m_provider->Get());
|
||||
if (!bitmap.IsOk())
|
||||
{
|
||||
// Just let GtkImage draw the bitmap in standard DPI. Arguably, we
|
||||
// should still be drawing it ourselves even in this case just for
|
||||
// consistency, but for now keep the original behaviour.
|
||||
#ifdef __WXGTK3__
|
||||
return wxGtkImageParentClass->draw(widget, cr);
|
||||
#else
|
||||
@@ -129,13 +155,24 @@ static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event)
|
||||
#endif
|
||||
}
|
||||
|
||||
const double scaleFactor = image->m_provider->GetScale();
|
||||
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocation(widget, &alloc);
|
||||
int x = (alloc.width - int(bitmap.GetScaledWidth() )) / 2;
|
||||
int y = (alloc.height - int(bitmap.GetScaledHeight())) / 2;
|
||||
int x = (alloc.width - int(bitmap.GetWidth() /scaleFactor)) / 2;
|
||||
int y = (alloc.height - int(bitmap.GetHeight()/scaleFactor)) / 2;
|
||||
#ifdef __WXGTK3__
|
||||
gtk_render_background(gtk_widget_get_style_context(widget),
|
||||
cr, 0, 0, alloc.width, alloc.height);
|
||||
|
||||
if (!wxIsSameDouble(scaleFactor, 1))
|
||||
{
|
||||
cairo_translate(cr, x, y);
|
||||
const double scale = 1 / scaleFactor;
|
||||
cairo_scale(cr, scale, scale);
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
bitmap.Draw(cr, x, y);
|
||||
#else
|
||||
x += alloc.x;
|
||||
|
@@ -176,36 +176,41 @@ namespace
|
||||
struct BitmapProvider: wxGtkImage::BitmapProvider
|
||||
{
|
||||
BitmapProvider(wxToolBarTool* tool) : m_tool(tool) { }
|
||||
|
||||
virtual double GetScale() const wxOVERRIDE;
|
||||
virtual wxBitmap Get() const wxOVERRIDE;
|
||||
wxToolBarTool* const m_tool;
|
||||
};
|
||||
|
||||
double BitmapProvider::GetScale() const
|
||||
{
|
||||
return m_tool->GetToolBar()->GetDPIScaleFactor();
|
||||
}
|
||||
|
||||
wxBitmap BitmapProvider::Get() const
|
||||
{
|
||||
#ifdef __WXGTK3__
|
||||
wxBitmap bitmap(m_tool->GetNormalBitmap());
|
||||
if (m_tool->IsEnabled())
|
||||
if (!m_tool->IsEnabled())
|
||||
{
|
||||
if (bitmap.IsOk() && bitmap.GetScaleFactor() <= 1)
|
||||
bitmap.UnRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxBitmap disabled(m_tool->GetDisabledBitmap());
|
||||
wxBitmap disabled(GetAtScale(m_tool->GetDisabledBitmapBundle()));
|
||||
// if no disabled bitmap and normal bitmap is scaled
|
||||
if (!disabled.IsOk() && bitmap.IsOk() && bitmap.GetScaleFactor() > 1)
|
||||
if (!disabled.IsOk() && IsScaled())
|
||||
{
|
||||
// make scaled disabled bitmap from normal one
|
||||
disabled = bitmap.CreateDisabled();
|
||||
wxBitmap bitmap(GetAtScale(m_tool->GetNormalBitmapBundle()));
|
||||
if (bitmap.IsOk())
|
||||
disabled = bitmap.CreateDisabled();
|
||||
}
|
||||
bitmap = disabled;
|
||||
return disabled;
|
||||
}
|
||||
|
||||
if (IsScaled())
|
||||
return GetAtScale(m_tool->GetNormalBitmapBundle());
|
||||
#else
|
||||
wxBitmap bitmap;
|
||||
if (!m_tool->IsEnabled())
|
||||
bitmap = m_tool->GetDisabledBitmap();
|
||||
return m_tool->GetDisabledBitmap();
|
||||
#endif
|
||||
return bitmap;
|
||||
return wxBitmap();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
Reference in New Issue
Block a user