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