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
+ _T('-') + client
;
115 /* static */ wxString
116 wxArtProviderCache::ConstructHashID(const wxArtID
& id
,
117 const wxArtClient
& client
,
120 return ConstructHashID(id
, client
) + _T('-') +
121 wxString::Format(_T("%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::Insert(wxArtProvider
*provider
)
165 CommonAddingProvider();
166 sm_providers
->Append(provider
);
169 /*static*/ bool wxArtProvider::Pop()
171 wxCHECK_MSG( sm_providers
, false, _T("no wxArtProvider exists") );
172 wxCHECK_MSG( !sm_providers
->empty(), false, _T("wxArtProviders stack is empty") );
174 delete sm_providers
->GetFirst()->GetData();
179 /*static*/ bool wxArtProvider::Remove(wxArtProvider
*provider
)
181 wxCHECK_MSG( sm_providers
, false, _T("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() == _T('C'), _T("invalid 'client' parameter") );
226 wxCHECK_MSG( sm_providers
, wxNullBitmap
, _T("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
);
239 #if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB)
240 if ( size
!= wxDefaultSize
&&
241 (bmp
.GetWidth() != size
.x
|| bmp
.GetHeight() != size
.y
) )
243 wxImage img
= bmp
.ConvertToImage();
244 img
.Rescale(size
.x
, size
.y
);
250 // We could try the IconBundles here and convert what we find
253 sm_cache
->PutBitmap(hashId
, bmp
);
259 /*static*/ wxIconBundle
wxArtProvider::GetIconBundle(const wxArtID
& id
, const wxArtClient
& client
)
261 // safety-check against writing client,id,size instead of id,client,size:
262 wxASSERT_MSG( client
.Last() == _T('C'), _T("invalid 'client' parameter") );
264 wxCHECK_MSG( sm_providers
, wxNullIconBundle
, _T("no wxArtProvider exists") );
266 wxString hashId
= wxArtProviderCache::ConstructHashID(id
, client
);
268 wxIconBundle iconbundle
;
269 if ( !sm_cache
->GetIconBundle(hashId
, &iconbundle
) )
271 for (wxArtProvidersList::compatibility_iterator node
= sm_providers
->GetFirst();
272 node
; node
= node
->GetNext())
274 iconbundle
= node
->GetData()->CreateIconBundle(id
, client
);
275 if ( iconbundle
.IsOk() )
279 sm_cache
->PutIconBundle(hashId
, iconbundle
);
285 /*static*/ wxIcon
wxArtProvider::GetIcon(const wxArtID
& id
,
286 const wxArtClient
& client
,
289 wxCHECK_MSG( sm_providers
, wxNullIcon
, _T("no wxArtProvider exists") );
291 // First look for an appropriate icon bundle - this will give us the best icon
292 wxIconBundle iconBundle
= GetIconBundle(id
, client
);
293 if ( iconBundle
.IsOk() )
294 return iconBundle
.GetIcon(size
);
296 // If there is no icon bundle then look for a bitmap
297 wxBitmap bmp
= GetBitmap(id
, client
, size
);
302 icon
.CopyFromBitmap(bmp
);
306 #if defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)
307 #include "wx/gtk/private.h"
308 extern GtkIconSize
wxArtClientToIconSize(const wxArtClient
& client
);
309 #endif // defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)
311 /*static*/ wxSize
wxArtProvider::GetSizeHint(const wxArtClient
& client
,
312 bool platform_dependent
)
314 if (!platform_dependent
)
316 wxArtProvidersList::compatibility_iterator node
= sm_providers
->GetFirst();
318 return node
->GetData()->DoGetSizeHint(client
);
321 // else return platform dependent size
323 #if defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)
324 // Gtk has specific sizes for each client, see artgtk.cpp
325 GtkIconSize gtk_size
= wxArtClientToIconSize(client
);
326 // no size hints for this client
327 if (gtk_size
== GTK_ICON_SIZE_INVALID
)
328 return wxDefaultSize
;
330 gtk_icon_size_lookup( gtk_size
, &width
, &height
);
331 return wxSize(width
, height
);
333 // NB: These size hints may have to be adjusted per platform
334 if (client
== wxART_TOOLBAR
)
335 return wxSize(16, 15);
336 else if (client
== wxART_MENU
)
337 return wxSize(16, 15);
338 else if (client
== wxART_FRAME_ICON
)
339 return wxSize(16, 15);
340 else if (client
== wxART_CMN_DIALOG
|| client
== wxART_MESSAGE_BOX
)
341 return wxSize(32, 32);
342 else if (client
== wxART_HELP_BROWSER
)
343 return wxSize(16, 15);
344 else if (client
== wxART_BUTTON
)
345 return wxSize(16, 15);
346 else // wxART_OTHER or perhaps a user's client, no specified size
347 return wxDefaultSize
;
348 #endif // GTK+ 2/else
351 // ----------------------------------------------------------------------------
352 // deprecated wxArtProvider methods
353 // ----------------------------------------------------------------------------
355 #if WXWIN_COMPATIBILITY_2_6
357 /* static */ void wxArtProvider::PushProvider(wxArtProvider
*provider
)
362 /* static */ void wxArtProvider::InsertProvider(wxArtProvider
*provider
)
367 /* static */ bool wxArtProvider::PopProvider()
372 /* static */ bool wxArtProvider::RemoveProvider(wxArtProvider
*provider
)
374 // RemoveProvider() used to delete the provider being removed so this is
375 // not a typo, we must call Delete() and not Remove() here
376 return Delete(provider
);
379 #endif // WXWIN_COMPATIBILITY_2_6
381 // ============================================================================
382 // wxArtProviderModule
383 // ============================================================================
385 class wxArtProviderModule
: public wxModule
390 wxArtProvider::InitStdProvider();
391 wxArtProvider::InitNativeProvider();
396 wxArtProvider::CleanUpProviders();
399 DECLARE_DYNAMIC_CLASS(wxArtProviderModule
)
402 IMPLEMENT_DYNAMIC_CLASS(wxArtProviderModule
, wxModule
)