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
|
// 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
|
// Class that can be used in place of GtkImage, to allow drawing of alternate
|
||||||
// bitmaps, such as HiDPI or disabled.
|
// bitmaps, such as HiDPI or disabled.
|
||||||
|
|
||||||
@@ -14,18 +17,34 @@ public:
|
|||||||
struct BitmapProvider
|
struct BitmapProvider
|
||||||
{
|
{
|
||||||
virtual ~BitmapProvider() { }
|
virtual ~BitmapProvider() { }
|
||||||
|
|
||||||
|
virtual double GetScale() const = 0;
|
||||||
virtual wxBitmap Get() 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 GType Type();
|
||||||
static GtkWidget* New(BitmapProvider* provider);
|
static GtkWidget* New(BitmapProvider* provider);
|
||||||
static GtkWidget* New(wxWindow* win = NULL);
|
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;
|
BitmapProvider* m_provider;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxGtkImage);
|
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;
|
||||||
~wxGtkImage() wxMEMBER_DELETE;
|
~wxGtkImage() wxMEMBER_DELETE;
|
||||||
};
|
};
|
||||||
|
@@ -146,6 +146,9 @@ public:
|
|||||||
{ return m_kind == wxITEM_CHECK || m_kind == wxITEM_RADIO; }
|
{ return m_kind == wxITEM_CHECK || m_kind == wxITEM_RADIO; }
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
|
wxBitmapBundle GetNormalBitmapBundle() const { return m_bmpNormal; }
|
||||||
|
wxBitmapBundle GetDisabledBitmapBundle() const { return m_bmpDisabled; }
|
||||||
|
|
||||||
wxBitmap GetNormalBitmap(const wxSize& size = wxDefaultSize) const
|
wxBitmap GetNormalBitmap(const wxSize& size = wxDefaultSize) const
|
||||||
{ return m_bmpNormal.GetBitmap(size); }
|
{ return m_bmpNormal.GetBitmap(size); }
|
||||||
wxBitmap GetDisabledBitmap(const wxSize& size = wxDefaultSize) const
|
wxBitmap GetDisabledBitmap(const wxSize& size = wxDefaultSize) const
|
||||||
|
@@ -112,6 +112,26 @@ public:
|
|||||||
bool IsToggled() const;
|
bool IsToggled() const;
|
||||||
bool CanBeToggled() 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 GetNormalBitmap() const;
|
||||||
wxBitmap GetDisabledBitmap() const;
|
wxBitmap GetDisabledBitmap() const;
|
||||||
|
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "wx/wxprec.h"
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
#include "wx/bitmap.h"
|
|
||||||
#include "wx/window.h"
|
#include "wx/window.h"
|
||||||
|
|
||||||
#include "wx/gtk/private/wrapgtk.h"
|
#include "wx/gtk/private/wrapgtk.h"
|
||||||
@@ -15,40 +14,70 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef __WXGTK3__
|
||||||
|
|
||||||
// Default provider for HiDPI common case
|
// Default provider for HiDPI common case
|
||||||
struct BitmapProviderDefault: wxGtkImage::BitmapProvider
|
struct BitmapProviderDefault: wxGtkImage::BitmapProvider
|
||||||
{
|
{
|
||||||
#ifdef __WXGTK3__
|
|
||||||
BitmapProviderDefault(wxWindow* win) : m_win(win) { }
|
BitmapProviderDefault(wxWindow* win) : m_win(win) { }
|
||||||
|
|
||||||
|
virtual double GetScale() const wxOVERRIDE;
|
||||||
virtual wxBitmap Get() 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;
|
wxWindow* const m_win;
|
||||||
wxBitmap m_bitmap;
|
|
||||||
wxBitmap m_bitmapDisabled;
|
// All the bitmaps we use.
|
||||||
#else
|
wxBitmapBundle m_bitmapBundle;
|
||||||
BitmapProviderDefault(wxWindow*) { }
|
|
||||||
virtual wxBitmap Get() const wxOVERRIDE { return wxBitmap(); }
|
// This bitmap is created on demand from m_bitmapBundle when necessary (and
|
||||||
#endif
|
// is mutable because this is done in const Get()).
|
||||||
|
mutable wxBitmap m_bitmapDisabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __WXGTK3__
|
double BitmapProviderDefault::GetScale() const
|
||||||
wxBitmap BitmapProviderDefault::Get() 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();
|
if ( m_win && !m_win->IsEnabled() )
|
||||||
m_bitmapDisabled.UnRef();
|
|
||||||
if (bitmap.IsOk() && bitmap.GetScaleFactor() > 1)
|
|
||||||
{
|
{
|
||||||
m_bitmap = bitmap;
|
if ( !m_bitmapDisabled.IsOk() && m_bitmapBundle.IsOk() )
|
||||||
if (m_win)
|
m_bitmapDisabled = GetAtScale(m_bitmapBundle).CreateDisabled();
|
||||||
m_bitmapDisabled = bitmap.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
|
} // namespace
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -85,27 +114,20 @@ GtkWidget* wxGtkImage::New(wxWindow* win)
|
|||||||
return New(new BitmapProviderDefault(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* pixbuf = NULL;
|
||||||
GdkPixbuf* pixbufNew = NULL;
|
|
||||||
if (bitmap.IsOk())
|
if (bitmap.IsOk())
|
||||||
{
|
{
|
||||||
if (bitmap.GetScaleFactor() <= 1)
|
pixbuf = bitmap.GetPixbuf();
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gtk_image_set_from_pixbuf(GTK_IMAGE(this), pixbuf);
|
gtk_image_set_from_pixbuf(GTK_IMAGE(this), pixbuf);
|
||||||
if (pixbufNew)
|
|
||||||
g_object_unref(pixbufNew);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkWidgetClass* wxGtkImageParentClass;
|
static GtkWidgetClass* wxGtkImageParentClass;
|
||||||
@@ -119,9 +141,13 @@ static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
wxGtkImage* image = WX_GTK_IMAGE(widget);
|
wxGtkImage* image = WX_GTK_IMAGE(widget);
|
||||||
|
|
||||||
const wxBitmap bitmap(image->m_provider->Get());
|
const wxBitmap bitmap(image->m_provider->Get());
|
||||||
if (!bitmap.IsOk())
|
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__
|
#ifdef __WXGTK3__
|
||||||
return wxGtkImageParentClass->draw(widget, cr);
|
return wxGtkImageParentClass->draw(widget, cr);
|
||||||
#else
|
#else
|
||||||
@@ -129,13 +155,24 @@ static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const double scaleFactor = image->m_provider->GetScale();
|
||||||
|
|
||||||
GtkAllocation alloc;
|
GtkAllocation alloc;
|
||||||
gtk_widget_get_allocation(widget, &alloc);
|
gtk_widget_get_allocation(widget, &alloc);
|
||||||
int x = (alloc.width - int(bitmap.GetScaledWidth() )) / 2;
|
int x = (alloc.width - int(bitmap.GetWidth() /scaleFactor)) / 2;
|
||||||
int y = (alloc.height - int(bitmap.GetScaledHeight())) / 2;
|
int y = (alloc.height - int(bitmap.GetHeight()/scaleFactor)) / 2;
|
||||||
#ifdef __WXGTK3__
|
#ifdef __WXGTK3__
|
||||||
gtk_render_background(gtk_widget_get_style_context(widget),
|
gtk_render_background(gtk_widget_get_style_context(widget),
|
||||||
cr, 0, 0, alloc.width, alloc.height);
|
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);
|
bitmap.Draw(cr, x, y);
|
||||||
#else
|
#else
|
||||||
x += alloc.x;
|
x += alloc.x;
|
||||||
|
@@ -176,36 +176,41 @@ namespace
|
|||||||
struct BitmapProvider: wxGtkImage::BitmapProvider
|
struct BitmapProvider: wxGtkImage::BitmapProvider
|
||||||
{
|
{
|
||||||
BitmapProvider(wxToolBarTool* tool) : m_tool(tool) { }
|
BitmapProvider(wxToolBarTool* tool) : m_tool(tool) { }
|
||||||
|
|
||||||
|
virtual double GetScale() const wxOVERRIDE;
|
||||||
virtual wxBitmap Get() const wxOVERRIDE;
|
virtual wxBitmap Get() const wxOVERRIDE;
|
||||||
wxToolBarTool* const m_tool;
|
wxToolBarTool* const m_tool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
double BitmapProvider::GetScale() const
|
||||||
|
{
|
||||||
|
return m_tool->GetToolBar()->GetDPIScaleFactor();
|
||||||
|
}
|
||||||
|
|
||||||
wxBitmap BitmapProvider::Get() const
|
wxBitmap BitmapProvider::Get() const
|
||||||
{
|
{
|
||||||
#ifdef __WXGTK3__
|
#ifdef __WXGTK3__
|
||||||
wxBitmap bitmap(m_tool->GetNormalBitmap());
|
if (!m_tool->IsEnabled())
|
||||||
if (m_tool->IsEnabled())
|
|
||||||
{
|
{
|
||||||
if (bitmap.IsOk() && bitmap.GetScaleFactor() <= 1)
|
wxBitmap disabled(GetAtScale(m_tool->GetDisabledBitmapBundle()));
|
||||||
bitmap.UnRef();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxBitmap disabled(m_tool->GetDisabledBitmap());
|
|
||||||
// if no disabled bitmap and normal bitmap is scaled
|
// 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
|
// 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
|
#else
|
||||||
wxBitmap bitmap;
|
|
||||||
if (!m_tool->IsEnabled())
|
if (!m_tool->IsEnabled())
|
||||||
bitmap = m_tool->GetDisabledBitmap();
|
return m_tool->GetDisabledBitmap();
|
||||||
#endif
|
#endif
|
||||||
return bitmap;
|
return wxBitmap();
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user