diff --git a/include/wx/bmpbndl.h b/include/wx/bmpbndl.h index 312b978c5c..d379c1e770 100644 --- a/include/wx/bmpbndl.h +++ b/include/wx/bmpbndl.h @@ -108,6 +108,9 @@ public: // Check if bitmap bundle is non-empty. bool IsOk() const { return m_impl.get() != NULL; } + // Clear the bundle contents, IsOk() will return false after doing this. + void Clear() { m_impl.reset(NULL); } + // Get the size of the bitmap represented by this bundle when using the // default DPI, i.e. 100% scaling. Returns invalid size for empty bundle. wxSize GetDefaultSize() const; @@ -242,4 +245,19 @@ public: virtual wxBitmap GetBitmap(const wxSize& size) = 0; }; +// ---------------------------------------------------------------------------- +// Allow using wxBitmapBundle in wxVariant +// ---------------------------------------------------------------------------- + +#if wxUSE_VARIANT + +class WXDLLIMPEXP_FWD_BASE wxVariant; + +WXDLLIMPEXP_CORE +wxBitmapBundle& operator<<(wxBitmapBundle& value, const wxVariant& variant); +WXDLLIMPEXP_CORE +wxVariant& operator<<(wxVariant& variant, const wxBitmapBundle& value); + +#endif // wxUSE_VARIANT + #endif // _WX_BMPBNDL_H_ diff --git a/include/wx/dvrenderers.h b/include/wx/dvrenderers.h index 4de42f3b14..f1b3fc1c04 100644 --- a/include/wx/dvrenderers.h +++ b/include/wx/dvrenderers.h @@ -155,6 +155,15 @@ public: wxString GetVariantType() const { return m_variantType; } + // Check if the given variant type is compatible with the type expected by + // this renderer: by default, just compare it with GetVariantType(), but + // can be overridden to accept other types that can be converted to the + // type needed by the renderer. + virtual bool IsCompatibleVariantType(const wxString& variantType) const + { + return variantType == GetVariantType(); + } + // Prepare for rendering the value of the corresponding item in the given // column taken from the provided non-null model. // @@ -163,8 +172,9 @@ public: // it and should probably be removed in the future. // // Return true if this cell is non-empty or false otherwise (and also if - // the model returned a value of the wrong, i.e. different from our - // GetVariantType(), type, in which case a debug error is also logged). + // the model returned a value of the wrong type, i.e. such that our + // IsCompatibleVariantType() returned false for it, in which case a debug + // error is also logged). bool PrepareForItem(const wxDataViewModel *model, const wxDataViewItem& item, unsigned column); diff --git a/include/wx/generic/dvrenderers.h b/include/wx/generic/dvrenderers.h index 1f23fdee3a..17d963ecdb 100644 --- a/include/wx/generic/dvrenderers.h +++ b/include/wx/generic/dvrenderers.h @@ -96,7 +96,7 @@ private: class WXDLLIMPEXP_ADV wxDataViewBitmapRenderer: public wxDataViewRenderer { public: - static wxString GetDefaultType() { return wxS("wxBitmap"); } + static wxString GetDefaultType() { return wxS("wxBitmapBundle"); } wxDataViewBitmapRenderer( const wxString &varianttype = GetDefaultType(), wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, @@ -104,6 +104,10 @@ public: virtual bool SetValue( const wxVariant &value ) wxOVERRIDE; virtual bool GetValue( wxVariant &value ) const wxOVERRIDE; + + virtual + bool IsCompatibleVariantType(const wxString& variantType) const wxOVERRIDE; + #if wxUSE_ACCESSIBILITY virtual wxString GetAccessibleDescription() const wxOVERRIDE; #endif // wxUSE_ACCESSIBILITY @@ -112,8 +116,7 @@ public: virtual wxSize GetSize() const wxOVERRIDE; private: - wxIcon m_icon; - wxBitmap m_bitmap; + wxBitmapBundle m_bitmapBundle; protected: wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewBitmapRenderer); diff --git a/include/wx/gtk/dvrenderers.h b/include/wx/gtk/dvrenderers.h index e81a5b5a63..e8a65c37b1 100644 --- a/include/wx/gtk/dvrenderers.h +++ b/include/wx/gtk/dvrenderers.h @@ -81,7 +81,7 @@ protected: class WXDLLIMPEXP_ADV wxDataViewBitmapRenderer: public wxDataViewRenderer { public: - static wxString GetDefaultType() { return wxS("wxBitmap"); } + static wxString GetDefaultType() { return wxS("wxBitmapBundle"); } wxDataViewBitmapRenderer( const wxString &varianttype = GetDefaultType(), wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, @@ -90,6 +90,9 @@ public: bool SetValue( const wxVariant &value ) wxOVERRIDE; bool GetValue( wxVariant &value ) const wxOVERRIDE; + virtual + bool IsCompatibleVariantType(const wxString& variantType) const wxOVERRIDE; + protected: wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewBitmapRenderer); }; diff --git a/include/wx/osx/dvrenderers.h b/include/wx/osx/dvrenderers.h index a854a3f112..218ce08d8c 100644 --- a/include/wx/osx/dvrenderers.h +++ b/include/wx/osx/dvrenderers.h @@ -104,12 +104,15 @@ private: class WXDLLIMPEXP_ADV wxDataViewBitmapRenderer: public wxDataViewRenderer { public: - static wxString GetDefaultType() { return wxS("wxBitmap"); } + static wxString GetDefaultType() { return wxS("wxBitmapBundle"); } wxDataViewBitmapRenderer(const wxString& varianttype = GetDefaultType(), wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT); + virtual + bool IsCompatibleVariantType(const wxString& variantType) const wxOVERRIDE; + virtual bool MacRender() wxOVERRIDE; private: diff --git a/include/wx/qt/dvrenderers.h b/include/wx/qt/dvrenderers.h index 6ae3e527a6..dc57dc349c 100644 --- a/include/wx/qt/dvrenderers.h +++ b/include/wx/qt/dvrenderers.h @@ -34,7 +34,7 @@ public: class WXDLLIMPEXP_ADV wxDataViewBitmapRenderer: public wxDataViewRenderer { public: - static wxString GetDefaultType() { return wxS("wxBitmap"); } + static wxString GetDefaultType() { return wxS("wxBitmapBundle"); } wxDataViewBitmapRenderer( const wxString &varianttype = GetDefaultType(), wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, @@ -42,6 +42,8 @@ public: bool SetValue( const wxVariant &value ); bool GetValue( wxVariant &value ) const; + + bool IsCompatibleVariantType(const wxString& variantType) const; }; // --------------------------------------------------------- diff --git a/interface/wx/bmpbndl.h b/interface/wx/bmpbndl.h index e78c900f2e..901b56d20b 100644 --- a/interface/wx/bmpbndl.h +++ b/interface/wx/bmpbndl.h @@ -288,6 +288,18 @@ public: */ static wxBitmapBundle FromSVGResource(const wxString& name, const wxSize& sizeDef); + /** + Clear the existing bundle contents. + + After calling this function IsOk() returns @false. + + This is the same as assigning a default-constructed bitmap bundle to + this object but slightly more explicit. + + @since 3.1.7 + */ + void Clear(); + /** Check if bitmap bundle is non-empty. diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index 8d992a1d17..b7fc418d3b 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -1981,6 +1981,15 @@ class wxDataViewRenderer : public wxObject public: /** Constructor. + + The @a varianttype parameter is the main type of wxVariant objects + supported by this renderer, i.e. those that can be passed to its + SetValue(), e.g. "string" for wxDataViewTextRenderer. The value of this + parameter is returned by GetVariantType(). + + When deriving a custom renderer, either an existing variant type or a + new custom one can be used, see wxVariant documentation for more + details. */ wxDataViewRenderer(const wxString& varianttype, wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, @@ -2061,9 +2070,27 @@ public: /** Returns a string with the type of the wxVariant supported by this renderer. + + Note that a renderer may support more than one variant type, in which + case it needs to override IsCompatibleVariantType() to return @a true + for all types it supports. But by default only the type returned by + this function is supported. */ wxString GetVariantType() const; + /** + Check if the given variant type is compatible with the type expected by + this renderer. + + The base class implementation just compares @a variantType with the + value returned by GetVariantType(), but this function can be overridden + to accept other types that can be converted to the type needed by the + renderer. + + @since 3.1.7 + */ + virtual bool IsCompatibleVariantType(const wxString& variantType) const; + /** Sets the alignment of the renderer's content. The default value of @c wxDVR_DEFAULT_ALIGNMENT indicates that the content @@ -2717,7 +2744,12 @@ protected: /** @class wxDataViewBitmapRenderer - This class is used by wxDataViewCtrl to render bitmap controls. + This class is used by wxDataViewCtrl to render bitmaps. + + This renderer accepts wxVariant objects storing wxBitmap, wxIcon or + wxBitmapBundle inside them, with the latter being preferred as it allows + the renderer to automatically select the bitmap of the best matching size + depending on the current DPI. @library{wxcore} @category{dvc} @@ -2728,6 +2760,11 @@ public: /** Returns the wxVariant type used with this renderer. + Note that the value returned by this function has changed from + "wxBitmap" to "wxBitmapBundle" in wxWidgets 3.1.7, however the exact + value shouldn't matter, as it is only supposed to be used as the value + for the first constructor argument. + @since 3.1.0 */ static wxString GetDefaultType(); diff --git a/src/common/bmpbndl.cpp b/src/common/bmpbndl.cpp index 03ce1dd5b9..7b9d532b74 100644 --- a/src/common/bmpbndl.cpp +++ b/src/common/bmpbndl.cpp @@ -36,6 +36,71 @@ #include "wx/osx/private.h" #endif +#if wxUSE_VARIANT + +#include "wx/variant.h" + +// We can't use the macros from wx/variant.h because they only work for +// wxObject-derived classes, so define our own wxVariantData. + +class wxBitmapBundleVariantData: public wxVariantData +{ +public: + explicit wxBitmapBundleVariantData(const wxBitmapBundle& value) + : m_value(value) + { + } + + virtual bool Eq(wxVariantData& data) const wxOVERRIDE + { + // We're only called with the objects of the same type, so the cast is + // safe. + return static_cast(data).m_value.IsSameAs(m_value); + } + + virtual wxString GetType() const wxOVERRIDE + { + return wxASCII_STR("wxBitmapBundle"); + } + + virtual wxClassInfo* GetValueClassInfo() wxOVERRIDE + { + return NULL; + } + + virtual wxVariantData* Clone() const wxOVERRIDE + { + return new wxBitmapBundleVariantData(m_value); + } + + wxBitmapBundle m_value; + + DECLARE_WXANY_CONVERSION() +}; + +IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxBitmapBundle, wxBitmapBundleVariantData) + +WXDLLIMPEXP_CORE +wxBitmapBundle& operator<<(wxBitmapBundle& value, const wxVariant& variant) +{ + wxASSERT( variant.GetType() == wxASCII_STR("wxBitmapBundle") ); + + wxBitmapBundleVariantData* const + data = static_cast(variant.GetData()); + + value = data->m_value; + return value; +} + +WXDLLIMPEXP_CORE +wxVariant& operator<<(wxVariant& variant, const wxBitmapBundle& value) +{ + variant.SetData(new wxBitmapBundleVariantData(value)); + return variant; +} + +#endif // wxUSE_VARIANT + // ---------------------------------------------------------------------------- // private helpers // ---------------------------------------------------------------------------- diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index db60a89eda..10ce375710 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -861,7 +861,7 @@ wxDataViewRendererBase::CheckedGetValue(const wxDataViewModel* model, // We always allow the cell to be null, regardless of the renderer type. if ( !value.IsNull() ) { - if ( value.GetType() != GetVariantType() ) + if ( !IsCompatibleVariantType(value.GetType()) ) { // If you're seeing this message, this indicates that either your // renderer is using the wrong type, or your model returns values diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index b2be0be0d0..111d77dd8b 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -1317,18 +1317,25 @@ wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value ) { - if (value.GetType() == wxT("wxBitmap")) + if (value.GetType() == wxT("wxBitmapBundle")) { - m_bitmap << value; + m_bitmapBundle << value; + } + else if (value.GetType() == wxT("wxBitmap")) + { + wxBitmap bitmap; + bitmap << value; + m_bitmapBundle = wxBitmapBundle(bitmap); } else if (value.GetType() == wxT("wxIcon")) { - m_icon << value; + wxIcon icon; + icon << value; + m_bitmapBundle = wxBitmapBundle(icon); } else { - m_icon = wxNullIcon; - m_bitmap = wxNullBitmap; + m_bitmapBundle.Clear(); } return true; @@ -1339,6 +1346,15 @@ bool wxDataViewBitmapRenderer::GetValue( wxVariant& WXUNUSED(value) ) const return false; } +bool +wxDataViewBitmapRenderer::IsCompatibleVariantType(const wxString& variantType) const +{ + // We can accept values of any types checked by SetValue(). + return variantType == wxS("wxBitmapBundle") + || variantType == wxS("wxBitmap") + || variantType == wxS("wxIcon"); +} + #if wxUSE_ACCESSIBILITY wxString wxDataViewBitmapRenderer::GetAccessibleDescription() const { @@ -1348,20 +1364,20 @@ wxString wxDataViewBitmapRenderer::GetAccessibleDescription() const bool wxDataViewBitmapRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) ) { - if (m_bitmap.IsOk()) - dc->DrawBitmap( m_bitmap, cell.x, cell.y, true /* use mask */ ); - else if (m_icon.IsOk()) - dc->DrawIcon( m_icon, cell.x, cell.y ); + if (m_bitmapBundle.IsOk()) + { + dc->DrawBitmap( m_bitmapBundle.GetBitmapFor(GetView()), + cell.x, cell.y, + true /* use mask */ ); + } return true; } wxSize wxDataViewBitmapRenderer::GetSize() const { - if (m_bitmap.IsOk()) - return wxSize( m_bitmap.GetWidth(), m_bitmap.GetHeight() ); - else if (m_icon.IsOk()) - return wxSize( m_icon.GetWidth(), m_icon.GetHeight() ); + if (m_bitmapBundle.IsOk()) + return m_bitmapBundle.GetPreferredBitmapSizeFor(GetView()); return GetView()->FromDIP(wxSize(wxDVC_DEFAULT_RENDERER_SIZE, wxDVC_DEFAULT_RENDERER_SIZE)); diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 115299de13..be1f0113fe 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -2569,22 +2569,32 @@ wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value ) { - wxBitmap bitmap; - if (value.GetType() == wxS("wxBitmap")) + wxBitmapBundle bitmapBundle; + if (value.GetType() == wxS("wxBitmapBundle")) { + bitmapBundle << value; + } + else if (value.GetType() == wxS("wxBitmap")) + { + wxBitmap bitmap; bitmap << value; + bitmapBundle = wxBitmapBundle(bitmap); } else if (value.GetType() == wxS("wxIcon")) { wxIcon icon; icon << value; - bitmap.CopyFromIcon(icon); + bitmapBundle = wxBitmapBundle(icon); } #ifdef __WXGTK3__ - WX_CELL_RENDERER_PIXBUF(m_renderer)->Set(bitmap); + WX_CELL_RENDERER_PIXBUF(m_renderer)->Set(bitmapBundle); #else - g_object_set(G_OBJECT(m_renderer), "pixbuf", bitmap.IsOk() ? bitmap.GetPixbuf() : NULL, NULL); + g_object_set(G_OBJECT(m_renderer), + "pixbuf", + bitmapBundle.IsOk() ? bitmapBundle.GetBitmap(wxDefaultSize).GetPixbuf() + : NULL, + NULL); #endif return true; @@ -2595,6 +2605,15 @@ bool wxDataViewBitmapRenderer::GetValue( wxVariant &WXUNUSED(value) ) const return false; } +bool +wxDataViewBitmapRenderer::IsCompatibleVariantType(const wxString& variantType) const +{ + // We can accept values of any types checked by SetValue(). + return variantType == wxS("wxBitmapBundle") + || variantType == wxS("wxBitmap") + || variantType == wxS("wxIcon"); +} + // --------------------------------------------------------- // wxDataViewToggleRenderer // --------------------------------------------------------- diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 095ff20a12..524c998d08 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -28,6 +28,9 @@ #include "wx/osx/private/available.h" #include "wx/osx/private/datatransfer.h" #include "wx/osx/cocoa/dataview.h" + +#include "wx/private/bmpbndl.h" + #include "wx/renderer.h" #include "wx/stopwatch.h" #include "wx/dcgraph.h" @@ -2983,6 +2986,13 @@ wxDataViewBitmapRenderer::wxDataViewBitmapRenderer(const wxString& varianttype, bool wxDataViewBitmapRenderer::MacRender() { if (GetValue().GetType() == wxS("wxBitmap")) + { + wxBitmapBundle bundle; + bundle << GetValue(); + if (bundle.IsOk()) + [GetNativeData()->GetItemCell() setObjectValue:wxOSXGetImageFromBundle(bundle)]; + } + else if (GetValue().GetType() == wxS("wxBitmap")) { wxBitmap bitmap; bitmap << GetValue(); @@ -2999,6 +3009,15 @@ bool wxDataViewBitmapRenderer::MacRender() return true; } +bool +wxDataViewBitmapRenderer::IsCompatibleVariantType(const wxString& variantType) const +{ + // We can accept values of any types checked by SetValue(). + return variantType == wxS("wxBitmapBundle") + || variantType == wxS("wxBitmap") + || variantType == wxS("wxIcon"); +} + wxIMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer); // ------------------------------------- diff --git a/src/qt/dvrenderers.cpp b/src/qt/dvrenderers.cpp index c552325f83..66f70541be 100644 --- a/src/qt/dvrenderers.cpp +++ b/src/qt/dvrenderers.cpp @@ -54,6 +54,13 @@ bool wxDataViewBitmapRenderer::GetValue( wxVariant &value ) const return false; } +bool +wxDataViewBitmapRenderer::IsCompatibleVariantType(const wxString& variantType) const +{ + return variantType == wxS("wxBitmap") + || variantType == wxS("wxIcon"); +} + //============================================================================== wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &variantType, wxDataViewCellMode mode,