]>
Commit | Line | Data |
---|---|---|
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::PushBack(new wxTangoArtProvider); | |
326 | } | |
327 | ||
328 | #endif // wxUSE_ARTPROVIDER_TANGO |