diff --git a/include/wx/artprov.h b/include/wx/artprov.h index 87b7fec01a..9b91493452 100644 --- a/include/wx/artprov.h +++ b/include/wx/artprov.h @@ -226,9 +226,14 @@ protected: return GetSizeHint(client, true); } - // Derived classes must override CreateBitmap or CreateIconBundle - // (or both) to create requested art resource. This method is called - // only once per instance's lifetime for each requested wxArtID. + // Derived classes must override at least one of the CreateXXX() functions + // below to create requested art resource. Overriding more than one of them + // is also possible but is usually not needed, as both GetBitmap() and + // GetBitmapBundle() will try using both CreateBitmap() and + // CreateBitmapBundle(). + // + // Note that these methods are called only once per instance's lifetime for + // each requested wxArtID as the return value is cached. virtual wxBitmap CreateBitmap(const wxArtID& WXUNUSED(id), const wxArtClient& WXUNUSED(client), const wxSize& WXUNUSED(size)) @@ -236,11 +241,12 @@ protected: return wxNullBitmap; } - // Default implementation creates a wxBitmapBundle which returns the - // specified art resource in whichever size it is being asked for. - virtual wxBitmapBundle CreateBitmapBundle(const wxArtID& id, - const wxArtClient& client, - const wxSize& size); + virtual wxBitmapBundle CreateBitmapBundle(const wxArtID& WXUNUSED(id), + const wxArtClient& WXUNUSED(client), + const wxSize& WXUNUSED(size)) + { + return wxBitmapBundle(); + } virtual wxIconBundle CreateIconBundle(const wxArtID& WXUNUSED(id), const wxArtClient& WXUNUSED(client)) diff --git a/src/common/artprov.cpp b/src/common/artprov.cpp index 982afd50b3..835f1fdbf1 100644 --- a/src/common/artprov.cpp +++ b/src/common/artprov.cpp @@ -325,9 +325,17 @@ void wxArtProvider::RescaleBitmap(wxBitmap& bmp, const wxSize& sizeNeeded) for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst(); node; node = node->GetNext()) { - bmp = node->GetData()->CreateBitmap(id, client, size); + wxArtProvider* const provider = node->GetData(); + bmp = provider->CreateBitmap(id, client, size); if ( bmp.IsOk() ) break; + + const wxBitmapBundle& bb = provider->CreateBitmapBundle(id, client, size); + if ( bb.IsOk() ) + { + bmp = bb.GetBitmap(size); + break; + } } wxSize sizeNeeded = size; @@ -385,9 +393,25 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id, for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst(); node; node = node->GetNext()) { - bitmapbundle = node->GetData()->CreateBitmapBundle(id, client, size); + wxArtProvider* const provider = node->GetData(); + bitmapbundle = provider->CreateBitmapBundle(id, client, size); if ( bitmapbundle.IsOk() ) break; + + // Try creating the bundle from individual bitmaps returned by the + // provider because they can be available in more than one size, + // i.e. it's better to return a custom bundle returning them in the + // size closest to the requested one rather than a simple bundle + // just containing the single bitmap in the specified size. + // + // Note that we do this here rather than outside of this loop + // because we consider that a simple bitmap defined in a higher + // priority provider should override a bitmap bundle defined in a + // lower priority one: even if this means that the bitmap will be + // scaled, at least we'll be using the expected bitmap rather than + // potentially using a bitmap of a different style. + if ( GetBitmap(id, client, size).IsOk() ) + bitmapbundle = wxBitmapBundle::FromImpl(new wxBitmapBundleImplArt(id, client, size)); } sm_cache->PutBitmapBundle(hashId, bitmapbundle); @@ -396,19 +420,6 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id, return bitmapbundle; } -wxBitmapBundle wxArtProvider::CreateBitmapBundle(const wxArtID& id, - const wxArtClient& client, - const wxSize& size) -{ - // Check that we have a valid art ID to ensure that wxBitmapBundleImplArt - // will be able to create valid bitmaps when it is used, because it is - // expected that a non-empty bundle always has at least one valid bitmap. - if ( !GetBitmap(id, client, size).IsOk() ) - return wxBitmapBundle(); - - return wxBitmapBundle::FromImpl(new wxBitmapBundleImplArt(id, client, size)); -} - /*static*/ wxIconBundle wxArtProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client) { diff --git a/tests/graphics/bmpbundle.cpp b/tests/graphics/bmpbundle.cpp index 9ea96f37c8..1362e2730b 100644 --- a/tests/graphics/bmpbundle.cpp +++ b/tests/graphics/bmpbundle.cpp @@ -14,6 +14,8 @@ #include "wx/bmpbndl.h" +#include "wx/artprov.h" + #include "asserthelper.h" // ---------------------------------------------------------------------------- @@ -144,3 +146,16 @@ TEST_CASE("BitmapBundle::FromSVGFile", "[bmpbundle][svg][file]") } #endif // wxHAS_SVG + +TEST_CASE("BitmapBundle::ArtProvider", "[bmpbundle][art]") +{ + // Check that creating a bogus bundle fails as expected. + wxBitmapBundle b = wxArtProvider::GetBitmapBundle("bloordyblop"); + CHECK( !b.IsOk() ); + + // And that creating a bundle using a standard icon works. + const wxSize size(16, 16); + b = wxArtProvider::GetBitmapBundle(wxART_INFORMATION, wxART_MENU, size); + CHECK( b.IsOk() ); + CHECK( b.GetDefaultSize() == size ); +}