1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/artgtk.cpp
3 // Purpose: stock wxArtProvider instance with native GTK+ stock icons
4 // Author: Vaclav Slavik
7 // Copyright: (c) Vaclav Slavik, 2004
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ---------------------------------------------------------------------------
13 // ---------------------------------------------------------------------------
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
18 #if defined(__BORLANDC__)
22 #include "wx/artprov.h"
25 #include "wx/gtk/private.h"
27 // compatibility with older GTK+ versions:
28 #ifndef GTK_STOCK_FILE
29 #define GTK_STOCK_FILE "gtk-file"
31 #ifndef GTK_STOCK_DIRECTORY
32 #define GTK_STOCK_DIRECTORY "gtk-directory"
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 class wxGTK2ArtProvider
: public wxArtProvider
43 virtual wxBitmap
CreateBitmap(const wxArtID
& id
, const wxArtClient
& client
,
45 virtual wxIconBundle
CreateIconBundle(const wxArtID
& id
,
46 const wxArtClient
& client
);
49 /*static*/ void wxArtProvider::InitNativeProvider()
51 PushBack(new wxGTK2ArtProvider
);
54 // ----------------------------------------------------------------------------
55 // CreateBitmap routine
56 // ----------------------------------------------------------------------------
61 wxString
wxArtIDToStock(const wxArtID
& id
)
63 #define ART(wxid, gtkid) \
64 if (id == wxid) return gtkid;
66 ART(wxART_ERROR
, GTK_STOCK_DIALOG_ERROR
)
67 ART(wxART_INFORMATION
, GTK_STOCK_DIALOG_INFO
)
68 ART(wxART_WARNING
, GTK_STOCK_DIALOG_WARNING
)
69 ART(wxART_QUESTION
, GTK_STOCK_DIALOG_QUESTION
)
71 //ART(wxART_HELP_SIDE_PANEL, )
72 ART(wxART_HELP_SETTINGS
, GTK_STOCK_SELECT_FONT
)
73 //ART(wxART_HELP_BOOK, )
74 ART(wxART_HELP_FOLDER
, GTK_STOCK_DIRECTORY
)
75 ART(wxART_HELP_PAGE
, GTK_STOCK_FILE
)
76 ART(wxART_MISSING_IMAGE
, GTK_STOCK_MISSING_IMAGE
)
77 ART(wxART_ADD_BOOKMARK
, GTK_STOCK_ADD
)
78 ART(wxART_DEL_BOOKMARK
, GTK_STOCK_REMOVE
)
79 ART(wxART_GO_BACK
, GTK_STOCK_GO_BACK
)
80 ART(wxART_GO_FORWARD
, GTK_STOCK_GO_FORWARD
)
81 ART(wxART_GO_UP
, GTK_STOCK_GO_UP
)
82 ART(wxART_GO_DOWN
, GTK_STOCK_GO_DOWN
)
83 ART(wxART_GO_TO_PARENT
, GTK_STOCK_GO_UP
)
84 ART(wxART_GO_HOME
, GTK_STOCK_HOME
)
85 ART(wxART_GOTO_FIRST
, GTK_STOCK_GOTO_FIRST
)
86 ART(wxART_GOTO_LAST
, GTK_STOCK_GOTO_LAST
)
87 ART(wxART_FILE_OPEN
, GTK_STOCK_OPEN
)
88 ART(wxART_PRINT
, GTK_STOCK_PRINT
)
89 ART(wxART_HELP
, GTK_STOCK_HELP
)
90 ART(wxART_TIP
, GTK_STOCK_DIALOG_INFO
)
91 //ART(wxART_REPORT_VIEW, )
92 //ART(wxART_LIST_VIEW, )
93 //ART(wxART_NEW_DIR, )
94 ART(wxART_FOLDER
, GTK_STOCK_DIRECTORY
)
95 ART(wxART_FOLDER_OPEN
, GTK_STOCK_DIRECTORY
)
96 //ART(wxART_GO_DIR_UP, )
97 ART(wxART_EXECUTABLE_FILE
, GTK_STOCK_EXECUTE
)
98 ART(wxART_NORMAL_FILE
, GTK_STOCK_FILE
)
99 ART(wxART_TICK_MARK
, GTK_STOCK_APPLY
)
100 ART(wxART_CROSS_MARK
, GTK_STOCK_CANCEL
)
102 ART(wxART_FLOPPY
, GTK_STOCK_FLOPPY
)
103 ART(wxART_CDROM
, GTK_STOCK_CDROM
)
104 ART(wxART_HARDDISK
, GTK_STOCK_HARDDISK
)
105 ART(wxART_REMOVABLE
, GTK_STOCK_HARDDISK
)
107 ART(wxART_FILE_SAVE
, GTK_STOCK_SAVE
)
108 ART(wxART_FILE_SAVE_AS
, GTK_STOCK_SAVE_AS
)
110 ART(wxART_COPY
, GTK_STOCK_COPY
)
111 ART(wxART_CUT
, GTK_STOCK_CUT
)
112 ART(wxART_PASTE
, GTK_STOCK_PASTE
)
113 ART(wxART_DELETE
, GTK_STOCK_DELETE
)
114 ART(wxART_NEW
, GTK_STOCK_NEW
)
116 ART(wxART_UNDO
, GTK_STOCK_UNDO
)
117 ART(wxART_REDO
, GTK_STOCK_REDO
)
119 ART(wxART_PLUS
, GTK_STOCK_ADD
)
120 ART(wxART_MINUS
, GTK_STOCK_REMOVE
)
122 ART(wxART_CLOSE
, GTK_STOCK_CLOSE
)
123 ART(wxART_QUIT
, GTK_STOCK_QUIT
)
125 ART(wxART_FIND
, GTK_STOCK_FIND
)
126 ART(wxART_FIND_AND_REPLACE
, GTK_STOCK_FIND_AND_REPLACE
)
130 // allow passing GTK+ stock IDs to wxArtProvider -- if a recognized wx
131 // ID wasn't found, pass it to GTK+ in the hope it is a GTK+ or theme
136 GtkIconSize
ArtClientToIconSize(const wxArtClient
& client
)
138 if (client
== wxART_TOOLBAR
)
139 return GTK_ICON_SIZE_LARGE_TOOLBAR
;
140 else if (client
== wxART_MENU
|| client
== wxART_FRAME_ICON
)
141 return GTK_ICON_SIZE_MENU
;
142 else if (client
== wxART_CMN_DIALOG
|| client
== wxART_MESSAGE_BOX
)
143 return GTK_ICON_SIZE_DIALOG
;
144 else if (client
== wxART_BUTTON
)
145 return GTK_ICON_SIZE_BUTTON
;
147 return GTK_ICON_SIZE_INVALID
; // this is arbitrary
150 GtkIconSize
FindClosestIconSize(const wxSize
& size
)
157 } s_sizes
[NUM_SIZES
];
158 static bool s_sizesInitialized
= false;
160 if (!s_sizesInitialized
)
162 s_sizes
[0].icon
= GTK_ICON_SIZE_MENU
;
163 s_sizes
[1].icon
= GTK_ICON_SIZE_SMALL_TOOLBAR
;
164 s_sizes
[2].icon
= GTK_ICON_SIZE_LARGE_TOOLBAR
;
165 s_sizes
[3].icon
= GTK_ICON_SIZE_BUTTON
;
166 s_sizes
[4].icon
= GTK_ICON_SIZE_DND
;
167 s_sizes
[5].icon
= GTK_ICON_SIZE_DIALOG
;
168 for (size_t i
= 0; i
< NUM_SIZES
; i
++)
170 gtk_icon_size_lookup(s_sizes
[i
].icon
,
171 &s_sizes
[i
].x
, &s_sizes
[i
].y
);
173 s_sizesInitialized
= true;
176 GtkIconSize best
= GTK_ICON_SIZE_DIALOG
; // presumably largest
177 unsigned distance
= INT_MAX
;
178 for (size_t i
= 0; i
< NUM_SIZES
; i
++)
180 // only use larger bitmaps, scaling down looks better than scaling up:
181 if (size
.x
> s_sizes
[i
].x
|| size
.y
> s_sizes
[i
].y
)
184 unsigned dist
= (size
.x
- s_sizes
[i
].x
) * (size
.x
- s_sizes
[i
].x
) +
185 (size
.y
- s_sizes
[i
].y
) * (size
.y
- s_sizes
[i
].y
);
187 return s_sizes
[i
].icon
;
188 else if (dist
< distance
)
191 best
= s_sizes
[i
].icon
;
197 GdkPixbuf
*CreateStockIcon(const char *stockid
, GtkIconSize size
)
199 // FIXME: This code is not 100% correct, because stock pixmap are
200 // context-dependent and may be affected by theme engine, the
201 // correct value can only be obtained for given GtkWidget object.
203 // Fool-proof implementation of stock bitmaps would extend wxBitmap
204 // with "stock-id" representation (in addition to pixmap and pixbuf
205 // ones) and would convert it to pixbuf when rendered.
207 GtkWidget
* widget
= wxGTKPrivate::GetButtonWidget();
209 GtkStyleContext
* sc
= gtk_widget_get_style_context(widget
);
210 GtkIconSet
* iconset
= gtk_style_context_lookup_icon_set(sc
, stockid
);
211 GdkPixbuf
* pixbuf
= NULL
;
213 pixbuf
= gtk_icon_set_render_icon_pixbuf(iconset
, sc
, size
);
216 GtkStyle
* style
= gtk_widget_get_style(widget
);
217 GtkIconSet
* iconset
= gtk_style_lookup_icon_set(style
, stockid
);
222 return gtk_icon_set_render_icon(iconset
, style
,
223 gtk_widget_get_default_direction(),
224 GTK_STATE_NORMAL
, size
, NULL
, NULL
);
228 GdkPixbuf
*CreateThemeIcon(const char *iconname
, int size
)
230 return gtk_icon_theme_load_icon
232 gtk_icon_theme_get_default(),
235 (GtkIconLookupFlags
)0,
241 // creates either stock or theme icon
242 GdkPixbuf
*CreateGtkIcon(const char *icon_name
,
243 GtkIconSize stock_size
, const wxSize
& pixel_size
)
245 // try stock GTK+ icon first
246 GdkPixbuf
*pixbuf
= CreateStockIcon(icon_name
, stock_size
);
250 // if that fails, try theme icon
251 wxSize
size(pixel_size
);
252 if ( pixel_size
== wxDefaultSize
)
253 gtk_icon_size_lookup(stock_size
, &size
.x
, &size
.y
);
254 return CreateThemeIcon(icon_name
, size
.x
);
257 template<typename SizeType
, typename LoaderFunc
>
258 wxIconBundle
DoCreateIconBundle(const char *stockid
,
259 const SizeType
*sizes_from
,
260 const SizeType
*sizes_to
,
266 for ( const SizeType
*i
= sizes_from
; i
!= sizes_to
; ++i
)
268 GdkPixbuf
*pixbuf
= get_icon(stockid
, *i
);
273 icon
.CopyFromBitmap(wxBitmap(pixbuf
));
274 bundle
.AddIcon(icon
);
280 } // anonymous namespace
282 wxBitmap
wxGTK2ArtProvider::CreateBitmap(const wxArtID
& id
,
283 const wxArtClient
& client
,
286 const wxString stockid
= wxArtIDToStock(id
);
288 GtkIconSize stocksize
= (size
== wxDefaultSize
) ?
289 ArtClientToIconSize(client
) :
290 FindClosestIconSize(size
);
291 // we must have some size, this is arbitrary
292 if (stocksize
== GTK_ICON_SIZE_INVALID
)
293 stocksize
= GTK_ICON_SIZE_BUTTON
;
295 GdkPixbuf
*pixbuf
= CreateGtkIcon(stockid
.utf8_str(), stocksize
, size
);
297 if (pixbuf
&& size
!= wxDefaultSize
&&
298 (size
.x
!= gdk_pixbuf_get_width(pixbuf
) ||
299 size
.y
!= gdk_pixbuf_get_height(pixbuf
)))
301 GdkPixbuf
*p2
= gdk_pixbuf_scale_simple(pixbuf
, size
.x
, size
.y
,
302 GDK_INTERP_BILINEAR
);
305 g_object_unref (pixbuf
);
310 return wxBitmap(pixbuf
);
314 wxGTK2ArtProvider::CreateIconBundle(const wxArtID
& id
,
315 const wxArtClient
& WXUNUSED(client
))
318 const wxString stockid
= wxArtIDToStock(id
);
320 // try to load the bundle as stock icon first
321 GtkWidget
* widget
= wxGTKPrivate::GetButtonWidget();
323 GtkStyleContext
* sc
= gtk_widget_get_style_context(widget
);
324 GtkIconSet
* iconset
= gtk_style_context_lookup_icon_set(sc
, stockid
.utf8_str());
326 GtkStyle
* style
= gtk_widget_get_style(widget
);
327 GtkIconSet
* iconset
= gtk_style_lookup_icon_set(style
, stockid
.utf8_str());
333 gtk_icon_set_get_sizes(iconset
, &sizes
, &n_sizes
);
334 bundle
= DoCreateIconBundle
337 sizes
, sizes
+ n_sizes
,
344 // otherwise try icon themes
345 gint
*sizes
= gtk_icon_theme_get_icon_sizes
347 gtk_icon_theme_get_default(),
357 bundle
= DoCreateIconBundle
368 // ----------------------------------------------------------------------------
369 // wxArtProvider::GetNativeSizeHint()
370 // ----------------------------------------------------------------------------
373 wxSize
wxArtProvider::GetNativeSizeHint(const wxArtClient
& client
)
375 // Gtk has specific sizes for each client, see artgtk.cpp
376 GtkIconSize gtk_size
= ArtClientToIconSize(client
);
377 // no size hints for this client
378 if (gtk_size
== GTK_ICON_SIZE_INVALID
)
379 return wxDefaultSize
;
381 gtk_icon_size_lookup( gtk_size
, &width
, &height
);
382 return wxSize(width
, height
);