Stop using macro-based wxList in wxArtProvider code

Use std::list<> instead.

Also use std::unique_ptr<> instead of managing memory manually. As this
makes wxArtProvidersList non-copyable, don't export it from the DLL any
longer, as DLL-exported classes apparently must have a copy ctor, or at
least MSVS (all versions up to 2022) try to generate it even if it's
explicitly deleted in the class declaration and fail, due to the base
class being non-copyable. And because there was never any reason to
export neither this class nor wxArtProviderCache from the DLL, stop
exporting the latter one too.

Note that this implies that the only way to delete a wxArtProvider
registered in the global provider list is by removing it from it,
instead of deleting it directly, which was apparently allowed before,
even though it shouldn't have ever been actually done -- but make this
even more clear in the documentation now.
This commit is contained in:
Vadim Zeitlin 2023-04-11 21:01:47 +02:00
parent b76ebc61d9
commit 4a294caacd
3 changed files with 39 additions and 32 deletions

View file

@ -17,8 +17,8 @@
#include "wx/iconbndl.h"
#include "wx/bmpbndl.h"
class WXDLLIMPEXP_FWD_CORE wxArtProvidersList;
class WXDLLIMPEXP_FWD_CORE wxArtProviderCache;
class wxArtProvidersList;
class wxArtProviderCache;
class WXDLLIMPEXP_FWD_CORE wxWindow;
class wxArtProviderModule;

View file

@ -133,6 +133,10 @@ const char* wxART_WX_LOGO;
wxArtProvider::Push(new MyProvider);
@endcode
Note that, as usual in wxWidgets API, wxArtProvider takes ownership of the
pointer and will destroy it on program shutdown. In particular, you should
not delete this pointer in your own code.
If you need bitmap images (of the same artwork) that should be displayed at
different sizes you should probably consider overriding wxArtProvider::CreateIconBundle
and supplying icon bundles that contain different bitmap sizes.
@ -423,6 +427,8 @@ public:
Register new art provider and add it to the top of providers stack
(i.e. it will be queried as the first provider).
@param provider A valid pointer that becomes owned by wxArtProvider.
@see PushBack()
*/
static void Push(wxArtProvider* provider);
@ -432,6 +438,8 @@ public:
In other words, it will be queried as the last one, after all others,
including the default provider.
@param provider A valid pointer that becomes owned by wxArtProvider.
@see Push()
@since 2.9.0

View file

@ -27,13 +27,15 @@
#include "wx/window.h"
#endif
// ===========================================================================
// implementation
// ===========================================================================
#include <list>
#include <memory>
#include "wx/listimpl.cpp"
WX_DECLARE_LIST(wxArtProvider, wxArtProvidersList);
WX_DEFINE_LIST(wxArtProvidersList)
using wxArtProviderPtr = std::unique_ptr<wxArtProvider>;
class wxArtProvidersList : public std::list<wxArtProviderPtr>
{
public:
using std::list<wxArtProviderPtr>::list;
};
// ----------------------------------------------------------------------------
// Cache class - stores already requested bitmaps
@ -43,7 +45,7 @@ WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxBitmap, wxArtProviderBitmapsHash);
WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxBitmapBundle, wxArtProviderBitmapBundlesHash);
WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxIconBundle, wxArtProviderIconBundlesHash);
class WXDLLEXPORT wxArtProviderCache
class wxArtProviderCache
{
public:
bool GetBitmap(const wxString& full_id, wxBitmap* bmp);
@ -241,10 +243,7 @@ wxArtProviderCache *wxArtProvider::sm_cache = nullptr;
// wxArtProvider ctors/dtor
// ----------------------------------------------------------------------------
wxArtProvider::~wxArtProvider()
{
Remove(this);
}
wxArtProvider::~wxArtProvider() = default;
// ----------------------------------------------------------------------------
// wxArtProvider operations on provider stack
@ -264,13 +263,13 @@ wxArtProvider::~wxArtProvider()
/*static*/ void wxArtProvider::Push(wxArtProvider *provider)
{
CommonAddingProvider();
sm_providers->Insert(provider);
sm_providers->push_front(wxArtProviderPtr(provider));
}
/*static*/ void wxArtProvider::PushBack(wxArtProvider *provider)
{
CommonAddingProvider();
sm_providers->Append(provider);
sm_providers->push_back(wxArtProviderPtr(provider));
}
/*static*/ bool wxArtProvider::Pop()
@ -278,7 +277,7 @@ wxArtProvider::~wxArtProvider()
wxCHECK_MSG( sm_providers, false, wxT("no wxArtProvider exists") );
wxCHECK_MSG( !sm_providers->empty(), false, wxT("wxArtProviders stack is empty") );
delete sm_providers->GetFirst()->GetData();
sm_providers->pop_front();
sm_cache->Clear();
return true;
}
@ -287,7 +286,16 @@ wxArtProvider::~wxArtProvider()
{
wxCHECK_MSG( sm_providers, false, wxT("no wxArtProvider exists") );
if ( sm_providers->DeleteObject(provider) )
// Unfortunately remove() doesn't return the number of the removed elements
// until C++20, so check whether it did anything manually.
const auto oldSize = sm_providers->size();
sm_providers->remove_if([provider](const wxArtProviderPtr& p)
{
return p.get() == provider;
});
if ( sm_providers->size() != oldSize )
{
sm_cache->Clear();
return true;
@ -308,9 +316,6 @@ wxArtProvider::~wxArtProvider()
{
if ( sm_providers )
{
while ( !sm_providers->empty() )
delete *sm_providers->begin();
wxDELETE(sm_providers);
wxDELETE(sm_cache);
}
@ -416,10 +421,8 @@ wxArtProvider::RescaleOrResizeIfNeeded(wxBitmap& bmp, const wxSize& sizeNeeded)
wxBitmap bmp;
if ( !sm_cache->GetBitmap(hashId, &bmp) )
{
for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
node; node = node->GetNext())
for (const auto& provider : *sm_providers)
{
wxArtProvider* const provider = node->GetData();
bmp = provider->CreateBitmap(id, client, size);
if ( bmp.IsOk() )
break;
@ -481,10 +484,8 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id,
if ( !sm_cache->GetBitmapBundle(hashId, &bitmapbundle) )
{
for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
node; node = node->GetNext())
for (const auto& provider : *sm_providers)
{
wxArtProvider* const provider = node->GetData();
bitmapbundle = provider->CreateBitmapBundle(id, client, size);
if ( bitmapbundle.IsOk() )
break;
@ -546,10 +547,9 @@ wxIconBundle wxArtProvider::DoGetIconBundle(const wxArtID& id, const wxArtClient
wxIconBundle iconbundle;
if ( !sm_cache->GetIconBundle(hashId, &iconbundle) )
{
for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
node; node = node->GetNext())
for (const auto& provider : *sm_providers)
{
iconbundle = node->GetData()->CreateIconBundle(id, client);
iconbundle = provider->CreateIconBundle(id, client);
if ( iconbundle.IsOk() )
break;
}
@ -607,9 +607,8 @@ wxArtID wxArtProvider::GetMessageBoxIconId(int flags)
/*static*/ wxSize wxArtProvider::GetDIPSizeHint(const wxArtClient& client)
{
wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
if (node)
return node->GetData()->DoGetSizeHint(client);
if ( !sm_providers->empty() )
return sm_providers->front()->DoGetSizeHint(client);
return GetNativeDIPSizeHint(client);
}