PCH-less compilation fix in recently added wxTangoArtProvider.
[wxWidgets.git] / src / common / arttango.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/arttango.cpp
3 // Purpose: art provider using embedded PNG versions of Tango icons
4 // Author: Vadim Zeitlin
5 // Created: 2010-12-27
6 // RCS-ID: $Id: wxhead.cpp,v 1.11 2010-04-22 12:44:51 zeitlin Exp $
7 // Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_ARTPROVIDER_TANGO
27
28 #ifndef WX_PRECOMP
29 #include "wx/image.h"
30 #include "wx/log.h"
31 #endif // WX_PRECOMP
32
33 #include "wx/artprov.h"
34
35 #include "wx/mstream.h"
36
37 // ----------------------------------------------------------------------------
38 // image data
39 // ----------------------------------------------------------------------------
40
41 // All files in art/tango in alphabetical order:
42 #include "../../art/tango/application_x_executable.h"
43 #include "../../art/tango/dialog_error.h"
44 #include "../../art/tango/dialog_information.h"
45 #include "../../art/tango/dialog_warning.h"
46 #include "../../art/tango/document_new.h"
47 #include "../../art/tango/document_open.h"
48 #include "../../art/tango/document_print.h"
49 #include "../../art/tango/document_save.h"
50 #include "../../art/tango/document_save_as.h"
51 #include "../../art/tango/drive_harddisk.h"
52 #include "../../art/tango/drive_optical.h"
53 #include "../../art/tango/drive_removable_media.h"
54 #include "../../art/tango/edit_copy.h"
55 #include "../../art/tango/edit_cut.h"
56 #include "../../art/tango/edit_delete.h"
57 #include "../../art/tango/edit_find.h"
58 #include "../../art/tango/edit_find_replace.h"
59 #include "../../art/tango/edit_paste.h"
60 #include "../../art/tango/edit_redo.h"
61 #include "../../art/tango/edit_undo.h"
62 #include "../../art/tango/folder.h"
63 #include "../../art/tango/folder_new.h"
64 #include "../../art/tango/folder_open.h"
65 #include "../../art/tango/go_down.h"
66 #include "../../art/tango/go_first.h"
67 #include "../../art/tango/go_home.h"
68 #include "../../art/tango/go_last.h"
69 #include "../../art/tango/go_next.h"
70 #include "../../art/tango/go_previous.h"
71 #include "../../art/tango/go_up.h"
72 #include "../../art/tango/image_missing.h"
73 #include "../../art/tango/text_x_generic.h"
74 #include "../../art/tango/list_add.h"
75 #include "../../art/tango/list_remove.h"
76
77 // ----------------------------------------------------------------------------
78 // art provider class
79 // ----------------------------------------------------------------------------
80
81 namespace
82 {
83
84 class wxTangoArtProvider : public wxArtProvider
85 {
86 public:
87 wxTangoArtProvider()
88 {
89 m_imageHandledAdded = false;
90 }
91
92 protected:
93 virtual wxBitmap CreateBitmap(const wxArtID& id,
94 const wxArtClient& client,
95 const wxSize& size);
96
97 private:
98 bool m_imageHandledAdded;
99
100 wxDECLARE_NO_COPY_CLASS(wxTangoArtProvider);
101 };
102
103 } // anonymous namespace
104
105 // ============================================================================
106 // implementation
107 // ============================================================================
108
109 wxBitmap
110 wxTangoArtProvider::CreateBitmap(const wxArtID& id,
111 const wxArtClient& client,
112 const wxSize& sizeHint)
113 {
114 // Array indexed by the id names with pointers to image data in 16 and 32
115 // pixel sizes as values. The order of the elements in this array is the
116 // same as the definition order in wx/artprov.h. While it's not very
117 // logical, this should make it simpler to add new icons later. Notice that
118 // most elements without Tango equivalents are simply omitted.
119
120 // To avoid repetition use BITMAP_DATA to only specify the image name once
121 // (this is especially important if we decide to add more image sizes
122 // later).
123 #define BITMAP_ARRAY_NAME(name, size) \
124 name ## _ ## size ## x ## size ## _png
125 #define BITMAP_DATA_FOR_SIZE(name, size) \
126 BITMAP_ARRAY_NAME(name, size), sizeof(BITMAP_ARRAY_NAME(name, size))
127 #define BITMAP_DATA(name) \
128 BITMAP_DATA_FOR_SIZE(name, 16), BITMAP_DATA_FOR_SIZE(name, 24)
129
130 static const struct BitmapEntry
131 {
132 const char *id;
133 const unsigned char *data16;
134 size_t len16;
135 const unsigned char *data24;
136 size_t len24;
137 } s_allBitmaps[] =
138 {
139 // Tango does have bookmark-new but no matching bookmark-delete and
140 // using mismatching icons would be ugly so we don't provide this one
141 // neither, we should add both of them if Tango ever adds the other one.
142 //{ wxART_ADD_BOOKMARK, BITMAP_DATA(bookmark_new)},
143 //{ wxART_DEL_BOOKMARK, BITMAP_DATA() },
144
145 { wxART_GO_BACK, BITMAP_DATA(go_previous) },
146 { wxART_GO_FORWARD, BITMAP_DATA(go_next) },
147 { wxART_GO_UP, BITMAP_DATA(go_up) },
148 { wxART_GO_DOWN, BITMAP_DATA(go_down) },
149 // wxART_GO_TO_PARENT doesn't seem to exist in Tango
150 { wxART_GO_HOME, BITMAP_DATA(go_home) },
151 { wxART_GOTO_FIRST, BITMAP_DATA(go_first) },
152 { wxART_GOTO_LAST, BITMAP_DATA(go_last) },
153
154 { wxART_FILE_OPEN, BITMAP_DATA(document_open) },
155 { wxART_FILE_SAVE, BITMAP_DATA(document_save) },
156 { wxART_FILE_SAVE_AS, BITMAP_DATA(document_save_as) },
157 { wxART_PRINT, BITMAP_DATA(document_print) },
158
159 // Should we use help-browser for wxART_HELP?
160
161 { wxART_NEW_DIR, BITMAP_DATA(folder_new) },
162 { wxART_HARDDISK, BITMAP_DATA(drive_harddisk) },
163 // drive-removable-media seems to be better than media-floppy
164 { wxART_FLOPPY, BITMAP_DATA(drive_removable_media) },
165 { wxART_CDROM, BITMAP_DATA(drive_optical) },
166 { wxART_REMOVABLE, BITMAP_DATA(drive_removable_media) },
167
168 { wxART_FOLDER, BITMAP_DATA(folder) },
169 { wxART_FOLDER_OPEN, BITMAP_DATA(folder_open) },
170 // wxART_GO_DIR_UP doesn't seem to exist in Tango
171
172 { wxART_EXECUTABLE_FILE, BITMAP_DATA(application_x_executable) },
173 { wxART_NORMAL_FILE, BITMAP_DATA(text_x_generic) },
174
175 // There is no dialog-question in Tango so use the information icon
176 // too, this is better for consistency and we do have a precedent for
177 // doing this as Windows Vista/7 does the same thing natively.
178 { wxART_ERROR, BITMAP_DATA(dialog_error) },
179 { wxART_QUESTION, BITMAP_DATA(dialog_information) },
180 { wxART_WARNING, BITMAP_DATA(dialog_warning) },
181 { wxART_INFORMATION, BITMAP_DATA(dialog_information) },
182
183 { wxART_MISSING_IMAGE, BITMAP_DATA(image_missing) },
184
185 { wxART_COPY, BITMAP_DATA(edit_copy) },
186 { wxART_CUT, BITMAP_DATA(edit_cut) },
187 { wxART_PASTE, BITMAP_DATA(edit_paste) },
188 { wxART_DELETE, BITMAP_DATA(edit_delete) },
189 { wxART_NEW, BITMAP_DATA(document_new) },
190 { wxART_UNDO, BITMAP_DATA(edit_undo) },
191 { wxART_REDO, BITMAP_DATA(edit_redo) },
192
193 { wxART_PLUS, BITMAP_DATA(list_add) },
194 { wxART_MINUS, BITMAP_DATA(list_remove) },
195
196 // Surprisingly Tango doesn't seem to have neither wxART_CLOSE nor
197 // wxART_QUIT. We could use system-log-out for the latter but it
198 // doesn't seem quite right.
199
200 { wxART_FIND, BITMAP_DATA(edit_find) },
201 { wxART_FIND_AND_REPLACE, BITMAP_DATA(edit_find_replace) },
202 };
203
204 #undef BITMAP_ARRAY_NAME
205 #undef BITMAP_DATA_FOR_SIZE
206 #undef BITMAP_DATA
207
208 for ( unsigned n = 0; n < WXSIZEOF(s_allBitmaps); n++ )
209 {
210 const BitmapEntry& entry = s_allBitmaps[n];
211 if ( entry.id != id )
212 continue;
213
214 // This is one of the bitmaps that we have, determine in which size we
215 // should return it.
216
217 wxSize size;
218 bool sizeIsAHint;
219 if ( sizeHint == wxDefaultSize )
220 {
221 // Use the normal platform-specific icon size.
222 size = GetNativeSizeHint(client);
223
224 if ( size == wxDefaultSize )
225 {
226 // If we failed to get it, determine the best size more or less
227 // arbitrarily. This definitely won't look good but then it
228 // shouldn't normally happen, all platforms should implement
229 // GetNativeSizeHint() properly.
230 if ( client == wxART_MENU || client == wxART_BUTTON )
231 size = wxSize(16, 16);
232 else
233 size = wxSize(24, 24);
234 }
235
236 // We should return the icon of exactly this size so it's more than
237 // just a hint.
238 sizeIsAHint = false;
239 }
240 else // We have a size hint
241 {
242 // Use it for determining the version of the icon to return.
243 size = sizeHint;
244
245 // But we don't need to return the image of exactly the same size
246 // as the hint, after all it's just that, a hint.
247 sizeIsAHint = true;
248 }
249
250 enum
251 {
252 TangoSize_16,
253 TangoSize_24
254 } tangoSize;
255
256 // We prefer to downscale the image rather than upscale it if possible
257 // so use the smaller one if we can, otherwise the large one.
258 if ( size.x <= 16 && size.y <= 16 )
259 tangoSize = TangoSize_16;
260 else
261 tangoSize = TangoSize_24;
262
263 const unsigned char *data;
264 size_t len;
265 switch ( tangoSize )
266 {
267 default:
268 wxFAIL_MSG( "Unsupported Tango bitmap size" );
269 // fall through
270
271 case TangoSize_16:
272 data = entry.data16;
273 len = entry.len16;
274 break;
275
276 case TangoSize_24:
277 data = entry.data24;
278 len = entry.len24;
279 break;
280 }
281
282 wxMemoryInputStream is(data, len);
283
284 // Before reading the image data from the stream for the first time,
285 // add the handler for PNG images: we do it here and not in, say,
286 // InitTangoProvider() to do it as lately as possible and so to avoid
287 // the asserts about adding an already added handler if the user code
288 // adds the handler itself.
289 if ( !m_imageHandledAdded )
290 {
291 // Of course, if the user code did add it already, we have nothing
292 // to do.
293 if ( !wxImage::FindHandler(wxBITMAP_TYPE_PNG) )
294 wxImage::AddHandler(new wxPNGHandler);
295
296 // In any case, no need to do it again.
297 m_imageHandledAdded = true;
298 }
299
300 wxImage image(is, wxBITMAP_TYPE_PNG);
301 if ( !image.IsOk() )
302 {
303 // This should normally never happen as all the embedded images are
304 // well-formed.
305 wxLogDebug("Failed to load embedded PNG image for \"%s\"", id);
306 return wxNullBitmap;
307 }
308
309 if ( !sizeIsAHint )
310 {
311 // Notice that this won't do anything if the size is already right.
312 image.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
313 }
314
315 return image;
316 }
317
318 // Not one of the bitmaps that we support.
319 return wxNullBitmap;
320 }
321
322 /* static */
323 void wxArtProvider::InitTangoProvider()
324 {
325 wxArtProvider::Push(new wxTangoArtProvider);
326 }
327
328 #endif // wxUSE_ARTPROVIDER_TANGO