home *** CD-ROM | disk | FTP | other *** search
/ Freelog 65 / Freelog065.iso / BAS / Bureautique / Gnumeric / gnumeric-1.3.92-rc1.exe / stock_browser.c < prev    next >
C/C++ Source or Header  |  2004-10-15  |  16KB  |  548 lines

  1. /* Stock Item and Icon Browser
  2.  *
  3.  * This source code for this demo doesn't demonstrate anything
  4.  * particularly useful in applications. The purpose of the "demo" is
  5.  * just to provide a handy place to browse the available stock icons
  6.  * and stock items.
  7.  */
  8.  
  9. #include <config.h>
  10. #include <string.h>
  11.  
  12. #include <gtk/gtk.h>
  13.  
  14. static GtkWidget *window = NULL;
  15.  
  16. typedef struct _StockItemInfo StockItemInfo;
  17. struct _StockItemInfo
  18. {
  19.   gchar *id;
  20.   GtkStockItem item;
  21.   GdkPixbuf *small_icon;
  22.   gchar *macro;
  23.   gchar *accel_str;
  24. };
  25.  
  26. /* Make StockItemInfo a boxed type so we can automatically
  27.  * manage memory
  28.  */
  29. #define STOCK_ITEM_INFO_TYPE stock_item_info_get_type ()
  30.  
  31. static void
  32. stock_item_info_free (StockItemInfo *info)
  33. {
  34.   g_free (info->id);
  35.   g_free (info->macro);
  36.   g_free (info->accel_str);
  37.   if (info->small_icon)
  38.     g_object_unref (info->small_icon);
  39.   
  40.   g_free (info);
  41. }
  42.  
  43. static StockItemInfo*
  44. stock_item_info_copy (StockItemInfo *src)
  45. {
  46.   StockItemInfo *info;
  47.  
  48.   info = g_new (StockItemInfo, 1);
  49.   info->id = g_strdup (src->id);
  50.   info->macro = g_strdup (src->macro);
  51.   info->accel_str = g_strdup (src->accel_str);
  52.   
  53.   info->item = src->item;
  54.  
  55.   info->small_icon = src->small_icon;
  56.   if (info->small_icon)
  57.     g_object_ref (info->small_icon);
  58.  
  59.   return info;
  60. }
  61.  
  62. static GType
  63. stock_item_info_get_type (void)
  64. {
  65.   static GType our_type = 0;
  66.   
  67.   if (our_type == 0)
  68.     our_type = g_boxed_type_register_static ("StockItemInfo",
  69.                                              (GBoxedCopyFunc) stock_item_info_copy,
  70.                                              (GBoxedFreeFunc) stock_item_info_free);
  71.  
  72.   return our_type;
  73. }
  74.  
  75. typedef struct _StockItemDisplay StockItemDisplay;
  76. struct _StockItemDisplay
  77. {
  78.   GtkWidget *type_label;
  79.   GtkWidget *macro_label;
  80.   GtkWidget *id_label;
  81.   GtkWidget *label_accel_label;
  82.   GtkWidget *icon_image;
  83. };
  84.  
  85. static gchar*
  86. id_to_macro (const gchar *id)
  87. {
  88.   GString *macro = NULL;
  89.   const gchar *cp;
  90.  
  91.   /* gtk-foo-bar -> GTK_STOCK_FOO_BAR */
  92.  
  93.   macro = g_string_new (NULL);
  94.   
  95.   cp = id;
  96.   
  97.   if (strncmp (cp, "gtk-", 4) == 0)
  98.     {
  99.       g_string_append (macro, "GTK_STOCK_");
  100.       cp += 4;
  101.     }
  102.  
  103.   while (*cp)
  104.     {
  105.       if (*cp == '-')
  106.     g_string_append_c (macro, '_');
  107.       else if (g_ascii_islower (*cp))
  108.     g_string_append_c (macro, g_ascii_toupper (*cp));
  109.       else
  110.     g_string_append_c (macro, *cp);
  111.  
  112.       cp++;
  113.     }
  114.  
  115.   return g_string_free (macro, FALSE);
  116. }
  117.  
  118. static GtkTreeModel*
  119. create_model (void)
  120. {
  121.   GtkListStore *store;
  122.   GSList *ids;
  123.   GSList *tmp_list;
  124.   
  125.   store = gtk_list_store_new (2, STOCK_ITEM_INFO_TYPE, G_TYPE_STRING);
  126.  
  127.   ids = gtk_stock_list_ids ();
  128.   ids = g_slist_sort (ids, (GCompareFunc) strcmp);
  129.   tmp_list = ids;
  130.   while (tmp_list != NULL)
  131.     {
  132.       StockItemInfo info;
  133.       GtkStockItem item;
  134.       GtkTreeIter iter;
  135.       GtkIconSet *icon_set;
  136.       
  137.       info.id = tmp_list->data;
  138.       
  139.       if (gtk_stock_lookup (info.id, &item))
  140.         {
  141.           info.item = item;
  142.         }
  143.       else
  144.         {
  145.           info.item.label = NULL;
  146.           info.item.stock_id = NULL;
  147.           info.item.modifier = 0;
  148.           info.item.keyval = 0;
  149.           info.item.translation_domain = NULL;
  150.         }
  151.  
  152.       /* only show icons for stock IDs that have default icons */
  153.       icon_set = gtk_icon_factory_lookup_default (info.id);
  154.       if (icon_set)
  155.         {
  156.           GtkIconSize *sizes = NULL;
  157.           gint n_sizes = 0;
  158.           gint i;
  159.           GtkIconSize size;
  160.  
  161.           /* See what sizes this stock icon really exists at */
  162.           gtk_icon_set_get_sizes (icon_set, &sizes, &n_sizes);
  163.  
  164.           /* Use menu size if it exists, otherwise first size found */
  165.           size = sizes[0];
  166.           i = 0;
  167.           while (i < n_sizes)
  168.             {
  169.               if (sizes[i] == GTK_ICON_SIZE_MENU)
  170.                 {
  171.                   size = GTK_ICON_SIZE_MENU;
  172.                   break;
  173.                 }
  174.               ++i;
  175.             }
  176.           g_free (sizes);
  177.           
  178.           info.small_icon = gtk_widget_render_icon (window, info.id,
  179.                                                     size,
  180.                                                     NULL);
  181.           
  182.           if (size != GTK_ICON_SIZE_MENU)
  183.             {
  184.               /* Make the result the proper size for our thumbnail */
  185.               gint w, h;
  186.               GdkPixbuf *scaled;
  187.               
  188.               gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
  189.               
  190.               scaled = gdk_pixbuf_scale_simple (info.small_icon,
  191.                                                 w, h,
  192.                                                 GDK_INTERP_BILINEAR);
  193.  
  194.               g_object_unref (info.small_icon);
  195.               info.small_icon = scaled;
  196.             }
  197.         }
  198.       else
  199.         info.small_icon = NULL;
  200.  
  201.       if (info.item.keyval != 0)
  202.         {
  203.           info.accel_str = gtk_accelerator_name (info.item.keyval,
  204.                                                  info.item.modifier);
  205.         }
  206.       else
  207.         {
  208.           info.accel_str = g_strdup ("");
  209.         }
  210.  
  211.       info.macro = id_to_macro (info.id);
  212.       
  213.       gtk_list_store_append (store, &iter);
  214.       gtk_list_store_set (store, &iter, 0, &info, 1, info.id, -1);
  215.  
  216.       g_free (info.macro);
  217.       g_free (info.accel_str);
  218.       if (info.small_icon)
  219.         g_object_unref (info.small_icon);
  220.       
  221.       tmp_list = g_slist_next (tmp_list);
  222.     }
  223.   
  224.   g_slist_foreach (ids, (GFunc)g_free, NULL);
  225.   g_slist_free (ids);
  226.  
  227.   return GTK_TREE_MODEL (store);
  228. }
  229.  
  230. /* Finds the largest size at which the given image stock id is
  231.  * available. This would not be useful for a normal application
  232.  */
  233. static GtkIconSize
  234. get_largest_size (const char *id)
  235. {
  236.   GtkIconSet *set = gtk_icon_factory_lookup_default (id);
  237.   GtkIconSize *sizes;
  238.   gint n_sizes, i;
  239.   GtkIconSize best_size = GTK_ICON_SIZE_INVALID;
  240.   gint best_pixels = 0;
  241.  
  242.   gtk_icon_set_get_sizes (set, &sizes, &n_sizes);
  243.  
  244.   for (i = 0; i < n_sizes; i++)
  245.     {
  246.       gint width, height;
  247.       
  248.       gtk_icon_size_lookup (sizes[i], &width, &height);
  249.  
  250.       if (width * height > best_pixels)
  251.     {
  252.       best_size = sizes[i];
  253.       best_pixels = width * height;
  254.     }
  255.     }
  256.   
  257.   g_free (sizes);
  258.  
  259.   return best_size;
  260. }
  261.  
  262. static void
  263. selection_changed (GtkTreeSelection *selection)
  264. {
  265.   GtkTreeView *treeview;
  266.   StockItemDisplay *display;
  267.   GtkTreeModel *model;
  268.   GtkTreeIter iter;
  269.   
  270.   treeview = gtk_tree_selection_get_tree_view (selection);
  271.   display = g_object_get_data (G_OBJECT (treeview), "stock-display");
  272.  
  273.   if (gtk_tree_selection_get_selected (selection, &model, &iter))
  274.     {
  275.       StockItemInfo *info;
  276.       gchar *str;
  277.       
  278.       gtk_tree_model_get (model, &iter,
  279.                           0, &info,
  280.                           -1);
  281.  
  282.       if (info->small_icon && info->item.label)
  283.         gtk_label_set_text (GTK_LABEL (display->type_label), "Icon and Item");
  284.       else if (info->small_icon)
  285.         gtk_label_set_text (GTK_LABEL (display->type_label), "Icon Only");
  286.       else if (info->item.label)
  287.         gtk_label_set_text (GTK_LABEL (display->type_label), "Item Only");
  288.       else
  289.         gtk_label_set_text (GTK_LABEL (display->type_label), "???????");
  290.  
  291.       gtk_label_set_text (GTK_LABEL (display->macro_label), info->macro);
  292.       gtk_label_set_text (GTK_LABEL (display->id_label), info->id);
  293.  
  294.       if (info->item.label)
  295.         {
  296.           str = g_strdup_printf ("%s %s", info->item.label, info->accel_str);
  297.           gtk_label_set_text_with_mnemonic (GTK_LABEL (display->label_accel_label), str);
  298.           g_free (str);
  299.         }
  300.       else
  301.         {
  302.           gtk_label_set_text (GTK_LABEL (display->label_accel_label), "");
  303.         }
  304.  
  305.       if (info->small_icon)
  306.         gtk_image_set_from_stock (GTK_IMAGE (display->icon_image), info->id,
  307.                                   get_largest_size (info->id));
  308.       else
  309.         gtk_image_set_from_pixbuf (GTK_IMAGE (display->icon_image), NULL);
  310.  
  311.       stock_item_info_free (info);
  312.     }
  313.   else
  314.     {
  315.       gtk_label_set_text (GTK_LABEL (display->type_label), "No selected item");
  316.       gtk_label_set_text (GTK_LABEL (display->macro_label), "");
  317.       gtk_label_set_text (GTK_LABEL (display->id_label), "");
  318.       gtk_label_set_text (GTK_LABEL (display->label_accel_label), "");
  319.       gtk_image_set_from_pixbuf (GTK_IMAGE (display->icon_image), NULL);
  320.     }
  321. }
  322.  
  323. static void
  324. macro_set_func_text (GtkTreeViewColumn *tree_column,
  325.              GtkCellRenderer   *cell,
  326.              GtkTreeModel      *model,
  327.              GtkTreeIter       *iter,
  328.              gpointer           data)
  329. {
  330.   StockItemInfo *info;
  331.   
  332.   gtk_tree_model_get (model, iter,
  333.                       0, &info,
  334.                       -1);
  335.   
  336.   g_object_set (GTK_CELL_RENDERER (cell),
  337.                 "text", info->macro,
  338.                 NULL);
  339.   
  340.   stock_item_info_free (info);
  341. }
  342.  
  343. static void
  344. id_set_func (GtkTreeViewColumn *tree_column,
  345.              GtkCellRenderer   *cell,
  346.              GtkTreeModel      *model,
  347.              GtkTreeIter       *iter,
  348.              gpointer           data)
  349. {
  350.   StockItemInfo *info;
  351.   
  352.   gtk_tree_model_get (model, iter,
  353.                       0, &info,
  354.                       -1);
  355.   
  356.   g_object_set (GTK_CELL_RENDERER (cell),
  357.                 "text", info->id,
  358.                 NULL);
  359.   
  360.   stock_item_info_free (info);
  361. }
  362.  
  363. static void
  364. accel_set_func (GtkTreeViewColumn *tree_column,
  365.                 GtkCellRenderer   *cell,
  366.                 GtkTreeModel      *model,
  367.                 GtkTreeIter       *iter,
  368.                 gpointer           data)
  369. {
  370.   StockItemInfo *info;
  371.   
  372.   gtk_tree_model_get (model, iter,
  373.                       0, &info,
  374.                       -1);
  375.   
  376.   g_object_set (GTK_CELL_RENDERER (cell),
  377.                 "text", info->accel_str,
  378.                 NULL);
  379.   
  380.   stock_item_info_free (info);
  381. }
  382.  
  383. static void
  384. label_set_func (GtkTreeViewColumn *tree_column,
  385.                 GtkCellRenderer   *cell,
  386.                 GtkTreeModel      *model,
  387.                 GtkTreeIter       *iter,
  388.                 gpointer           data)
  389. {
  390.   StockItemInfo *info;
  391.   
  392.   gtk_tree_model_get (model, iter,
  393.                       0, &info,
  394.                       -1);
  395.   
  396.   g_object_set (GTK_CELL_RENDERER (cell),
  397.                 "text", info->item.label,
  398.                 NULL);
  399.   
  400.   stock_item_info_free (info);
  401. }
  402.  
  403. GtkWidget *
  404. do_stock_browser (GtkWidget *do_widget)
  405. {  
  406.   if (!window)
  407.     {
  408.       GtkWidget *frame;
  409.       GtkWidget *vbox;
  410.       GtkWidget *hbox;
  411.       GtkWidget *sw;
  412.       GtkWidget *treeview;
  413.       GtkWidget *align;
  414.       GtkTreeModel *model;
  415.       GtkCellRenderer *cell_renderer;
  416.       StockItemDisplay *display;
  417.       GtkTreeSelection *selection;
  418.       GtkTreeViewColumn *column;
  419.  
  420.       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  421.       gtk_window_set_screen (GTK_WINDOW (window),
  422.                  gtk_widget_get_screen (do_widget));
  423.       gtk_window_set_title (GTK_WINDOW (window), "Stock Icons and Items");
  424.       gtk_window_set_default_size (GTK_WINDOW (window), -1, 500);
  425.  
  426.       g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
  427.       gtk_container_set_border_width (GTK_CONTAINER (window), 8);
  428.  
  429.       hbox = gtk_hbox_new (FALSE, 8);
  430.       gtk_container_add (GTK_CONTAINER (window), hbox);
  431.  
  432.       sw = gtk_scrolled_window_new (NULL, NULL);
  433.       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
  434.                                       GTK_POLICY_NEVER,
  435.                                       GTK_POLICY_AUTOMATIC);
  436.       gtk_box_pack_start (GTK_BOX (hbox), sw, FALSE, FALSE, 0);
  437.  
  438.       model = create_model ();
  439.       
  440.       treeview = gtk_tree_view_new_with_model (model);
  441.  
  442.       g_object_unref (model);
  443.  
  444.       gtk_container_add (GTK_CONTAINER (sw), treeview);
  445.       
  446.       column = gtk_tree_view_column_new ();
  447.       gtk_tree_view_column_set_title (column, "Macro");
  448.  
  449.       cell_renderer = gtk_cell_renderer_pixbuf_new ();
  450.       gtk_tree_view_column_pack_start (column,
  451.                        cell_renderer,
  452.                        FALSE);
  453.       gtk_tree_view_column_set_attributes (column, cell_renderer,
  454.                        "stock_id", 1, NULL);
  455.       cell_renderer = gtk_cell_renderer_text_new ();
  456.       gtk_tree_view_column_pack_start (column,
  457.                        cell_renderer,
  458.                        TRUE);
  459.       gtk_tree_view_column_set_cell_data_func (column, cell_renderer,
  460.                            macro_set_func_text, NULL, NULL);
  461.  
  462.       gtk_tree_view_append_column (GTK_TREE_VIEW (treeview),
  463.                    column);
  464.  
  465.       cell_renderer = gtk_cell_renderer_text_new ();
  466.       gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview),
  467.                                                   -1,
  468.                                                   "Label",
  469.                                                   cell_renderer,
  470.                                                   label_set_func,
  471.                                                   NULL,
  472.                                                   NULL);
  473.  
  474.       cell_renderer = gtk_cell_renderer_text_new ();
  475.       gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview),
  476.                                                   -1,
  477.                                                   "Accel",
  478.                                                   cell_renderer,
  479.                                                   accel_set_func,
  480.                                                   NULL,
  481.                                                   NULL);
  482.  
  483.       cell_renderer = gtk_cell_renderer_text_new ();
  484.       gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview),
  485.                                                   -1,
  486.                                                   "ID",
  487.                                                   cell_renderer,
  488.                                                   id_set_func,
  489.                                                   NULL,
  490.                                                   NULL);
  491.       
  492.       align = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
  493.       gtk_box_pack_end (GTK_BOX (hbox), align, FALSE, FALSE, 0);
  494.       
  495.       frame = gtk_frame_new ("Selected Item");
  496.       gtk_container_add (GTK_CONTAINER (align), frame);
  497.  
  498.       vbox = gtk_vbox_new (FALSE, 8);
  499.       gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  500.       gtk_container_add (GTK_CONTAINER (frame), vbox);
  501.  
  502.       display = g_new (StockItemDisplay, 1);
  503.       g_object_set_data_full (G_OBJECT (treeview),
  504.                               "stock-display",
  505.                               display,
  506.                               g_free); /* free display with treeview */
  507.       
  508.       display->type_label = gtk_label_new (NULL);
  509.       display->macro_label = gtk_label_new (NULL);
  510.       display->id_label = gtk_label_new (NULL);
  511.       display->label_accel_label = gtk_label_new (NULL);
  512.       display->icon_image = gtk_image_new_from_pixbuf (NULL); /* empty image */
  513.  
  514.       gtk_box_pack_start (GTK_BOX (vbox), display->type_label,
  515.                           FALSE, FALSE, 0);
  516.  
  517.       gtk_box_pack_start (GTK_BOX (vbox), display->icon_image,
  518.                           FALSE, FALSE, 0);
  519.       
  520.       gtk_box_pack_start (GTK_BOX (vbox), display->label_accel_label,
  521.                           FALSE, FALSE, 0);
  522.       gtk_box_pack_start (GTK_BOX (vbox), display->macro_label,
  523.                           FALSE, FALSE, 0);
  524.       gtk_box_pack_start (GTK_BOX (vbox), display->id_label,
  525.                           FALSE, FALSE, 0);
  526.  
  527.       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
  528.       gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
  529.       
  530.       g_signal_connect (selection,
  531.             "changed",
  532.             G_CALLBACK (selection_changed),
  533.             NULL);
  534.     }
  535.  
  536.   if (!GTK_WIDGET_VISIBLE (window))
  537.     {
  538.       gtk_widget_show_all (window);
  539.     }
  540.   else
  541.     {     
  542.       gtk_widget_destroy (window);
  543.       window = NULL;
  544.     }
  545.  
  546.   return window;
  547. }
  548.