Hi.
Stock things are not the easiest concept to grasp. They are quite flexible and extendable, but learning curve can be quite steep.
First stock thing that you should know about is
stock item, represented by GtkStockItem. This structure holds stock item's ID and all non-image data that one usually sees on widgets, created from stock. GtkMenuItem's label and accelerator come from this struct for example.
Second stock thing is
stock icon, represented by GtkIconSet and associated ID. As the name of the main structure suggests, this is a set of one or more images that can be used in different situations (for example, icon set that represents "back" icon needs least 2 images: one for LTR locales and one for RTL ones).
The only connection between stock icons and items is their ID. But there is no rule that both stock item and icon must exist for given ID. It is completely valid to have only stock item or only stock icon.
Creating stock items is really simple. Just create GtkStockItem structure, fill it with proper data and call gtk_stock_add() or gtk_stock_add_static().
Creating stock icons can be really simple or quite complex, depending on the requirements. But in any case, you'll need to create your own GtkIconFactory, add it to default list of icon factories that is being searched by theme system and then add icon sets to this factory.
Last thing is to create actual icon set. This is where the bulk of complexity is hidden, because source of images in icon set can be:
- file on disk that is read by icon factory
- GdkPixbuf that is supplied by application
- icon name, in which case image is loaded from icon theme
First two sources are quite easy to set up, but offer little flexibility. Last one would be the preferred way of creating new stock icons, because icon theme authors can override your default icon. (Of course, this is also the most complex way, since you need to work with theme system;)
To give you something to play with, I created simple application that demonstrates much of what I described above:
Code:
#include <gtk/gtk.h>
/* This is usually defined by build system */
#define GETTEXT_PACKAGE "my-sample-stock-app"
/* Define stock items */
static GtkStockItem stock_items[] =
{
{"my-stock-sample1", "My Stock Sample 1", 0, 0, GETTEXT_PACKAGE},
{"my-stock-sample2", "My Stock Sample 2", 0, 0, GETTEXT_PACKAGE},
{"my-stock-sample3", "My Stock Sample 3", 0, 0, GETTEXT_PACKAGE}
};
static void
init_stocks (void)
{
GtkIconFactory *factory;
GtkIconSet *iconset;
GtkIconSource *source;
GdkPixbuf *pixbuf;
char *path;
/* Add our custom stock items */
gtk_stock_add_static (stock_items, G_N_ELEMENTS (stock_items));
/* Init icon factory */
factory = gtk_icon_factory_new ();
gtk_icon_factory_add_default (factory);
/* Create stock icon for "my-stock-sample1" (from file) */
path = g_build_filename (g_get_current_dir (), "night1.png", NULL);
source = gtk_icon_source_new ();
gtk_icon_source_set_filename (source, path);
g_free (path);
iconset = gtk_icon_set_new ();
gtk_icon_set_add_source (iconset, source);
gtk_icon_source_free (source);
gtk_icon_factory_add (factory, "my-stock-sample1", iconset);
gtk_icon_set_unref (iconset);
/* Create stock icon for "my-stock-sample2" (from pixbuf) */
path = g_build_filename (g_get_current_dir (), "night2.png", NULL);
pixbuf = gdk_pixbuf_new_from_file (path, NULL);
g_free (path);
iconset = gtk_icon_set_new_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
gtk_icon_factory_add (factory, "my-stock-sample2", iconset);
gtk_icon_set_unref (iconset);
/* Create stock icon for "my-stock-sample3" (from named icon) */
source = gtk_icon_source_new ();
gtk_icon_source_set_icon_name (source, "folder-music");
iconset = gtk_icon_set_new ();
gtk_icon_set_add_source (iconset, source);
gtk_icon_source_free (source);
gtk_icon_factory_add (factory, "my-stock-sample3", iconset);
gtk_icon_set_unref (iconset);
}
int
main (int argc,
char **argv)
{
GtkWidget *window,
*vbox,
*hbox,
*button,
*label;
gtk_init (&argc, &argv);
init_stocks();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", gtk_main_quit, NULL);
vbox = gtk_vbox_new (FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
button = gtk_button_new_from_stock ("my-stock-sample1");
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
label = gtk_label_new ("From filename");
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
button = gtk_button_new_from_stock ("my-stock-sample2");
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
label = gtk_label_new ("From pixbuf");
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
button = gtk_button_new_from_stock ("my-stock-sample3");
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
label = gtk_label_new ("From named icon (theme)");
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
Tadej