1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/artprov.cpp
3 // Purpose: wxArtProvider class
4 // Author: Vaclav Slavik
8 // Copyright: (c) Vaclav Slavik
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ---------------------------------------------------------------------------
14 // ---------------------------------------------------------------------------
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
19 #if defined(__BORLANDC__)
23 #include "wx/artprov.h"
28 #include "wx/hashmap.h"
30 #include "wx/module.h"
33 // ===========================================================================
35 // ===========================================================================
37 #include "wx/listimpl.cpp"
38 WX_DECLARE_LIST(wxArtProvider
, wxArtProvidersList
);
39 WX_DEFINE_LIST(wxArtProvidersList
)
41 // ----------------------------------------------------------------------------
42 // Cache class - stores already requested bitmaps
43 // ----------------------------------------------------------------------------
45 WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxBitmap
, wxArtProviderBitmapsHash
);
46 WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxIconBundle
, wxArtProviderIconBundlesHash
);
48 class WXDLLEXPORT wxArtProviderCache
51 bool GetBitmap(const wxString
& full_id
, wxBitmap
* bmp
);
52 void PutBitmap(const wxString
& full_id
, const wxBitmap
& bmp
)
53 { m_bitmapsHash
[full_id
] = bmp
; }
55 bool GetIconBundle(const wxString
& full_id
, wxIconBundle
* bmp
);
56 void PutIconBundle(const wxString
& full_id
, const wxIconBundle
& iconbundle
)
57 { m_iconBundlesHash
[full_id
] = iconbundle
; }
61 static wxString
ConstructHashID(const wxArtID
& id
,
62 const wxArtClient
& client
,
65 static wxString
ConstructHashID(const wxArtID
& id
,
66 const wxArtClient
& client
);
69 wxArtProviderBitmapsHash m_bitmapsHash
; // cache of wxBitmaps
70 wxArtProviderIconBundlesHash m_iconBundlesHash
; // cache of wxIconBundles
73 bool wxArtProviderCache::GetBitmap(const wxString
& full_id
, wxBitmap
* bmp
)
75 wxArtProviderBitmapsHash::iterator entry
= m_bitmapsHash
.find(full_id
);
76 if ( entry
== m_bitmapsHash
.end() )
87 bool wxArtProviderCache::GetIconBundle(const wxString
& full_id
, wxIconBundle
* bmp
)
89 wxArtProviderIconBundlesHash::iterator entry
= m_iconBundlesHash
.find(full_id
);
90 if ( entry
== m_iconBundlesHash
.end() )
101 void wxArtProviderCache::Clear()
103 m_bitmapsHash
.clear();
104 m_iconBundlesHash
.clear();
107 /* static */ wxString
108 wxArtProviderCache::ConstructHashID(const wxArtID
& id
,
109 const wxArtClient
& client
)
111 return id
+ wxT('-') + client
;
115 /* static */ wxString
116 wxArtProviderCache::ConstructHashID(const wxArtID
& id
,
117 const wxArtClient
& client
,
120 return ConstructHashID(id
, client
) + wxT('-') +
121 wxString::Format(wxT("%d-%d"), size
.x
, size
.y
);
124 // ============================================================================
125 // wxArtProvider class
126 // ============================================================================
128 IMPLEMENT_ABSTRACT_CLASS(wxArtProvider
, wxObject
)
130 wxArtProvidersList
*wxArtProvider::sm_providers
= NULL
;
131 wxArtProviderCache
*wxArtProvider::sm_cache
= NULL
;
133 // ----------------------------------------------------------------------------
134 // wxArtProvider ctors/dtor
135 // ----------------------------------------------------------------------------
137 wxArtProvider::~wxArtProvider()
142 // ----------------------------------------------------------------------------
143 // wxArtProvider operations on provider stack
144 // ----------------------------------------------------------------------------
146 /*static*/ void wxArtProvider::CommonAddingProvider()
150 sm_providers
= new wxArtProvidersList
;
151 sm_cache
= new wxArtProviderCache
;
157 /*static*/ void wxArtProvider::Push(wxArtProvider
*provider
)
159 CommonAddingProvider();
160 sm_providers
->Insert(provider
);
163 /*static*/ void wxArtProvider::PushBack(wxArtProvider
*provider
)
165 CommonAddingProvider();
166 sm_providers
->Append(provider
);
169 /*static*/ bool wxArtProvider::Pop()
171 wxCHECK_MSG( sm_providers
, false, wxT("no wxArtProvider exists") );
172 wxCHECK_MSG( !sm_providers
->empty(), false, wxT("wxArtProviders stack is empty") );
174 delete sm_providers
->GetFirst()->GetData();
179 /*static*/ bool wxArtProvider::Remove(wxArtProvider
*provider
)
181 wxCHECK_MSG( sm_providers
, false, wxT("no wxArtProvider exists") );
183 if ( sm_providers
->DeleteObject(provider
) )
192 /*static*/ bool wxArtProvider::Delete(wxArtProvider
*provider
)
194 // provider will remove itself from the stack in its dtor
200 /*static*/ void wxArtProvider::CleanUpProviders()
204 while ( !sm_providers
->empty() )
205 delete *sm_providers
->begin();
215 // ----------------------------------------------------------------------------
216 // wxArtProvider: retrieving bitmaps/icons
217 // ----------------------------------------------------------------------------
219 /*static*/ wxBitmap
wxArtProvider::GetBitmap(const wxArtID
& id
,
220 const wxArtClient
& client
,
223 // safety-check against writing client,id,size instead of id,client,size:
224 wxASSERT_MSG( client
.Last() == wxT('C'), wxT("invalid 'client' parameter") );
226 wxCHECK_MSG( sm_providers
, wxNullBitmap
, wxT("no wxArtProvider exists") );
228 wxString hashId
= wxArtProviderCache::ConstructHashID(id
, client
, size
);
231 if ( !sm_cache
->GetBitmap(hashId
, &bmp
) )
233 for (wxArtProvidersList::compatibility_iterator node
= sm_providers
->GetFirst();
234 node
; node
= node
->GetNext())
236 bmp
= node
->GetData()->CreateBitmap(id
, client
, size
);
241 wxSize sizeNeeded
= size
;
244 // no bitmap created -- as a fallback, try if we can find desired
246 wxIconBundle iconBundle
= DoGetIconBundle(id
, client
);
247 if ( iconBundle
.IsOk() )
249 if ( sizeNeeded
== wxDefaultSize
)
250 sizeNeeded
= GetNativeSizeHint(client
);
252 wxIcon
icon(iconBundle
.GetIcon(sizeNeeded
));
255 // this icon may be not of the correct size, it will be
256 // rescaled below in such case
257 bmp
.CopyFromIcon(icon
);
262 // if we didn't get the correct size, resize the bitmap
263 #if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB)
264 if ( bmp
.IsOk() && sizeNeeded
!= wxDefaultSize
)
266 if ( bmp
.GetSize() != sizeNeeded
)
268 wxImage img
= bmp
.ConvertToImage();
269 img
.Rescale(sizeNeeded
.x
, sizeNeeded
.y
);
273 #endif // wxUSE_IMAGE
275 sm_cache
->PutBitmap(hashId
, bmp
);
282 wxIconBundle
wxArtProvider::GetIconBundle(const wxArtID
& id
, const wxArtClient
& client
)
284 wxIconBundle
iconbundle(DoGetIconBundle(id
, client
));
286 if ( iconbundle
.IsOk() )
292 // fall back to single-icon bundle
293 return wxIconBundle(GetIcon(id
, client
));
298 wxIconBundle
wxArtProvider::DoGetIconBundle(const wxArtID
& id
, const wxArtClient
& client
)
300 // safety-check against writing client,id,size instead of id,client,size:
301 wxASSERT_MSG( client
.Last() == wxT('C'), wxT("invalid 'client' parameter") );
303 wxCHECK_MSG( sm_providers
, wxNullIconBundle
, wxT("no wxArtProvider exists") );
305 wxString hashId
= wxArtProviderCache::ConstructHashID(id
, client
);
307 wxIconBundle iconbundle
;
308 if ( !sm_cache
->GetIconBundle(hashId
, &iconbundle
) )
310 for (wxArtProvidersList::compatibility_iterator node
= sm_providers
->GetFirst();
311 node
; node
= node
->GetNext())
313 iconbundle
= node
->GetData()->CreateIconBundle(id
, client
);
314 if ( iconbundle
.IsOk() )
318 sm_cache
->PutIconBundle(hashId
, iconbundle
);
324 /*static*/ wxIcon
wxArtProvider::GetIcon(const wxArtID
& id
,
325 const wxArtClient
& client
,
328 wxBitmap bmp
= GetBitmap(id
, client
, size
);
334 icon
.CopyFromBitmap(bmp
);
339 wxArtID
wxArtProvider::GetMessageBoxIconId(int flags
)
341 switch ( flags
& wxICON_MASK
)
344 wxFAIL_MSG(wxT("incorrect message box icon flags"));
350 case wxICON_INFORMATION
:
351 return wxART_INFORMATION
;
354 return wxART_WARNING
;
356 case wxICON_QUESTION
:
357 return wxART_QUESTION
;
361 /*static*/ wxSize
wxArtProvider::GetSizeHint(const wxArtClient
& client
,
362 bool platform_dependent
)
364 if (!platform_dependent
)
366 wxArtProvidersList::compatibility_iterator node
= sm_providers
->GetFirst();
368 return node
->GetData()->DoGetSizeHint(client
);
371 return GetNativeSizeHint(client
);
374 #ifndef wxHAS_NATIVE_ART_PROVIDER_IMPL
376 wxSize
wxArtProvider::GetNativeSizeHint(const wxArtClient
& WXUNUSED(client
))
378 // rather than returning some arbitrary value that doesn't make much
379 // sense (as 2.8 used to do), tell the caller that we don't have a clue:
380 return wxDefaultSize
;
384 void wxArtProvider::InitNativeProvider()
387 #endif // !wxHAS_NATIVE_ART_PROVIDER_IMPL
391 bool wxArtProvider::HasNativeProvider()
400 // ----------------------------------------------------------------------------
401 // deprecated wxArtProvider methods
402 // ----------------------------------------------------------------------------
404 #if WXWIN_COMPATIBILITY_2_6
406 /* static */ void wxArtProvider::PushProvider(wxArtProvider
*provider
)
411 /* static */ void wxArtProvider::InsertProvider(wxArtProvider
*provider
)
416 /* static */ bool wxArtProvider::PopProvider()
421 /* static */ bool wxArtProvider::RemoveProvider(wxArtProvider
*provider
)
423 // RemoveProvider() used to delete the provider being removed so this is
424 // not a typo, we must call Delete() and not Remove() here
425 return Delete(provider
);
428 #endif // WXWIN_COMPATIBILITY_2_6
430 #if WXWIN_COMPATIBILITY_2_8
431 /* static */ void wxArtProvider::Insert(wxArtProvider
*provider
)
435 #endif // WXWIN_COMPATIBILITY_2_8
437 // ============================================================================
438 // wxArtProviderModule
439 // ============================================================================
441 class wxArtProviderModule
: public wxModule
446 wxArtProvider::InitStdProvider();
447 wxArtProvider::InitNativeProvider();
452 wxArtProvider::CleanUpProviders();
455 DECLARE_DYNAMIC_CLASS(wxArtProviderModule
)
458 IMPLEMENT_DYNAMIC_CLASS(wxArtProviderModule
, wxModule
)