hook the docview-specific customization of event handling logic at TryValidator(...
[wxWidgets.git] / src / common / iconbndl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/iconbndl.cpp
3 // Purpose: wxIconBundle
4 // Author: Mattia Barbon, Vadim Zeitlin
5 // Created: 23.03.2002
6 // RCS-ID: $Id$
7 // Copyright: (c) Mattia barbon
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #include "wx/iconbndl.h"
19
20 #ifndef WX_PRECOMP
21 #include "wx/settings.h"
22 #include "wx/log.h"
23 #include "wx/intl.h"
24 #include "wx/bitmap.h"
25 #include "wx/image.h"
26 #endif
27
28 #include "wx/arrimpl.cpp"
29 WX_DEFINE_OBJARRAY(wxIconArray)
30
31 IMPLEMENT_DYNAMIC_CLASS(wxIconBundle, wxGDIObject)
32
33 #define M_ICONBUNDLEDATA static_cast<wxIconBundleRefData*>(m_refData)
34
35 // ----------------------------------------------------------------------------
36 // wxIconBundleRefData
37 // ----------------------------------------------------------------------------
38
39 class WXDLLEXPORT wxIconBundleRefData : public wxGDIRefData
40 {
41 public:
42 // default and copy ctors and assignment operators are ok
43
44 virtual bool IsOk() const { return !m_icons.empty(); }
45
46 wxIconArray m_icons;
47 };
48
49 // ============================================================================
50 // wxIconBundle implementation
51 // ============================================================================
52
53 wxIconBundle::wxIconBundle()
54 {
55 }
56
57 wxIconBundle::wxIconBundle(const wxString& file, wxBitmapType type)
58 : wxGDIObject()
59 {
60 AddIcon(file, type);
61 }
62
63 wxIconBundle::wxIconBundle(const wxIcon& icon)
64 : wxGDIObject()
65 {
66 AddIcon(icon);
67 }
68
69 wxGDIRefData *wxIconBundle::CreateGDIRefData() const
70 {
71 return new wxIconBundleRefData;
72 }
73
74 wxGDIRefData *wxIconBundle::CloneGDIRefData(const wxGDIRefData *data) const
75 {
76 return new wxIconBundleRefData(*wx_static_cast(const wxIconBundleRefData *, data));
77 }
78
79 void wxIconBundle::DeleteIcons()
80 {
81 UnRef();
82 }
83
84 void wxIconBundle::AddIcon(const wxString& file, wxBitmapType type)
85 {
86 #ifdef __WXMAC__
87 // Deal with standard icons
88 if ( type == wxBITMAP_TYPE_ICON_RESOURCE )
89 {
90 wxIcon tmp(file, type);
91 if (tmp.Ok())
92 {
93 AddIcon(tmp);
94 return;
95 }
96 }
97 #endif // __WXMAC__
98
99 #if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB)
100 wxImage image;
101
102 const size_t count = wxImage::GetImageCount( file, type );
103 for ( size_t i = 0; i < count; ++i )
104 {
105 if ( !image.LoadFile( file, type, i ) )
106 {
107 wxLogError( _("Failed to load image %d from file '%s'."),
108 i, file.c_str() );
109 continue;
110 }
111
112 wxIcon tmp;
113 tmp.CopyFromBitmap(wxBitmap(image));
114 AddIcon(tmp);
115 }
116 #else // !wxUSE_IMAGE
117 wxUnusedVar(file);
118 wxUnusedVar(type);
119 #endif // wxUSE_IMAGE/!wxUSE_IMAGE
120 }
121
122 wxIcon wxIconBundle::GetIcon(const wxSize& size) const
123 {
124 const size_t count = GetIconCount();
125
126 // optimize for the common case of icon bundles containing one icon only
127 wxIcon iconBest;
128 switch ( count )
129 {
130 case 0:
131 // nothing to do, iconBest is already invalid
132 break;
133
134 case 1:
135 iconBest = M_ICONBUNDLEDATA->m_icons[0];
136 break;
137
138 default:
139 // there is more than one icon, find the best match:
140 wxCoord sysX = wxSystemSettings::GetMetric( wxSYS_ICON_X ),
141 sysY = wxSystemSettings::GetMetric( wxSYS_ICON_Y );
142
143 const wxIconArray& iconArray = M_ICONBUNDLEDATA->m_icons;
144 for ( size_t i = 0; i < count; i++ )
145 {
146 const wxIcon& icon = iconArray[i];
147 wxCoord sx = icon.GetWidth(),
148 sy = icon.GetHeight();
149
150 // if we got an icon of exactly the requested size, we're done
151 if ( sx == size.x && sy == size.y )
152 {
153 iconBest = icon;
154 break;
155 }
156
157 // the best icon is by default (arbitrarily) the first one but
158 // if we find a system-sized icon, take it instead
159 if ((sx == sysX && sy == sysY) || !iconBest.IsOk())
160 iconBest = icon;
161 }
162 }
163
164 #if defined( __WXMAC__ ) && wxOSX_USE_CARRBON
165 return wxIcon(iconBest.GetHICON(), size);
166 #else
167 return iconBest;
168 #endif
169 }
170
171 wxIcon wxIconBundle::GetIconOfExactSize(const wxSize& size) const
172 {
173 wxIcon icon = GetIcon(size);
174 if ( icon.Ok() &&
175 (icon.GetWidth() != size.x || icon.GetHeight() != size.y) )
176 {
177 icon = wxNullIcon;
178 }
179
180 return icon;
181 }
182
183 void wxIconBundle::AddIcon(const wxIcon& icon)
184 {
185 wxCHECK_RET( icon.IsOk(), _T("invalid icon") );
186
187 AllocExclusive();
188
189 wxIconArray& iconArray = M_ICONBUNDLEDATA->m_icons;
190
191 // replace existing icon with the same size if we already have it
192 const size_t count = iconArray.size();
193 for ( size_t i = 0; i < count; ++i )
194 {
195 wxIcon& tmp = iconArray[i];
196 if ( tmp.Ok() &&
197 tmp.GetWidth() == icon.GetWidth() &&
198 tmp.GetHeight() == icon.GetHeight() )
199 {
200 tmp = icon;
201 return;
202 }
203 }
204
205 // if we don't, add an icon with new size
206 iconArray.Add(icon);
207 }
208
209 size_t wxIconBundle::GetIconCount() const
210 {
211 return IsOk() ? M_ICONBUNDLEDATA->m_icons.size() : 0;
212 }
213
214 wxIcon wxIconBundle::GetIconByIndex(size_t n) const
215 {
216 wxCHECK_MSG( n < GetIconCount(), wxNullIcon, _T("invalid index") );
217
218 return M_ICONBUNDLEDATA->m_icons[n];
219 }