1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/artstd.cpp 
   3 // Purpose:     stock wxArtProvider instance with native GTK+ stock icons 
   4 // Author:      Vaclav Slavik 
   8 // Copyright:   (c) Vaclav Slavik, 2004 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // --------------------------------------------------------------------------- 
  14 // --------------------------------------------------------------------------- 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  19 #if defined(__BORLANDC__) 
  23 #include "wx/artprov.h" 
  24 #include "wx/gtk/private.h" 
  26 // compatibility with older GTK+ versions: 
  27 #ifndef GTK_STOCK_FILE 
  28     #define GTK_STOCK_FILE "gtk-file" 
  30 #ifndef GTK_STOCK_DIRECTORY 
  31     #define GTK_STOCK_DIRECTORY "gtk-directory" 
  35 // ---------------------------------------------------------------------------- 
  37 // ---------------------------------------------------------------------------- 
  39 class wxGTK2ArtProvider 
: public wxArtProvider
 
  42     virtual wxBitmap 
CreateBitmap(const wxArtID
& id
, const wxArtClient
& client
, 
  44     virtual wxIconBundle 
CreateIconBundle(const wxArtID
& id
, 
  45                                           const wxArtClient
& client
); 
  48 /*static*/ void wxArtProvider::InitNativeProvider() 
  50     Push(new wxGTK2ArtProvider
); 
  53 // ---------------------------------------------------------------------------- 
  54 // CreateBitmap routine 
  55 // ---------------------------------------------------------------------------- 
  60 wxString 
wxArtIDToStock(const wxArtID
& id
) 
  62     #define ART(wxid, gtkid) \ 
  63            if (id == wxid) return gtkid; 
  65     ART(wxART_ERROR
,                               GTK_STOCK_DIALOG_ERROR
) 
  66     ART(wxART_INFORMATION
,                         GTK_STOCK_DIALOG_INFO
) 
  67     ART(wxART_WARNING
,                             GTK_STOCK_DIALOG_WARNING
) 
  68     ART(wxART_QUESTION
,                            GTK_STOCK_DIALOG_QUESTION
) 
  70     //ART(wxART_HELP_SIDE_PANEL,                     ) 
  71     ART(wxART_HELP_SETTINGS
,                       GTK_STOCK_SELECT_FONT
) 
  72     //ART(wxART_HELP_BOOK,                           ) 
  73     ART(wxART_HELP_FOLDER
,                         GTK_STOCK_DIRECTORY
) 
  74     ART(wxART_HELP_PAGE
,                           GTK_STOCK_FILE
) 
  75     ART(wxART_MISSING_IMAGE
,                       GTK_STOCK_MISSING_IMAGE
) 
  76     ART(wxART_ADD_BOOKMARK
,                        GTK_STOCK_ADD
) 
  77     ART(wxART_DEL_BOOKMARK
,                        GTK_STOCK_REMOVE
) 
  78     ART(wxART_GO_BACK
,                             GTK_STOCK_GO_BACK
) 
  79     ART(wxART_GO_FORWARD
,                          GTK_STOCK_GO_FORWARD
) 
  80     ART(wxART_GO_UP
,                               GTK_STOCK_GO_UP
) 
  81     ART(wxART_GO_DOWN
,                             GTK_STOCK_GO_DOWN
) 
  82     ART(wxART_GO_TO_PARENT
,                        GTK_STOCK_GO_UP
) 
  83     ART(wxART_GO_HOME
,                             GTK_STOCK_HOME
) 
  84     ART(wxART_FILE_OPEN
,                           GTK_STOCK_OPEN
) 
  85     ART(wxART_PRINT
,                               GTK_STOCK_PRINT
) 
  86     ART(wxART_HELP
,                                GTK_STOCK_HELP
) 
  87     ART(wxART_TIP
,                                 GTK_STOCK_DIALOG_INFO
) 
  88     //ART(wxART_REPORT_VIEW,                         ) 
  89     //ART(wxART_LIST_VIEW,                           ) 
  90     //ART(wxART_NEW_DIR,                             ) 
  91     ART(wxART_FOLDER
,                              GTK_STOCK_DIRECTORY
) 
  92     ART(wxART_FOLDER_OPEN
,                         GTK_STOCK_DIRECTORY
) 
  93     //ART(wxART_GO_DIR_UP,                           ) 
  94     ART(wxART_EXECUTABLE_FILE
,                     GTK_STOCK_EXECUTE
) 
  95     ART(wxART_NORMAL_FILE
,                         GTK_STOCK_FILE
) 
  96     ART(wxART_TICK_MARK
,                           GTK_STOCK_APPLY
) 
  97     ART(wxART_CROSS_MARK
,                          GTK_STOCK_CANCEL
) 
  99     ART(wxART_FLOPPY
,                              GTK_STOCK_FLOPPY
) 
 100     ART(wxART_CDROM
,                               GTK_STOCK_CDROM
) 
 101     ART(wxART_HARDDISK
,                            GTK_STOCK_HARDDISK
) 
 102     ART(wxART_REMOVABLE
,                           GTK_STOCK_HARDDISK
) 
 104     ART(wxART_FILE_SAVE
,                           GTK_STOCK_SAVE
) 
 105     ART(wxART_FILE_SAVE_AS
,                        GTK_STOCK_SAVE_AS
) 
 107     ART(wxART_COPY
,                                GTK_STOCK_COPY
) 
 108     ART(wxART_CUT
,                                 GTK_STOCK_CUT
) 
 109     ART(wxART_PASTE
,                               GTK_STOCK_PASTE
) 
 110     ART(wxART_DELETE
,                              GTK_STOCK_DELETE
) 
 111     ART(wxART_NEW
,                                 GTK_STOCK_NEW
) 
 113     ART(wxART_UNDO
,                                GTK_STOCK_UNDO
) 
 114     ART(wxART_REDO
,                                GTK_STOCK_REDO
) 
 116     ART(wxART_CLOSE
,                               GTK_STOCK_CLOSE
) 
 117     ART(wxART_QUIT
,                                GTK_STOCK_QUIT
) 
 119     ART(wxART_FIND
,                                GTK_STOCK_FIND
) 
 120     ART(wxART_FIND_AND_REPLACE
,                    GTK_STOCK_FIND_AND_REPLACE
) 
 124     // allow passing GTK+ stock IDs to wxArtProvider -- if a recognized wx 
 125     // ID wasn't found, pass it to GTK+ in the hope it is a GTK+ or theme 
 130 GtkIconSize 
ArtClientToIconSize(const wxArtClient
& client
) 
 132     if (client 
== wxART_TOOLBAR
) 
 133         return GTK_ICON_SIZE_LARGE_TOOLBAR
; 
 134     else if (client 
== wxART_MENU 
|| client 
== wxART_FRAME_ICON
) 
 135         return GTK_ICON_SIZE_MENU
; 
 136     else if (client 
== wxART_CMN_DIALOG 
|| client 
== wxART_MESSAGE_BOX
) 
 137         return GTK_ICON_SIZE_DIALOG
; 
 138     else if (client 
== wxART_BUTTON
) 
 139         return GTK_ICON_SIZE_BUTTON
; 
 141         return GTK_ICON_SIZE_INVALID
; // this is arbitrary 
 144 GtkIconSize 
FindClosestIconSize(const wxSize
& size
) 
 151     } s_sizes
[NUM_SIZES
]; 
 152     static bool s_sizesInitialized 
= false; 
 154     if (!s_sizesInitialized
) 
 156         s_sizes
[0].icon 
= GTK_ICON_SIZE_MENU
; 
 157         s_sizes
[1].icon 
= GTK_ICON_SIZE_SMALL_TOOLBAR
; 
 158         s_sizes
[2].icon 
= GTK_ICON_SIZE_LARGE_TOOLBAR
; 
 159         s_sizes
[3].icon 
= GTK_ICON_SIZE_BUTTON
; 
 160         s_sizes
[4].icon 
= GTK_ICON_SIZE_DND
; 
 161         s_sizes
[5].icon 
= GTK_ICON_SIZE_DIALOG
; 
 162         for (size_t i 
= 0; i 
< NUM_SIZES
; i
++) 
 164             gtk_icon_size_lookup(s_sizes
[i
].icon
, 
 165                                  &s_sizes
[i
].x
, &s_sizes
[i
].y
); 
 167         s_sizesInitialized 
= true; 
 170     GtkIconSize best 
= GTK_ICON_SIZE_DIALOG
; // presumably largest 
 171     unsigned distance 
= INT_MAX
; 
 172     for (size_t i 
= 0; i 
< NUM_SIZES
; i
++) 
 174         // only use larger bitmaps, scaling down looks better than scaling up: 
 175         if (size
.x 
> s_sizes
[i
].x 
|| size
.y 
> s_sizes
[i
].y
) 
 178         unsigned dist 
= (size
.x 
- s_sizes
[i
].x
) * (size
.x 
- s_sizes
[i
].x
) + 
 179                         (size
.y 
- s_sizes
[i
].y
) * (size
.y 
- s_sizes
[i
].y
); 
 181             return s_sizes
[i
].icon
; 
 182         else if (dist 
< distance
) 
 185             best 
= s_sizes
[i
].icon
; 
 191 GdkPixbuf 
*CreateStockIcon(const char *stockid
, GtkIconSize size
) 
 193     // FIXME: This code is not 100% correct, because stock pixmap are 
 194     //        context-dependent and may be affected by theme engine, the 
 195     //        correct value can only be obtained for given GtkWidget object. 
 197     //        Fool-proof implementation of stock bitmaps would extend wxBitmap 
 198     //        with "stock-id" representation (in addition to pixmap and pixbuf 
 199     //        ones) and would convert it to pixbuf when rendered. 
 201     GtkStyle
* style 
= wxGTKPrivate::GetButtonWidget()->style
; 
 202     GtkIconSet
* iconset 
= gtk_style_lookup_icon_set(style
, stockid
); 
 207     return gtk_icon_set_render_icon(iconset
, style
, 
 208                                     gtk_widget_get_default_direction(), 
 209                                     GTK_STATE_NORMAL
, size
, NULL
, NULL
); 
 212 GdkPixbuf 
*CreateThemeIcon(const char *iconname
, int size
) 
 214     return gtk_icon_theme_load_icon
 
 216                gtk_icon_theme_get_default(), 
 219                (GtkIconLookupFlags
)0, 
 225 // creates either stock or theme icon 
 226 GdkPixbuf 
*CreateGtkIcon(const char *icon_name
, 
 227                          GtkIconSize stock_size
, const wxSize
& pixel_size
) 
 229     // try stock GTK+ icon first 
 230     GdkPixbuf 
*pixbuf 
= CreateStockIcon(icon_name
, stock_size
); 
 234     // if that fails, try theme icon 
 235     wxSize 
size(pixel_size
); 
 236     if ( pixel_size 
== wxDefaultSize 
) 
 237         gtk_icon_size_lookup(stock_size
, &size
.x
, &size
.y
); 
 238     return CreateThemeIcon(icon_name
, size
.x
); 
 241 template<typename SizeType
, typename LoaderFunc
> 
 242 wxIconBundle 
DoCreateIconBundle(const char *stockid
, 
 243                                 const SizeType 
*sizes_from
, 
 244                                 const SizeType 
*sizes_to
, 
 250     for ( const SizeType 
*i 
= sizes_from
; i 
!= sizes_to
; ++i 
) 
 252         GdkPixbuf 
*pixbuf 
= get_icon(stockid
, *i
); 
 257         icon
.SetPixbuf(pixbuf
); 
 258         bundle
.AddIcon(icon
); 
 264 } // anonymous namespace 
 266 wxBitmap 
wxGTK2ArtProvider::CreateBitmap(const wxArtID
& id
, 
 267                                          const wxArtClient
& client
, 
 270     const wxString stockid 
= wxArtIDToStock(id
); 
 272     GtkIconSize stocksize 
= (size 
== wxDefaultSize
) ? 
 273                                 ArtClientToIconSize(client
) : 
 274                                 FindClosestIconSize(size
); 
 275     // we must have some size, this is arbitrary 
 276     if (stocksize 
== GTK_ICON_SIZE_INVALID
) 
 277         stocksize 
= GTK_ICON_SIZE_BUTTON
; 
 279     GdkPixbuf 
*pixbuf 
= CreateGtkIcon(stockid
.utf8_str(), stocksize
, size
); 
 281     if (pixbuf 
&& size 
!= wxDefaultSize 
&& 
 282         (size
.x 
!= gdk_pixbuf_get_width(pixbuf
) || 
 283          size
.y 
!= gdk_pixbuf_get_height(pixbuf
))) 
 285         GdkPixbuf 
*p2 
= gdk_pixbuf_scale_simple(pixbuf
, size
.x
, size
.y
, 
 286                                                 GDK_INTERP_BILINEAR
); 
 289             g_object_unref (pixbuf
); 
 296         bmp
.SetPixbuf(pixbuf
); 
 302 wxGTK2ArtProvider::CreateIconBundle(const wxArtID
& id
, 
 303                                     const wxArtClient
& WXUNUSED(client
)) 
 305     const wxString stockid 
= wxArtIDToStock(id
); 
 307     // try to load the bundle as stock icon first 
 308     GtkStyle
* style 
= wxGTKPrivate::GetButtonWidget()->style
; 
 309     GtkIconSet
* iconset 
= gtk_style_lookup_icon_set(style
, stockid
.utf8_str()); 
 314         gtk_icon_set_get_sizes(iconset
, &sizes
, &n_sizes
); 
 315         wxIconBundle bundle 
= DoCreateIconBundle
 
 318                                   sizes
, sizes 
+ n_sizes
, 
 325     // otherwise try icon themes 
 327     if ( !gtk_check_version(2,6,0) ) 
 329         gint 
*sizes 
= gtk_icon_theme_get_icon_sizes
 
 331                           gtk_icon_theme_get_default(), 
 335             return wxNullIconBundle
; 
 341         wxIconBundle bundle 
= DoCreateIconBundle
 
 350 #endif // __WXGTK26__ 
 352     return wxNullIconBundle
; 
 355 // ---------------------------------------------------------------------------- 
 356 // wxArtProvider::GetNativeSizeHint() 
 357 // ---------------------------------------------------------------------------- 
 360 wxSize 
wxArtProvider::GetNativeSizeHint(const wxArtClient
& client
) 
 362     // Gtk has specific sizes for each client, see artgtk.cpp 
 363     GtkIconSize gtk_size 
= ArtClientToIconSize(client
); 
 364     // no size hints for this client 
 365     if (gtk_size 
== GTK_ICON_SIZE_INVALID
) 
 366         return wxDefaultSize
; 
 368     gtk_icon_size_lookup( gtk_size
, &width
, &height
); 
 369     return wxSize(width
, height
);