1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/iconbndl.cpp
3 // Purpose: wxIconBundle
4 // Author: Mattia Barbon, Vadim Zeitlin
7 // Copyright: (c) Mattia barbon
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #include "wx/iconbndl.h"
21 #include "wx/settings.h"
24 #include "wx/bitmap.h"
26 #include "wx/stream.h"
29 #include "wx/wfstream.h"
31 #include "wx/arrimpl.cpp"
32 WX_DEFINE_OBJARRAY(wxIconArray
)
34 IMPLEMENT_DYNAMIC_CLASS(wxIconBundle
, wxGDIObject
)
36 #define M_ICONBUNDLEDATA static_cast<wxIconBundleRefData*>(m_refData)
38 // ----------------------------------------------------------------------------
39 // wxIconBundleRefData
40 // ----------------------------------------------------------------------------
42 class WXDLLEXPORT wxIconBundleRefData
: public wxGDIRefData
45 // default and copy ctors and assignment operators are ok
47 virtual bool IsOk() const { return !m_icons
.empty(); }
52 // ============================================================================
53 // wxIconBundle implementation
54 // ============================================================================
56 wxIconBundle::wxIconBundle()
60 #if wxUSE_STREAMS && wxUSE_IMAGE
62 #if wxUSE_FFILE || wxUSE_FILE
63 wxIconBundle::wxIconBundle(const wxString
& file
, wxBitmapType type
)
68 #endif // wxUSE_FFILE || wxUSE_FILE
70 wxIconBundle::wxIconBundle(wxInputStream
& stream
, wxBitmapType type
)
73 AddIcon(stream
, type
);
75 #endif // wxUSE_STREAMS && wxUSE_IMAGE
77 wxIconBundle::wxIconBundle(const wxIcon
& icon
)
83 wxGDIRefData
*wxIconBundle::CreateGDIRefData() const
85 return new wxIconBundleRefData
;
88 wxGDIRefData
*wxIconBundle::CloneGDIRefData(const wxGDIRefData
*data
) const
90 return new wxIconBundleRefData(*static_cast<const wxIconBundleRefData
*>(data
));
93 void wxIconBundle::DeleteIcons()
98 #if wxUSE_STREAMS && wxUSE_IMAGE
103 // Adds icon from 'input' to the bundle. Shows 'errorMessage' on failure
104 // (it must contain "%d", because it is used to report # of image in the file
105 // that failed to load):
106 void DoAddIcon(wxIconBundle
& bundle
,
107 wxInputStream
& input
,
109 const wxString
& errorMessage
)
113 const wxFileOffset posOrig
= input
.TellI();
115 const size_t count
= wxImage::GetImageCount(input
, type
);
116 for ( size_t i
= 0; i
< count
; ++i
)
120 // the call to LoadFile() for the first sub-image updated the
121 // stream position but we need to start reading the subsequent
122 // sub-image at the image beginning too
123 input
.SeekI(posOrig
);
126 if ( !image
.LoadFile(input
, type
, i
) )
128 wxLogError(errorMessage
, i
);
132 if ( type
== wxBITMAP_TYPE_ANY
)
134 // store the type so that we don't need to try all handlers again
135 // for the subsequent images, they should all be of the same type
136 type
= image
.GetType();
140 tmp
.CopyFromBitmap(wxBitmap(image
));
145 } // anonymous namespace
147 #if wxUSE_FFILE || wxUSE_FILE
149 void wxIconBundle::AddIcon(const wxString
& file
, wxBitmapType type
)
152 // Deal with standard icons
153 if ( type
== wxBITMAP_TYPE_ICON_RESOURCE
)
155 wxIcon
tmp(file
, type
);
165 wxFFileInputStream
stream(file
);
167 wxFileInputStream
stream(file
);
173 wxString::Format(_("Failed to load image %%d from file '%s'."), file
)
177 #endif // wxUSE_FFILE || wxUSE_FILE
179 void wxIconBundle::AddIcon(wxInputStream
& stream
, wxBitmapType type
)
181 DoAddIcon(*this, stream
, type
, _("Failed to load image %d from stream."));
184 #endif // wxUSE_STREAMS && wxUSE_IMAGE
186 wxIcon
wxIconBundle::GetIcon(const wxSize
& size
) const
188 const size_t count
= GetIconCount();
190 // optimize for the common case of icon bundles containing one icon only
195 // nothing to do, iconBest is already invalid
199 iconBest
= M_ICONBUNDLEDATA
->m_icons
[0];
203 // there is more than one icon, find the best match:
204 wxCoord sysX
= wxSystemSettings::GetMetric( wxSYS_ICON_X
),
205 sysY
= wxSystemSettings::GetMetric( wxSYS_ICON_Y
);
207 const wxIconArray
& iconArray
= M_ICONBUNDLEDATA
->m_icons
;
208 for ( size_t i
= 0; i
< count
; i
++ )
210 const wxIcon
& icon
= iconArray
[i
];
211 wxCoord sx
= icon
.GetWidth(),
212 sy
= icon
.GetHeight();
214 // if we got an icon of exactly the requested size, we're done
215 if ( sx
== size
.x
&& sy
== size
.y
)
221 // the best icon is by default (arbitrarily) the first one but
222 // if we find a system-sized icon, take it instead
223 if ((sx
== sysX
&& sy
== sysY
) || !iconBest
.IsOk())
228 #if defined( __WXMAC__ ) && wxOSX_USE_CARBON
229 return wxIcon(iconBest
.GetHICON(), size
);
235 wxIcon
wxIconBundle::GetIconOfExactSize(const wxSize
& size
) const
237 wxIcon icon
= GetIcon(size
);
239 (icon
.GetWidth() != size
.x
|| icon
.GetHeight() != size
.y
) )
247 void wxIconBundle::AddIcon(const wxIcon
& icon
)
249 wxCHECK_RET( icon
.IsOk(), wxT("invalid icon") );
253 wxIconArray
& iconArray
= M_ICONBUNDLEDATA
->m_icons
;
255 // replace existing icon with the same size if we already have it
256 const size_t count
= iconArray
.size();
257 for ( size_t i
= 0; i
< count
; ++i
)
259 wxIcon
& tmp
= iconArray
[i
];
261 tmp
.GetWidth() == icon
.GetWidth() &&
262 tmp
.GetHeight() == icon
.GetHeight() )
269 // if we don't, add an icon with new size
273 size_t wxIconBundle::GetIconCount() const
275 return IsOk() ? M_ICONBUNDLEDATA
->m_icons
.size() : 0;
278 wxIcon
wxIconBundle::GetIconByIndex(size_t n
) const
280 wxCHECK_MSG( n
< GetIconCount(), wxNullIcon
, wxT("invalid index") );
282 return M_ICONBUNDLEDATA
->m_icons
[n
];