~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/gtk/artgtk.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/gtk/artgtk.cpp
 
3
// Purpose:     stock wxArtProvider instance with native GTK+ stock icons
 
4
// Author:      Vaclav Slavik
 
5
// Modified by:
 
6
// Created:     2004-08-22
 
7
// RCS-ID:      $Id: artgtk.cpp 71894 2012-06-30 20:39:06Z PC $
 
8
// Copyright:   (c) Vaclav Slavik, 2004
 
9
// Licence:     wxWindows licence
 
10
/////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
// ---------------------------------------------------------------------------
 
13
// headers
 
14
// ---------------------------------------------------------------------------
 
15
 
 
16
// For compilers that support precompilation, includes "wx.h".
 
17
#include "wx/wxprec.h"
 
18
 
 
19
#if defined(__BORLANDC__)
 
20
    #pragma hdrstop
 
21
#endif
 
22
 
 
23
#include "wx/artprov.h"
 
24
 
 
25
#include <gtk/gtk.h>
 
26
#include "wx/gtk/private.h"
 
27
 
 
28
// compatibility with older GTK+ versions:
 
29
#ifndef GTK_STOCK_FILE
 
30
    #define GTK_STOCK_FILE "gtk-file"
 
31
#endif
 
32
#ifndef GTK_STOCK_DIRECTORY
 
33
    #define GTK_STOCK_DIRECTORY "gtk-directory"
 
34
#endif
 
35
 
 
36
 
 
37
// ----------------------------------------------------------------------------
 
38
// wxGTK2ArtProvider
 
39
// ----------------------------------------------------------------------------
 
40
 
 
41
class wxGTK2ArtProvider : public wxArtProvider
 
42
{
 
43
protected:
 
44
    virtual wxBitmap CreateBitmap(const wxArtID& id, const wxArtClient& client,
 
45
                                  const wxSize& size);
 
46
    virtual wxIconBundle CreateIconBundle(const wxArtID& id,
 
47
                                          const wxArtClient& client);
 
48
};
 
49
 
 
50
/*static*/ void wxArtProvider::InitNativeProvider()
 
51
{
 
52
    PushBack(new wxGTK2ArtProvider);
 
53
}
 
54
 
 
55
// ----------------------------------------------------------------------------
 
56
// CreateBitmap routine
 
57
// ----------------------------------------------------------------------------
 
58
 
 
59
namespace
 
60
{
 
61
 
 
62
wxString wxArtIDToStock(const wxArtID& id)
 
63
{
 
64
    #define ART(wxid, gtkid) \
 
65
           if (id == wxid) return gtkid;
 
66
 
 
67
    ART(wxART_ERROR,                               GTK_STOCK_DIALOG_ERROR)
 
68
    ART(wxART_INFORMATION,                         GTK_STOCK_DIALOG_INFO)
 
69
    ART(wxART_WARNING,                             GTK_STOCK_DIALOG_WARNING)
 
70
    ART(wxART_QUESTION,                            GTK_STOCK_DIALOG_QUESTION)
 
71
 
 
72
    //ART(wxART_HELP_SIDE_PANEL,                     )
 
73
    ART(wxART_HELP_SETTINGS,                       GTK_STOCK_SELECT_FONT)
 
74
    //ART(wxART_HELP_BOOK,                           )
 
75
    ART(wxART_HELP_FOLDER,                         GTK_STOCK_DIRECTORY)
 
76
    ART(wxART_HELP_PAGE,                           GTK_STOCK_FILE)
 
77
    ART(wxART_MISSING_IMAGE,                       GTK_STOCK_MISSING_IMAGE)
 
78
    ART(wxART_ADD_BOOKMARK,                        GTK_STOCK_ADD)
 
79
    ART(wxART_DEL_BOOKMARK,                        GTK_STOCK_REMOVE)
 
80
    ART(wxART_GO_BACK,                             GTK_STOCK_GO_BACK)
 
81
    ART(wxART_GO_FORWARD,                          GTK_STOCK_GO_FORWARD)
 
82
    ART(wxART_GO_UP,                               GTK_STOCK_GO_UP)
 
83
    ART(wxART_GO_DOWN,                             GTK_STOCK_GO_DOWN)
 
84
    ART(wxART_GO_TO_PARENT,                        GTK_STOCK_GO_UP)
 
85
    ART(wxART_GO_HOME,                             GTK_STOCK_HOME)
 
86
    ART(wxART_GOTO_FIRST,                          GTK_STOCK_GOTO_FIRST)
 
87
    ART(wxART_GOTO_LAST,                           GTK_STOCK_GOTO_LAST)
 
88
    ART(wxART_FILE_OPEN,                           GTK_STOCK_OPEN)
 
89
    ART(wxART_PRINT,                               GTK_STOCK_PRINT)
 
90
    ART(wxART_HELP,                                GTK_STOCK_HELP)
 
91
    ART(wxART_TIP,                                 GTK_STOCK_DIALOG_INFO)
 
92
    //ART(wxART_REPORT_VIEW,                         )
 
93
    //ART(wxART_LIST_VIEW,                           )
 
94
    //ART(wxART_NEW_DIR,                             )
 
95
    ART(wxART_FOLDER,                              GTK_STOCK_DIRECTORY)
 
96
    ART(wxART_FOLDER_OPEN,                         GTK_STOCK_DIRECTORY)
 
97
    //ART(wxART_GO_DIR_UP,                           )
 
98
    ART(wxART_EXECUTABLE_FILE,                     GTK_STOCK_EXECUTE)
 
99
    ART(wxART_NORMAL_FILE,                         GTK_STOCK_FILE)
 
100
    ART(wxART_TICK_MARK,                           GTK_STOCK_APPLY)
 
101
    ART(wxART_CROSS_MARK,                          GTK_STOCK_CANCEL)
 
102
 
 
103
    ART(wxART_FLOPPY,                              GTK_STOCK_FLOPPY)
 
104
    ART(wxART_CDROM,                               GTK_STOCK_CDROM)
 
105
    ART(wxART_HARDDISK,                            GTK_STOCK_HARDDISK)
 
106
    ART(wxART_REMOVABLE,                           GTK_STOCK_HARDDISK)
 
107
 
 
108
    ART(wxART_FILE_SAVE,                           GTK_STOCK_SAVE)
 
109
    ART(wxART_FILE_SAVE_AS,                        GTK_STOCK_SAVE_AS)
 
110
 
 
111
    ART(wxART_COPY,                                GTK_STOCK_COPY)
 
112
    ART(wxART_CUT,                                 GTK_STOCK_CUT)
 
113
    ART(wxART_PASTE,                               GTK_STOCK_PASTE)
 
114
    ART(wxART_DELETE,                              GTK_STOCK_DELETE)
 
115
    ART(wxART_NEW,                                 GTK_STOCK_NEW)
 
116
 
 
117
    ART(wxART_UNDO,                                GTK_STOCK_UNDO)
 
118
    ART(wxART_REDO,                                GTK_STOCK_REDO)
 
119
 
 
120
    ART(wxART_PLUS,                                GTK_STOCK_ADD)
 
121
    ART(wxART_MINUS,                               GTK_STOCK_REMOVE)
 
122
 
 
123
    ART(wxART_CLOSE,                               GTK_STOCK_CLOSE)
 
124
    ART(wxART_QUIT,                                GTK_STOCK_QUIT)
 
125
 
 
126
    ART(wxART_FIND,                                GTK_STOCK_FIND)
 
127
    ART(wxART_FIND_AND_REPLACE,                    GTK_STOCK_FIND_AND_REPLACE)
 
128
 
 
129
    #undef ART
 
130
 
 
131
    // allow passing GTK+ stock IDs to wxArtProvider -- if a recognized wx
 
132
    // ID wasn't found, pass it to GTK+ in the hope it is a GTK+ or theme
 
133
    // icon name:
 
134
    return id;
 
135
}
 
136
 
 
137
GtkIconSize ArtClientToIconSize(const wxArtClient& client)
 
138
{
 
139
    if (client == wxART_TOOLBAR)
 
140
        return GTK_ICON_SIZE_LARGE_TOOLBAR;
 
141
    else if (client == wxART_MENU || client == wxART_FRAME_ICON)
 
142
        return GTK_ICON_SIZE_MENU;
 
143
    else if (client == wxART_CMN_DIALOG || client == wxART_MESSAGE_BOX)
 
144
        return GTK_ICON_SIZE_DIALOG;
 
145
    else if (client == wxART_BUTTON)
 
146
        return GTK_ICON_SIZE_BUTTON;
 
147
    else
 
148
        return GTK_ICON_SIZE_INVALID; // this is arbitrary
 
149
}
 
150
 
 
151
GtkIconSize FindClosestIconSize(const wxSize& size)
 
152
{
 
153
    #define NUM_SIZES 6
 
154
    static struct
 
155
    {
 
156
        GtkIconSize icon;
 
157
        gint x, y;
 
158
    } s_sizes[NUM_SIZES];
 
159
    static bool s_sizesInitialized = false;
 
160
 
 
161
    if (!s_sizesInitialized)
 
162
    {
 
163
        s_sizes[0].icon = GTK_ICON_SIZE_MENU;
 
164
        s_sizes[1].icon = GTK_ICON_SIZE_SMALL_TOOLBAR;
 
165
        s_sizes[2].icon = GTK_ICON_SIZE_LARGE_TOOLBAR;
 
166
        s_sizes[3].icon = GTK_ICON_SIZE_BUTTON;
 
167
        s_sizes[4].icon = GTK_ICON_SIZE_DND;
 
168
        s_sizes[5].icon = GTK_ICON_SIZE_DIALOG;
 
169
        for (size_t i = 0; i < NUM_SIZES; i++)
 
170
        {
 
171
            gtk_icon_size_lookup(s_sizes[i].icon,
 
172
                                 &s_sizes[i].x, &s_sizes[i].y);
 
173
        }
 
174
        s_sizesInitialized = true;
 
175
    }
 
176
 
 
177
    GtkIconSize best = GTK_ICON_SIZE_DIALOG; // presumably largest
 
178
    unsigned distance = INT_MAX;
 
179
    for (size_t i = 0; i < NUM_SIZES; i++)
 
180
    {
 
181
        // only use larger bitmaps, scaling down looks better than scaling up:
 
182
        if (size.x > s_sizes[i].x || size.y > s_sizes[i].y)
 
183
            continue;
 
184
 
 
185
        unsigned dist = (size.x - s_sizes[i].x) * (size.x - s_sizes[i].x) +
 
186
                        (size.y - s_sizes[i].y) * (size.y - s_sizes[i].y);
 
187
        if (dist == 0)
 
188
            return s_sizes[i].icon;
 
189
        else if (dist < distance)
 
190
        {
 
191
            distance = dist;
 
192
            best = s_sizes[i].icon;
 
193
        }
 
194
    }
 
195
    return best;
 
196
}
 
197
 
 
198
GdkPixbuf *CreateStockIcon(const char *stockid, GtkIconSize size)
 
199
{
 
200
    // FIXME: This code is not 100% correct, because stock pixmap are
 
201
    //        context-dependent and may be affected by theme engine, the
 
202
    //        correct value can only be obtained for given GtkWidget object.
 
203
    //
 
204
    //        Fool-proof implementation of stock bitmaps would extend wxBitmap
 
205
    //        with "stock-id" representation (in addition to pixmap and pixbuf
 
206
    //        ones) and would convert it to pixbuf when rendered.
 
207
 
 
208
    GtkStyle* style = gtk_widget_get_style(wxGTKPrivate::GetButtonWidget());
 
209
    GtkIconSet* iconset = gtk_style_lookup_icon_set(style, stockid);
 
210
 
 
211
    if (!iconset)
 
212
        return NULL;
 
213
 
 
214
    return gtk_icon_set_render_icon(iconset, style,
 
215
                                    gtk_widget_get_default_direction(),
 
216
                                    GTK_STATE_NORMAL, size, NULL, NULL);
 
217
}
 
218
 
 
219
GdkPixbuf *CreateThemeIcon(const char *iconname, int size)
 
220
{
 
221
    return gtk_icon_theme_load_icon
 
222
           (
 
223
               gtk_icon_theme_get_default(),
 
224
               iconname,
 
225
               size,
 
226
               (GtkIconLookupFlags)0,
 
227
               NULL
 
228
           );
 
229
}
 
230
 
 
231
 
 
232
// creates either stock or theme icon
 
233
GdkPixbuf *CreateGtkIcon(const char *icon_name,
 
234
                         GtkIconSize stock_size, const wxSize& pixel_size)
 
235
{
 
236
    // try stock GTK+ icon first
 
237
    GdkPixbuf *pixbuf = CreateStockIcon(icon_name, stock_size);
 
238
    if ( pixbuf )
 
239
        return pixbuf;
 
240
 
 
241
    // if that fails, try theme icon
 
242
    wxSize size(pixel_size);
 
243
    if ( pixel_size == wxDefaultSize )
 
244
        gtk_icon_size_lookup(stock_size, &size.x, &size.y);
 
245
    return CreateThemeIcon(icon_name, size.x);
 
246
}
 
247
 
 
248
template<typename SizeType, typename LoaderFunc>
 
249
wxIconBundle DoCreateIconBundle(const char *stockid,
 
250
                                const SizeType *sizes_from,
 
251
                                const SizeType *sizes_to,
 
252
                                LoaderFunc get_icon)
 
253
 
 
254
{
 
255
    wxIconBundle bundle;
 
256
 
 
257
    for ( const SizeType *i = sizes_from; i != sizes_to; ++i )
 
258
    {
 
259
        GdkPixbuf *pixbuf = get_icon(stockid, *i);
 
260
        if ( !pixbuf )
 
261
            continue;
 
262
 
 
263
        wxIcon icon;
 
264
        icon.CopyFromBitmap(wxBitmap(pixbuf));
 
265
        bundle.AddIcon(icon);
 
266
    }
 
267
 
 
268
    return bundle;
 
269
}
 
270
 
 
271
} // anonymous namespace
 
272
 
 
273
wxBitmap wxGTK2ArtProvider::CreateBitmap(const wxArtID& id,
 
274
                                         const wxArtClient& client,
 
275
                                         const wxSize& size)
 
276
{
 
277
    const wxString stockid = wxArtIDToStock(id);
 
278
 
 
279
    GtkIconSize stocksize = (size == wxDefaultSize) ?
 
280
                                ArtClientToIconSize(client) :
 
281
                                FindClosestIconSize(size);
 
282
    // we must have some size, this is arbitrary
 
283
    if (stocksize == GTK_ICON_SIZE_INVALID)
 
284
        stocksize = GTK_ICON_SIZE_BUTTON;
 
285
 
 
286
    GdkPixbuf *pixbuf = CreateGtkIcon(stockid.utf8_str(), stocksize, size);
 
287
 
 
288
    if (pixbuf && size != wxDefaultSize &&
 
289
        (size.x != gdk_pixbuf_get_width(pixbuf) ||
 
290
         size.y != gdk_pixbuf_get_height(pixbuf)))
 
291
    {
 
292
        GdkPixbuf *p2 = gdk_pixbuf_scale_simple(pixbuf, size.x, size.y,
 
293
                                                GDK_INTERP_BILINEAR);
 
294
        if (p2)
 
295
        {
 
296
            g_object_unref (pixbuf);
 
297
            pixbuf = p2;
 
298
        }
 
299
    }
 
300
 
 
301
    return wxBitmap(pixbuf);
 
302
}
 
303
 
 
304
wxIconBundle
 
305
wxGTK2ArtProvider::CreateIconBundle(const wxArtID& id,
 
306
                                    const wxArtClient& WXUNUSED(client))
 
307
{
 
308
    wxIconBundle bundle;
 
309
    const wxString stockid = wxArtIDToStock(id);
 
310
 
 
311
    // try to load the bundle as stock icon first
 
312
    GtkStyle* style = gtk_widget_get_style(wxGTKPrivate::GetButtonWidget());
 
313
    GtkIconSet* iconset = gtk_style_lookup_icon_set(style, stockid.utf8_str());
 
314
    if ( iconset )
 
315
    {
 
316
        GtkIconSize *sizes;
 
317
        gint n_sizes;
 
318
        gtk_icon_set_get_sizes(iconset, &sizes, &n_sizes);
 
319
        bundle = DoCreateIconBundle
 
320
                              (
 
321
                                  stockid.utf8_str(),
 
322
                                  sizes, sizes + n_sizes,
 
323
                                  &CreateStockIcon
 
324
                              );
 
325
        g_free(sizes);
 
326
        return bundle;
 
327
    }
 
328
 
 
329
    // otherwise try icon themes
 
330
#ifdef __WXGTK26__
 
331
#ifndef __WXGTK3__
 
332
    if ( !gtk_check_version(2,6,0) )
 
333
#endif
 
334
    {
 
335
        gint *sizes = gtk_icon_theme_get_icon_sizes
 
336
                      (
 
337
                          gtk_icon_theme_get_default(),
 
338
                          stockid.utf8_str()
 
339
                      );
 
340
        if ( !sizes )
 
341
            return bundle;
 
342
 
 
343
        gint *last = sizes;
 
344
        while ( *last )
 
345
            last++;
 
346
 
 
347
        bundle = DoCreateIconBundle
 
348
                              (
 
349
                                  stockid.utf8_str(),
 
350
                                  sizes, last,
 
351
                                  &CreateThemeIcon
 
352
                              );
 
353
        g_free(sizes);
 
354
    }
 
355
#endif // __WXGTK26__
 
356
 
 
357
    return bundle;
 
358
}
 
359
 
 
360
// ----------------------------------------------------------------------------
 
361
// wxArtProvider::GetNativeSizeHint()
 
362
// ----------------------------------------------------------------------------
 
363
 
 
364
/*static*/
 
365
wxSize wxArtProvider::GetNativeSizeHint(const wxArtClient& client)
 
366
{
 
367
    // Gtk has specific sizes for each client, see artgtk.cpp
 
368
    GtkIconSize gtk_size = ArtClientToIconSize(client);
 
369
    // no size hints for this client
 
370
    if (gtk_size == GTK_ICON_SIZE_INVALID)
 
371
        return wxDefaultSize;
 
372
    gint width, height;
 
373
    gtk_icon_size_lookup( gtk_size, &width, &height);
 
374
    return wxSize(width, height);
 
375
}