/* Stock Item/Icon Browser * * This source code for this demo doesn't demonstrate anything * particularly useful in applications. The purpose of the "demo" is * just to provide a handy place to browse the available stock icons * and stock items. */ #include #include static GtkWidget *window = NULL; typedef struct _StockItemInfo StockItemInfo; struct _StockItemInfo { gchar *id; GtkStockItem item; GdkPixbuf *small_icon; gchar *macro; gchar *accel_str; }; /* Make StockItemInfo a boxed type so we can automatically * manage memory */ #define STOCK_ITEM_INFO_TYPE stock_item_info_get_type () static void stock_item_info_free (StockItemInfo *info) { g_free (info->id); g_free (info->macro); g_free (info->accel_str); if (info->small_icon) g_object_unref (G_OBJECT (info->small_icon)); g_free (info); } static StockItemInfo* stock_item_info_copy (StockItemInfo *src) { StockItemInfo *info; info = g_new (StockItemInfo, 1); info->id = g_strdup (src->id); info->macro = g_strdup (src->macro); info->accel_str = g_strdup (src->accel_str); info->item = src->item; info->small_icon = src->small_icon; if (info->small_icon) g_object_ref (G_OBJECT (info->small_icon)); return info; } static GType stock_item_info_get_type (void) { static GType our_type = 0; if (our_type == 0) our_type = g_boxed_type_register_static ("StockItemInfo", NULL, (GBoxedCopyFunc) stock_item_info_copy, (GBoxedFreeFunc) stock_item_info_free, FALSE); return our_type; } typedef struct _StockItemDisplay StockItemDisplay; struct _StockItemDisplay { GtkWidget *type_label; GtkWidget *macro_label; GtkWidget *id_label; GtkWidget *label_accel_label; GtkWidget *icon_image; }; /* columns in the tree model */ enum { COLUMN_ICON_MACRO, COLUMN_LABEL, COLUMN_ACCEL, COLUMN_ID }; static gchar* id_to_macro (const gchar *id) { GString *macro; const gchar *cp; gchar *p; /* gtk-foo -> GTK_STOCK_FOO */ cp = id; while (*cp && *cp != '-') ++cp; if (*cp == '\0') return g_strdup ("??UNKNOWN??"); macro = g_string_new (NULL); g_string_append_len (macro, id, cp - id); g_string_append (macro, "_STOCK"); g_string_append (macro, cp); p = macro->str; while (*p) { if (*p == '-') *p = '_'; ++p; } g_strup (macro->str); return g_string_free (macro, FALSE); } static GtkTreeModel* create_model (void) { GtkListStore *store; GSList *ids; GSList *tmp_list; store = gtk_list_store_new_with_types (1, STOCK_ITEM_INFO_TYPE); ids = gtk_stock_list_ids (); ids = g_slist_sort (ids, (GCompareFunc) strcmp); tmp_list = ids; while (tmp_list != NULL) { StockItemInfo info; GtkStockItem item; GtkTreeIter iter; GtkIconSet *icon_set; info.id = tmp_list->data; if (gtk_stock_lookup (info.id, &item)) { info.item = item; } else { info.item.label = NULL; info.item.stock_id = NULL; info.item.modifier = 0; info.item.keyval = 0; info.item.translation_domain = NULL; } /* only show icons for stock IDs that have default icons */ icon_set = gtk_icon_factory_lookup_default (info.id); if (icon_set) { GtkIconSize *sizes = NULL; gint n_sizes = 0; gint i; GtkIconSize size; /* See what sizes this stock icon really exists at */ gtk_icon_set_get_sizes (icon_set, &sizes, &n_sizes); /* Use menu size if it exists, otherwise first size found */ size = sizes[0]; i = 0; while (i < n_sizes) { if (sizes[i] == GTK_ICON_SIZE_MENU) { size = GTK_ICON_SIZE_MENU; break; } ++i; } g_free (sizes); info.small_icon = gtk_widget_render_icon (window, info.id, size, NULL); if (size != GTK_ICON_SIZE_MENU) { /* Make the result the proper size for our thumbnail */ gint w, h; GdkPixbuf *scaled; gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h); scaled = gdk_pixbuf_scale_simple (info.small_icon, w, h, GDK_INTERP_BILINEAR); g_object_unref (G_OBJECT (info.small_icon)); info.small_icon = scaled; } } else info.small_icon = NULL; if (info.item.keyval != 0) { info.accel_str = gtk_accelerator_name (info.item.keyval, info.item.modifier); } else { info.accel_str = g_strdup (""); } info.macro = id_to_macro (info.id); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, &info, -1); g_free (info.macro); g_free (info.accel_str); if (info.small_icon) g_object_unref (G_OBJECT (info.small_icon)); tmp_list = g_slist_next (tmp_list); } g_slist_foreach (ids, (GFunc)g_free, NULL); g_slist_free (ids); return GTK_TREE_MODEL (store); } static void selection_changed (GtkTreeSelection *selection) { GtkTreeView *treeview; StockItemDisplay *display; GtkTreeModel *model; GtkTreeIter iter; treeview = gtk_tree_selection_get_tree_view (selection); display = g_object_get_data (G_OBJECT (treeview), "stock-display"); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { StockItemInfo *info; gchar *str; gtk_tree_model_get (model, &iter, 0, &info, -1); if (info->small_icon && info->item.label) gtk_label_set_text (GTK_LABEL (display->type_label), "Icon and Item"); else if (info->small_icon) gtk_label_set_text (GTK_LABEL (display->type_label), "Icon Only"); else if (info->item.label) gtk_label_set_text (GTK_LABEL (display->type_label), "Item Only"); else gtk_label_set_text (GTK_LABEL (display->type_label), "???????"); gtk_label_set_text (GTK_LABEL (display->macro_label), info->macro); gtk_label_set_text (GTK_LABEL (display->id_label), info->id); if (info->item.label) { str = g_strdup_printf ("%s %s", info->item.label, info->accel_str); gtk_label_set_text_with_mnemonic (GTK_LABEL (display->label_accel_label), str); g_free (str); } else { gtk_label_set_text (GTK_LABEL (display->label_accel_label), ""); } /* The problem here is that some icons don't have SIZE_LARGE_TOOLBAR, * so we get a "missing image" icon... */ if (info->small_icon) gtk_image_set_from_stock (GTK_IMAGE (display->icon_image), info->id, GTK_ICON_SIZE_LARGE_TOOLBAR); else gtk_image_set_from_pixbuf (GTK_IMAGE (display->icon_image), NULL); stock_item_info_free (info); } else { gtk_label_set_text (GTK_LABEL (display->type_label), "No selected item"); gtk_label_set_text (GTK_LABEL (display->macro_label), ""); gtk_label_set_text (GTK_LABEL (display->id_label), ""); gtk_label_set_text (GTK_LABEL (display->label_accel_label), ""); gtk_image_set_from_pixbuf (GTK_IMAGE (display->icon_image), NULL); } } static void macro_set_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { StockItemInfo *info; gtk_tree_model_get (model, iter, 0, &info, -1); g_object_set (GTK_CELL_RENDERER (cell), "text", info->macro, "pixbuf", info->small_icon, NULL); stock_item_info_free (info); } static void id_set_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { StockItemInfo *info; gtk_tree_model_get (model, iter, 0, &info, -1); g_object_set (GTK_CELL_RENDERER (cell), "text", info->id, NULL); stock_item_info_free (info); } static void accel_set_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { StockItemInfo *info; gtk_tree_model_get (model, iter, 0, &info, -1); g_object_set (GTK_CELL_RENDERER (cell), "text", info->accel_str, NULL); stock_item_info_free (info); } static void label_set_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { StockItemInfo *info; gtk_tree_model_get (model, iter, 0, &info, -1); g_object_set (GTK_CELL_RENDERER (cell), "text", info->item.label, NULL); stock_item_info_free (info); } GtkWidget * do_stock_browser (void) { if (!window) { GtkWidget *frame; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *sw; GtkWidget *treeview; GtkWidget *align; GtkTreeModel *model; GtkCellRenderer *cell_renderer; StockItemDisplay *display; GtkTreeSelection *selection; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Stock Icons and Items"); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); gtk_container_set_border_width (GTK_CONTAINER (window), 8); hbox = gtk_hbox_new (FALSE, 8); gtk_container_add (GTK_CONTAINER (window), hbox); sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (hbox), sw, FALSE, FALSE, 0); model = create_model (); treeview = gtk_tree_view_new_with_model (model); g_object_unref (G_OBJECT (model)); gtk_container_add (GTK_CONTAINER (sw), treeview); cell_renderer = gtk_cell_renderer_text_pixbuf_new (); gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1, "Macro", cell_renderer, macro_set_func, NULL, NULL); g_object_unref (G_OBJECT (cell_renderer)); cell_renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1, "Label", cell_renderer, label_set_func, NULL, NULL); gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1, "Accel", cell_renderer, accel_set_func, NULL, NULL); gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1, "ID", cell_renderer, id_set_func, NULL, NULL); g_object_unref (G_OBJECT (cell_renderer)); align = gtk_alignment_new (0.5, 0.0, 0.0, 0.0); gtk_box_pack_end (GTK_BOX (hbox), align, FALSE, FALSE, 0); frame = gtk_frame_new ("Selected Item"); gtk_container_add (GTK_CONTAINER (align), frame); vbox = gtk_vbox_new (FALSE, 8); gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); gtk_container_add (GTK_CONTAINER (frame), vbox); display = g_new (StockItemDisplay, 1); g_object_set_data_full (G_OBJECT (treeview), "stock-display", display, g_free); /* free display with treeview */ display->type_label = gtk_label_new (NULL); display->macro_label = gtk_label_new (NULL); display->id_label = gtk_label_new (NULL); display->label_accel_label = gtk_label_new (NULL); display->icon_image = gtk_image_new_from_pixbuf (NULL); /* empty image */ gtk_box_pack_start (GTK_BOX (vbox), display->type_label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), display->icon_image, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), display->label_accel_label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), display->macro_label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), display->id_label, FALSE, FALSE, 0); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); gtk_tree_selection_set_mode (selection, GTK_TREE_SELECTION_SINGLE); g_signal_connect_data (G_OBJECT (selection), "changed", G_CALLBACK (selection_changed), NULL, NULL, FALSE, FALSE); } if (!GTK_WIDGET_VISIBLE (window)) { gtk_widget_show_all (window); } else { gtk_widget_destroy (window); window = NULL; } return window; }