]> git.saurik.com Git - wxWidgets.git/blame - src/common/artprov.cpp
Misc validity fixes to samples/xrc/rc/*.xrc.
[wxWidgets.git] / src / common / artprov.cpp
CommitLineData
2aca4a98 1/////////////////////////////////////////////////////////////////////////////
8ecff181 2// Name: src/common/artprov.cpp
2aca4a98
VS
3// Purpose: wxArtProvider class
4// Author: Vaclav Slavik
5// Modified by:
6// Created: 18/03/2002
2aca4a98 7// Copyright: (c) Vaclav Slavik
65571936 8// Licence: wxWindows licence
2aca4a98
VS
9/////////////////////////////////////////////////////////////////////////////
10
11// ---------------------------------------------------------------------------
12// headers
13// ---------------------------------------------------------------------------
14
2aca4a98
VS
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#if defined(__BORLANDC__)
19 #pragma hdrstop
20#endif
21
02761f6c
WS
22#include "wx/artprov.h"
23
2aca4a98 24#ifndef WX_PRECOMP
2aca4a98 25 #include "wx/list.h"
8ecff181 26 #include "wx/log.h"
df69528b 27 #include "wx/hashmap.h"
155ecd4c 28 #include "wx/image.h"
02761f6c 29 #include "wx/module.h"
2aca4a98
VS
30#endif
31
2aca4a98
VS
32// ===========================================================================
33// implementation
34// ===========================================================================
35
36#include "wx/listimpl.cpp"
37WX_DECLARE_LIST(wxArtProvider, wxArtProvidersList);
259c43f6 38WX_DEFINE_LIST(wxArtProvidersList)
2aca4a98
VS
39
40// ----------------------------------------------------------------------------
41// Cache class - stores already requested bitmaps
42// ----------------------------------------------------------------------------
43
3f5c62f9 44WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxBitmap, wxArtProviderBitmapsHash);
52734360 45WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxIconBundle, wxArtProviderIconBundlesHash);
2aca4a98
VS
46
47class WXDLLEXPORT wxArtProviderCache
48{
49public:
50 bool GetBitmap(const wxString& full_id, wxBitmap* bmp);
51 void PutBitmap(const wxString& full_id, const wxBitmap& bmp)
52 { m_bitmapsHash[full_id] = bmp; }
53
52734360
VZ
54 bool GetIconBundle(const wxString& full_id, wxIconBundle* bmp);
55 void PutIconBundle(const wxString& full_id, const wxIconBundle& iconbundle)
56 { m_iconBundlesHash[full_id] = iconbundle; }
57
2aca4a98 58 void Clear();
9e7ed2b0 59
57b0987b
VS
60 static wxString ConstructHashID(const wxArtID& id,
61 const wxArtClient& client,
2aca4a98
VS
62 const wxSize& size);
63
52734360
VZ
64 static wxString ConstructHashID(const wxArtID& id,
65 const wxArtClient& client);
66
2aca4a98 67private:
52734360
VZ
68 wxArtProviderBitmapsHash m_bitmapsHash; // cache of wxBitmaps
69 wxArtProviderIconBundlesHash m_iconBundlesHash; // cache of wxIconBundles
2aca4a98
VS
70};
71
72bool wxArtProviderCache::GetBitmap(const wxString& full_id, wxBitmap* bmp)
73{
74 wxArtProviderBitmapsHash::iterator entry = m_bitmapsHash.find(full_id);
75 if ( entry == m_bitmapsHash.end() )
76 {
4629016d 77 return false;
2aca4a98
VS
78 }
79 else
80 {
81 *bmp = entry->second;
4629016d 82 return true;
2aca4a98
VS
83 }
84}
85
52734360
VZ
86bool wxArtProviderCache::GetIconBundle(const wxString& full_id, wxIconBundle* bmp)
87{
88 wxArtProviderIconBundlesHash::iterator entry = m_iconBundlesHash.find(full_id);
89 if ( entry == m_iconBundlesHash.end() )
90 {
91 return false;
92 }
93 else
94 {
95 *bmp = entry->second;
96 return true;
97 }
98}
99
2aca4a98
VS
100void wxArtProviderCache::Clear()
101{
102 m_bitmapsHash.clear();
52734360 103 m_iconBundlesHash.clear();
2aca4a98
VS
104}
105
52734360
VZ
106/* static */ wxString
107wxArtProviderCache::ConstructHashID(const wxArtID& id,
108 const wxArtClient& client)
2aca4a98 109{
9a83f860 110 return id + wxT('-') + client;
2aca4a98
VS
111}
112
113
52734360
VZ
114/* static */ wxString
115wxArtProviderCache::ConstructHashID(const wxArtID& id,
116 const wxArtClient& client,
117 const wxSize& size)
118{
9a83f860
VZ
119 return ConstructHashID(id, client) + wxT('-') +
120 wxString::Format(wxT("%d-%d"), size.x, size.y);
52734360
VZ
121}
122
571d2e0f 123// ============================================================================
2aca4a98 124// wxArtProvider class
571d2e0f 125// ============================================================================
2aca4a98
VS
126
127IMPLEMENT_ABSTRACT_CLASS(wxArtProvider, wxObject)
128
129wxArtProvidersList *wxArtProvider::sm_providers = NULL;
130wxArtProviderCache *wxArtProvider::sm_cache = NULL;
131
571d2e0f
VZ
132// ----------------------------------------------------------------------------
133// wxArtProvider ctors/dtor
134// ----------------------------------------------------------------------------
135
136wxArtProvider::~wxArtProvider()
137{
138 Remove(this);
139}
140
141// ----------------------------------------------------------------------------
142// wxArtProvider operations on provider stack
143// ----------------------------------------------------------------------------
144
dd7d379e 145/*static*/ void wxArtProvider::CommonAddingProvider()
2aca4a98
VS
146{
147 if ( !sm_providers )
148 {
149 sm_providers = new wxArtProvidersList;
2aca4a98
VS
150 sm_cache = new wxArtProviderCache;
151 }
152
c3357a03 153 sm_cache->Clear();
2aca4a98
VS
154}
155
571d2e0f 156/*static*/ void wxArtProvider::Push(wxArtProvider *provider)
dd7d379e
VS
157{
158 CommonAddingProvider();
159 sm_providers->Insert(provider);
160}
161
14440cc6 162/*static*/ void wxArtProvider::PushBack(wxArtProvider *provider)
dd7d379e
VS
163{
164 CommonAddingProvider();
165 sm_providers->Append(provider);
166}
167
571d2e0f 168/*static*/ bool wxArtProvider::Pop()
2aca4a98 169{
9a83f860
VZ
170 wxCHECK_MSG( sm_providers, false, wxT("no wxArtProvider exists") );
171 wxCHECK_MSG( !sm_providers->empty(), false, wxT("wxArtProviders stack is empty") );
2aca4a98 172
222ed1d6 173 delete sm_providers->GetFirst()->GetData();
2aca4a98 174 sm_cache->Clear();
4629016d 175 return true;
2aca4a98
VS
176}
177
571d2e0f 178/*static*/ bool wxArtProvider::Remove(wxArtProvider *provider)
2aca4a98 179{
9a83f860 180 wxCHECK_MSG( sm_providers, false, wxT("no wxArtProvider exists") );
2aca4a98
VS
181
182 if ( sm_providers->DeleteObject(provider) )
183 {
184 sm_cache->Clear();
4629016d 185 return true;
2aca4a98 186 }
9e7ed2b0 187
4629016d 188 return false;
2aca4a98
VS
189}
190
571d2e0f
VZ
191/*static*/ bool wxArtProvider::Delete(wxArtProvider *provider)
192{
193 // provider will remove itself from the stack in its dtor
194 delete provider;
195
196 return true;
197}
198
2aca4a98
VS
199/*static*/ void wxArtProvider::CleanUpProviders()
200{
571d2e0f
VZ
201 if ( sm_providers )
202 {
203 while ( !sm_providers->empty() )
204 delete *sm_providers->begin();
205
5276b0a5
VZ
206 wxDELETE(sm_providers);
207 wxDELETE(sm_cache);
571d2e0f 208 }
2aca4a98
VS
209}
210
571d2e0f
VZ
211// ----------------------------------------------------------------------------
212// wxArtProvider: retrieving bitmaps/icons
213// ----------------------------------------------------------------------------
214
57b0987b
VS
215/*static*/ wxBitmap wxArtProvider::GetBitmap(const wxArtID& id,
216 const wxArtClient& client,
e53a95bc 217 const wxSize& size)
2aca4a98 218{
57b0987b 219 // safety-check against writing client,id,size instead of id,client,size:
9a83f860 220 wxASSERT_MSG( client.Last() == wxT('C'), wxT("invalid 'client' parameter") );
57b0987b 221
9a83f860 222 wxCHECK_MSG( sm_providers, wxNullBitmap, wxT("no wxArtProvider exists") );
2aca4a98 223
e53a95bc 224 wxString hashId = wxArtProviderCache::ConstructHashID(id, client, size);
2aca4a98
VS
225
226 wxBitmap bmp;
227 if ( !sm_cache->GetBitmap(hashId, &bmp) )
228 {
222ed1d6 229 for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
2aca4a98
VS
230 node; node = node->GetNext())
231 {
e53a95bc 232 bmp = node->GetData()->CreateBitmap(id, client, size);
a1b806b9 233 if ( bmp.IsOk() )
b5c2a334
VS
234 break;
235 }
236
1d3dfc57 237 wxSize sizeNeeded = size;
a1b806b9 238 if ( !bmp.IsOk() )
b5c2a334
VS
239 {
240 // no bitmap created -- as a fallback, try if we can find desired
241 // icon in a bundle
242 wxIconBundle iconBundle = DoGetIconBundle(id, client);
243 if ( iconBundle.IsOk() )
3242feb1 244 {
1d3dfc57
VZ
245 if ( sizeNeeded == wxDefaultSize )
246 sizeNeeded = GetNativeSizeHint(client);
247
248 wxIcon icon(iconBundle.GetIcon(sizeNeeded));
b5c2a334 249 if ( icon.IsOk() )
1d3dfc57
VZ
250 {
251 // this icon may be not of the correct size, it will be
252 // rescaled below in such case
b5c2a334 253 bmp.CopyFromIcon(icon);
1d3dfc57 254 }
b5c2a334
VS
255 }
256 }
257
1d3dfc57 258 // if we didn't get the correct size, resize the bitmap
64c288fa 259#if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB)
1d3dfc57
VZ
260 if ( bmp.IsOk() && sizeNeeded != wxDefaultSize )
261 {
262 if ( bmp.GetSize() != sizeNeeded )
b5c2a334
VS
263 {
264 wxImage img = bmp.ConvertToImage();
1d3dfc57 265 img.Rescale(sizeNeeded.x, sizeNeeded.y);
b5c2a334 266 bmp = wxBitmap(img);
3242feb1 267 }
2aca4a98 268 }
1d3dfc57 269#endif // wxUSE_IMAGE
b5c2a334 270
2aca4a98 271 sm_cache->PutBitmap(hashId, bmp);
b5c2a334 272 }
2aca4a98
VS
273
274 return bmp;
275}
276
b5c2a334
VS
277/*static*/
278wxIconBundle wxArtProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client)
279{
280 wxIconBundle iconbundle(DoGetIconBundle(id, client));
281
282 if ( iconbundle.IsOk() )
283 {
284 return iconbundle;
285 }
286 else
287 {
288 // fall back to single-icon bundle
289 return wxIconBundle(GetIcon(id, client));
290 }
291}
292
293/*static*/
294wxIconBundle wxArtProvider::DoGetIconBundle(const wxArtID& id, const wxArtClient& client)
52734360
VZ
295{
296 // safety-check against writing client,id,size instead of id,client,size:
9a83f860 297 wxASSERT_MSG( client.Last() == wxT('C'), wxT("invalid 'client' parameter") );
52734360 298
9a83f860 299 wxCHECK_MSG( sm_providers, wxNullIconBundle, wxT("no wxArtProvider exists") );
52734360
VZ
300
301 wxString hashId = wxArtProviderCache::ConstructHashID(id, client);
302
303 wxIconBundle iconbundle;
304 if ( !sm_cache->GetIconBundle(hashId, &iconbundle) )
305 {
306 for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
307 node; node = node->GetNext())
308 {
309 iconbundle = node->GetData()->CreateIconBundle(id, client);
310 if ( iconbundle.IsOk() )
311 break;
312 }
313
314 sm_cache->PutIconBundle(hashId, iconbundle);
315 }
316
317 return iconbundle;
318}
319
57b0987b
VS
320/*static*/ wxIcon wxArtProvider::GetIcon(const wxArtID& id,
321 const wxArtClient& client,
2aca4a98
VS
322 const wxSize& size)
323{
57b0987b 324 wxBitmap bmp = GetBitmap(id, client, size);
b5c2a334
VS
325
326 if ( !bmp.IsOk() )
2aca4a98 327 return wxNullIcon;
2aca4a98 328
25dd6997
VZ
329 wxIcon icon;
330 icon.CopyFromBitmap(bmp);
331 return icon;
332}
2aca4a98 333
1970409e 334/* static */
39f6b6ba 335wxArtID wxArtProvider::GetMessageBoxIconId(int flags)
1970409e 336{
1970409e
VZ
337 switch ( flags & wxICON_MASK )
338 {
339 default:
9a83f860 340 wxFAIL_MSG(wxT("incorrect message box icon flags"));
1970409e
VZ
341 // fall through
342
343 case wxICON_ERROR:
39f6b6ba 344 return wxART_ERROR;
1970409e
VZ
345
346 case wxICON_INFORMATION:
39f6b6ba 347 return wxART_INFORMATION;
1970409e
VZ
348
349 case wxICON_WARNING:
39f6b6ba 350 return wxART_WARNING;
1970409e
VZ
351
352 case wxICON_QUESTION:
39f6b6ba 353 return wxART_QUESTION;
1970409e 354 }
1970409e
VZ
355}
356
e53a95bc 357/*static*/ wxSize wxArtProvider::GetSizeHint(const wxArtClient& client,
b737ad10
RR
358 bool platform_dependent)
359{
360 if (!platform_dependent)
361 {
362 wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
363 if (node)
e53a95bc
RR
364 return node->GetData()->DoGetSizeHint(client);
365 }
f6d43eda 366
a158acac
VS
367 return GetNativeSizeHint(client);
368}
369
370#ifndef wxHAS_NATIVE_ART_PROVIDER_IMPL
371/*static*/
6f23f80b 372wxSize wxArtProvider::GetNativeSizeHint(const wxArtClient& WXUNUSED(client))
a158acac
VS
373{
374 // rather than returning some arbitrary value that doesn't make much
375 // sense (as 2.8 used to do), tell the caller that we don't have a clue:
376 return wxDefaultSize;
377}
378
379/*static*/
380void wxArtProvider::InitNativeProvider()
381{
b737ad10 382}
a158acac
VS
383#endif // !wxHAS_NATIVE_ART_PROVIDER_IMPL
384
b737ad10 385
14440cc6
VS
386/* static */
387bool wxArtProvider::HasNativeProvider()
388{
389#ifdef __WXGTK20__
390 return true;
391#else
392 return false;
393#endif
394}
395
571d2e0f
VZ
396// ----------------------------------------------------------------------------
397// deprecated wxArtProvider methods
398// ----------------------------------------------------------------------------
399
400#if WXWIN_COMPATIBILITY_2_6
401
402/* static */ void wxArtProvider::PushProvider(wxArtProvider *provider)
403{
404 Push(provider);
405}
406
407/* static */ void wxArtProvider::InsertProvider(wxArtProvider *provider)
408{
7716a165 409 PushBack(provider);
571d2e0f
VZ
410}
411
412/* static */ bool wxArtProvider::PopProvider()
413{
414 return Pop();
415}
416
417/* static */ bool wxArtProvider::RemoveProvider(wxArtProvider *provider)
418{
419 // RemoveProvider() used to delete the provider being removed so this is
420 // not a typo, we must call Delete() and not Remove() here
421 return Delete(provider);
422}
423
424#endif // WXWIN_COMPATIBILITY_2_6
425
14440cc6
VS
426#if WXWIN_COMPATIBILITY_2_8
427/* static */ void wxArtProvider::Insert(wxArtProvider *provider)
428{
429 PushBack(provider);
430}
431#endif // WXWIN_COMPATIBILITY_2_8
432
571d2e0f
VZ
433// ============================================================================
434// wxArtProviderModule
435// ============================================================================
2aca4a98
VS
436
437class wxArtProviderModule: public wxModule
438{
439public:
2b5f62a0
VZ
440 bool OnInit()
441 {
0d68cd13
VZ
442 // The order here is such that the native provider will be used first
443 // and the standard one last as all these default providers add
444 // themselves to the bottom of the stack.
445 wxArtProvider::InitNativeProvider();
c1d2466a
VZ
446#if wxUSE_ARTPROVIDER_TANGO
447 wxArtProvider::InitTangoProvider();
448#endif // wxUSE_ARTPROVIDER_TANGO
0d68cd13
VZ
449#if wxUSE_ARTPROVIDER_STD
450 wxArtProvider::InitStdProvider();
451#endif // wxUSE_ARTPROVIDER_STD
4629016d 452 return true;
2b5f62a0
VZ
453 }
454 void OnExit()
455 {
456 wxArtProvider::CleanUpProviders();
457 }
2aca4a98
VS
458
459 DECLARE_DYNAMIC_CLASS(wxArtProviderModule)
460};
461
462IMPLEMENT_DYNAMIC_CLASS(wxArtProviderModule, wxModule)