1 ///////////////////////////////////////////////////////////////////////////// 
   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 #if defined(__WXGTK20__) && !defined(__WXUNIVERSAL__) 
  25 #include "wx/artprov.h" 
  26 #include "wx/module.h" 
  27 #include "wx/gtk/private.h" 
  31 // compatibility with older GTK+ versions: 
  32 #ifndef GTK_STOCK_FILE 
  33     #define GTK_STOCK_FILE "gtk-file" 
  35 #ifndef GTK_STOCK_DIRECTORY 
  36     #define GTK_STOCK_DIRECTORY "gtk-directory" 
  40 // ---------------------------------------------------------------------------- 
  42 // ---------------------------------------------------------------------------- 
  44 class wxGTK2ArtProvider 
: public wxArtProvider
 
  47     virtual wxBitmap 
CreateBitmap(const wxArtID
& id
, const wxArtClient
& client
, 
  51 /*static*/ void wxArtProvider::InitNativeProvider() 
  53     wxArtProvider::PushProvider(new wxGTK2ArtProvider
); 
  56 // ---------------------------------------------------------------------------- 
  57 // CreateBitmap routine 
  58 // ---------------------------------------------------------------------------- 
  60 static const char *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,                             ) 
  92     ART(wxART_FOLDER
,                              GTK_STOCK_DIRECTORY
) 
  93     ART(wxART_FOLDER_OPEN
,                         GTK_STOCK_DIRECTORY
) 
  95     //ART(wxART_GO_DIR_UP,                           ) 
  96     ART(wxART_EXECUTABLE_FILE
,                     GTK_STOCK_EXECUTE
) 
  97     ART(wxART_NORMAL_FILE
,                         GTK_STOCK_FILE
) 
  98     ART(wxART_TICK_MARK
,                           GTK_STOCK_APPLY
) 
  99     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_QUIT
,                                GTK_STOCK_QUIT
) 
 121     ART(wxART_FIND
,                                GTK_STOCK_FIND
) 
 122     ART(wxART_FIND_AND_REPLACE
,                    GTK_STOCK_FIND_AND_REPLACE
) 
 130 GtkIconSize 
wxArtClientToIconSize(const wxArtClient
& client
) 
 132     if (client 
== wxART_TOOLBAR
) 
 133         return GTK_ICON_SIZE_LARGE_TOOLBAR
; 
 134     else if (client 
== wxART_MENU
) 
 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 static 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
; 
 192 static GtkStyle 
*gs_gtkStyle 
= NULL
; 
 194 static GdkPixbuf 
*CreateStockIcon(const char *stockid
, GtkIconSize size
) 
 196     // FIXME: This code is not 100% correct, because stock pixmap are 
 197     //        context-dependent and may be affected by theme engine, the 
 198     //        correct value can only be obtained for given GtkWidget object. 
 200     //        Fool-proof implementation of stock bitmaps would extend wxBitmap 
 201     //        with "stock-id" representation (in addition to pixmap and pixbuf 
 202     //        ones) and would convert it to pixbuf when rendered. 
 204     if (gs_gtkStyle 
== NULL
) 
 206         GtkWidget 
*widget 
= gtk_button_new(); 
 207         gs_gtkStyle 
= gtk_rc_get_style(widget
); 
 208         wxASSERT( gs_gtkStyle 
!= NULL 
); 
 209         g_object_ref(G_OBJECT(gs_gtkStyle
)); 
 210         gtk_widget_destroy(widget
); 
 213     GtkIconSet 
*iconset 
= gtk_style_lookup_icon_set(gs_gtkStyle
, stockid
); 
 218     return gtk_icon_set_render_icon(iconset
, gs_gtkStyle
, 
 219                                     gtk_widget_get_default_direction(), 
 220                                     GTK_STATE_NORMAL
, size
, NULL
, NULL
); 
 224 static GdkPixbuf 
*CreateThemeIcon(const char *iconname
, 
 225                                   GtkIconSize iconsize
, const wxSize
& sz
) 
 228     if (size 
== wxDefaultSize
) 
 230         gtk_icon_size_lookup(iconsize
, &size
.x
, &size
.y
); 
 233     return gtk_icon_theme_load_icon( 
 234                     gtk_icon_theme_get_default(), 
 237                     (GtkIconLookupFlags
)0, NULL
); 
 241 wxBitmap 
wxGTK2ArtProvider::CreateBitmap(const wxArtID
& id
, 
 242                                          const wxArtClient
& client
, 
 245     wxCharBuffer stockid 
= wxArtIDToStock(id
); 
 246     GtkIconSize stocksize 
= (size 
== wxDefaultSize
) ? 
 247                                 wxArtClientToIconSize(client
) : 
 248                                 FindClosestIconSize(size
); 
 250     // we must have some size, this is arbitrary 
 251     if (stocksize 
== GTK_ICON_SIZE_INVALID
) 
 252         stocksize 
= GTK_ICON_SIZE_BUTTON
; 
 254     // allow passing GTK+ stock IDs to wxArtProvider: 
 256         stockid 
= id
.ToAscii(); 
 258     GdkPixbuf 
*pixbuf 
= CreateStockIcon(stockid
, stocksize
); 
 261     if (!gtk_check_version(2,4,0)) 
 264             pixbuf 
= CreateThemeIcon(stockid
, stocksize
, size
); 
 268     if (pixbuf 
&& size 
!= wxDefaultSize 
&& 
 269         (size
.x 
!= gdk_pixbuf_get_width(pixbuf
) || 
 270          size
.y 
!= gdk_pixbuf_get_height(pixbuf
))) 
 272         GdkPixbuf 
*p2 
= gdk_pixbuf_scale_simple(pixbuf
, size
.x
, size
.y
, 
 273                                                 GDK_INTERP_BILINEAR
); 
 276             gdk_pixbuf_unref(pixbuf
); 
 285     bmp
.SetWidth(gdk_pixbuf_get_width(pixbuf
)); 
 286     bmp
.SetHeight(gdk_pixbuf_get_height(pixbuf
)); 
 287     bmp
.SetPixbuf(pixbuf
); 
 292 // ---------------------------------------------------------------------------- 
 294 // ---------------------------------------------------------------------------- 
 296 class wxArtGtkModule
: public wxModule
 
 299     bool OnInit() { return true; } 
 304             g_object_unref(G_OBJECT(gs_gtkStyle
)); 
 309     DECLARE_DYNAMIC_CLASS(wxArtGtkModule
) 
 312 IMPLEMENT_DYNAMIC_CLASS(wxArtGtkModule
, wxModule
) 
 314 #endif // defined(__WXGTK20__) && !defined(__WXUNIVERSAL__)