]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/toolpalette.c
f7ed51ea59a92a7fbbbcd68a1a59505fb64f694d
[~andy/gtk] / demos / gtk-demo / toolpalette.c
1 /* Tool Palette
2  *
3  * A tool palette widget shows groups of toolbar items as a grid of icons
4  * or a list of names.
5  */
6
7 #include <string.h>
8 #include <gtk/gtk.h>
9 #include "config.h"
10 #include "demo-common.h"
11
12 static GtkWidget *window = NULL;
13
14 static void load_stock_items (GtkToolPalette *palette);
15 static void load_toggle_items (GtkToolPalette *palette);
16 static void load_special_items (GtkToolPalette *palette);
17
18 typedef struct _CanvasItem CanvasItem;
19
20 struct _CanvasItem
21 {
22   GdkPixbuf *pixbuf;
23   gdouble x, y;
24 };
25
26 static CanvasItem *drop_item = NULL;
27 static GList *canvas_items = NULL;
28
29 /********************************/
30 /* ====== Canvas drawing ====== */
31 /********************************/
32
33 static CanvasItem*
34 canvas_item_new (GtkWidget     *widget,
35                  GtkToolButton *button,
36                  gdouble        x,
37                  gdouble        y)
38 {
39   CanvasItem *item = NULL;
40   const gchar *stock_id;
41   GdkPixbuf *pixbuf;
42
43   stock_id = gtk_tool_button_get_stock_id (button);
44   pixbuf = gtk_widget_render_icon (widget, stock_id, GTK_ICON_SIZE_DIALOG, NULL);
45
46   if (pixbuf)
47     {
48       item = g_slice_new0 (CanvasItem);
49       item->pixbuf = pixbuf;
50       item->x = x;
51       item->y = y;
52     }
53
54   return item;
55 }
56
57 static void
58 canvas_item_free (CanvasItem *item)
59 {
60   g_object_unref (item->pixbuf);
61   g_slice_free (CanvasItem, item);
62 }
63
64 static void
65 canvas_item_draw (const CanvasItem *item,
66                   cairo_t          *cr,
67                   gboolean          preview)
68 {
69   gdouble cx = gdk_pixbuf_get_width (item->pixbuf);
70   gdouble cy = gdk_pixbuf_get_height (item->pixbuf);
71
72   gdk_cairo_set_source_pixbuf (cr,
73                                item->pixbuf,
74                                item->x - cx * 0.5,
75                                item->y - cy * 0.5);
76
77   if (preview)
78     cairo_paint_with_alpha (cr, 0.6);
79   else
80     cairo_paint (cr);
81 }
82
83 static gboolean
84 canvas_draw (GtkWidget *widget,
85              cairo_t   *cr)
86 {
87   GList *iter;
88
89   cairo_set_source_rgb (cr, 1, 1, 1);
90   cairo_paint (cr);
91
92   for (iter = canvas_items; iter; iter = iter->next)
93     canvas_item_draw (iter->data, cr, FALSE);
94
95   if (drop_item)
96     canvas_item_draw (drop_item, cr, TRUE);
97
98   return TRUE;
99 }
100
101 /*****************************/
102 /* ====== Palette DnD ====== */
103 /*****************************/
104
105 static void
106 palette_drop_item (GtkToolItem      *drag_item,
107                    GtkToolItemGroup *drop_group,
108                    gint              x,
109                    gint              y)
110 {
111   GtkWidget *drag_group = gtk_widget_get_parent (GTK_WIDGET (drag_item));
112   GtkToolItem *drop_item = gtk_tool_item_group_get_drop_item (drop_group, x, y);
113   gint drop_position = -1;
114
115   if (drop_item)
116     drop_position = gtk_tool_item_group_get_item_position (GTK_TOOL_ITEM_GROUP (drop_group), drop_item);
117
118   if (GTK_TOOL_ITEM_GROUP (drag_group) != drop_group)
119     {
120       gboolean homogeneous, expand, fill, new_row;
121
122       g_object_ref (drag_item);
123       gtk_container_child_get (GTK_CONTAINER (drag_group), GTK_WIDGET (drag_item),
124                                "homogeneous", &homogeneous,
125                                "expand", &expand,
126                                "fill", &fill,
127                                "new-row", &new_row,
128                                NULL);
129       gtk_container_remove (GTK_CONTAINER (drag_group), GTK_WIDGET (drag_item));
130       gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (drop_group),
131                                   drag_item, drop_position);
132       gtk_container_child_set (GTK_CONTAINER (drop_group), GTK_WIDGET (drag_item),
133                                "homogeneous", homogeneous,
134                                "expand", expand,
135                                "fill", fill,
136                                "new-row", new_row,
137                                NULL);
138       g_object_unref (drag_item);
139     }
140   else
141     gtk_tool_item_group_set_item_position (GTK_TOOL_ITEM_GROUP (drop_group),
142                                            drag_item, drop_position);
143 }
144
145 static void
146 palette_drop_group (GtkToolPalette   *palette,
147                     GtkToolItemGroup *drag_group,
148                     GtkToolItemGroup *drop_group)
149 {
150   gint drop_position = -1;
151
152   if (drop_group)
153     drop_position = gtk_tool_palette_get_group_position (palette, drop_group);
154
155   gtk_tool_palette_set_group_position (palette, drag_group, drop_position);
156 }
157
158 static void
159 palette_drag_data_received (GtkWidget        *widget,
160                             GdkDragContext   *context,
161                             gint              x,
162                             gint              y,
163                             GtkSelectionData *selection,
164                             guint             info,
165                             guint             time,
166                             gpointer          data)
167 {
168   GtkAllocation     allocation;
169   GtkToolItemGroup *drop_group = NULL;
170   GtkWidget        *drag_palette = gtk_drag_get_source_widget (context);
171   GtkWidget        *drag_item = NULL;
172
173   while (drag_palette && !GTK_IS_TOOL_PALETTE (drag_palette))
174     drag_palette = gtk_widget_get_parent (drag_palette);
175
176   if (drag_palette)
177     {
178       drag_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (drag_palette),
179                                                   selection);
180       drop_group = gtk_tool_palette_get_drop_group (GTK_TOOL_PALETTE (widget),
181                                                     x, y);
182     }
183
184   if (GTK_IS_TOOL_ITEM_GROUP (drag_item))
185     palette_drop_group (GTK_TOOL_PALETTE (drag_palette),
186                         GTK_TOOL_ITEM_GROUP (drag_item),
187                         drop_group);
188   else if (GTK_IS_TOOL_ITEM (drag_item) && drop_group)
189     {
190       gtk_widget_get_allocation (GTK_WIDGET (drop_group), &allocation);
191       palette_drop_item (GTK_TOOL_ITEM (drag_item),
192                          drop_group,
193                          x - allocation.x,
194                          y - allocation.y);
195     }
196 }
197
198 /********************************/
199 /* ====== Passive Canvas ====== */
200 /********************************/
201
202 static void
203 passive_canvas_drag_data_received (GtkWidget        *widget,
204                                    GdkDragContext   *context,
205                                    gint              x,
206                                    gint              y,
207                                    GtkSelectionData *selection,
208                                    guint             info,
209                                    guint             time,
210                                    gpointer          data)
211 {
212   /* find the tool button, which is the source of this DnD operation */
213
214   GtkWidget *palette = gtk_drag_get_source_widget (context);
215   CanvasItem *canvas_item = NULL;
216   GtkWidget *tool_item = NULL;
217
218   while (palette && !GTK_IS_TOOL_PALETTE (palette))
219     palette = gtk_widget_get_parent (palette);
220
221   if (palette)
222     tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
223                                                 selection);
224
225   g_assert (NULL == drop_item);
226
227   /* append a new canvas item when a tool button was found */
228
229   if (GTK_IS_TOOL_ITEM (tool_item))
230     canvas_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
231
232   if (canvas_item)
233     {
234       canvas_items = g_list_append (canvas_items, canvas_item);
235       gtk_widget_queue_draw (widget);
236     }
237 }
238
239 /************************************/
240 /* ====== Interactive Canvas ====== */
241 /************************************/
242
243 static gboolean
244 interactive_canvas_drag_motion (GtkWidget      *widget,
245                                 GdkDragContext *context,
246                                 gint            x,
247                                 gint            y,
248                                 guint           time,
249                                 gpointer        data)
250 {
251   if (drop_item)
252     {
253       /* already have a drop indicator - just update position */
254
255       drop_item->x = x;
256       drop_item->y = y;
257
258       gtk_widget_queue_draw (widget);
259       gdk_drag_status (context, GDK_ACTION_COPY, time);
260     }
261   else
262     {
263       /* request DnD data for creating a drop indicator */
264
265       GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
266
267       if (!target)
268         return FALSE;
269
270       gtk_drag_get_data (widget, context, target, time);
271     }
272
273   return TRUE;
274 }
275
276 static void
277 interactive_canvas_drag_data_received (GtkWidget        *widget,
278                                        GdkDragContext   *context,
279                                        gint              x,
280                                        gint              y,
281                                        GtkSelectionData *selection,
282                                        guint             info,
283                                        guint             time,
284                                        gpointer          data)
285
286 {
287   /* find the tool button which is the source of this DnD operation */
288
289   GtkWidget *palette = gtk_drag_get_source_widget (context);
290   GtkWidget *tool_item = NULL;
291
292   while (palette && !GTK_IS_TOOL_PALETTE (palette))
293     palette = gtk_widget_get_parent (palette);
294
295   if (palette)
296     tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
297                                                 selection);
298
299   /* create a drop indicator when a tool button was found */
300
301   g_assert (NULL == drop_item);
302
303   if (GTK_IS_TOOL_ITEM (tool_item))
304     {
305       drop_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
306       gdk_drag_status (context, GDK_ACTION_COPY, time);
307       gtk_widget_queue_draw (widget);
308     }
309 }
310
311 static gboolean
312 interactive_canvas_drag_drop (GtkWidget      *widget,
313                               GdkDragContext *context,
314                               gint            x,
315                               gint            y,
316                               guint           time,
317                               gpointer        data)
318 {
319   if (drop_item)
320     {
321       /* turn the drop indicator into a real canvas item */
322
323       drop_item->x = x;
324       drop_item->y = y;
325
326       canvas_items = g_list_append (canvas_items, drop_item);
327       drop_item = NULL;
328
329       /* signal the item was accepted and redraw */
330
331       gtk_drag_finish (context, TRUE, FALSE, time);
332       gtk_widget_queue_draw (widget);
333
334       return TRUE;
335     }
336
337   return FALSE;
338 }
339
340 static gboolean
341 interactive_canvas_real_drag_leave (gpointer data)
342 {
343   if (drop_item)
344     {
345       GtkWidget *widget = GTK_WIDGET (data);
346
347       canvas_item_free (drop_item);
348       drop_item = NULL;
349
350       gtk_widget_queue_draw (widget);
351     }
352
353   return FALSE;
354 }
355
356 static void
357 interactive_canvas_drag_leave (GtkWidget      *widget,
358                                GdkDragContext *context,
359                                guint           time,
360                                gpointer        data)
361 {
362   /* defer cleanup until a potential "drag-drop" signal was received */
363   g_idle_add (interactive_canvas_real_drag_leave, widget);
364 }
365
366 static void
367 on_combo_orientation_changed (GtkComboBox *combo_box,
368                               gpointer     user_data)
369 {
370   GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
371   GtkScrolledWindow *sw;
372   GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
373   GtkTreeIter iter;
374   gint val = 0;
375
376   sw = GTK_SCROLLED_WINDOW (gtk_widget_get_parent (GTK_WIDGET (palette)));
377
378   if (!gtk_combo_box_get_active_iter (combo_box, &iter))
379     return;
380
381   gtk_tree_model_get (model, &iter, 1, &val, -1);
382
383   gtk_orientable_set_orientation (GTK_ORIENTABLE (palette), val);
384
385   if (val == GTK_ORIENTATION_HORIZONTAL)
386     gtk_scrolled_window_set_policy (sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
387   else
388     gtk_scrolled_window_set_policy (sw, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
389 }
390
391 static void
392 on_combo_style_changed (GtkComboBox *combo_box,
393                         gpointer     user_data)
394 {
395   GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
396   GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
397   GtkTreeIter iter;
398   gint val = 0;
399
400   if (!gtk_combo_box_get_active_iter (combo_box, &iter))
401     return;
402
403   gtk_tree_model_get (model, &iter, 1, &val, -1);
404
405   if (val == -1)
406     gtk_tool_palette_unset_style (palette);
407   else
408     gtk_tool_palette_set_style (palette, val);
409 }
410
411 GtkWidget *
412 do_toolpalette (GtkWidget *do_widget)
413 {
414   GtkWidget *box = NULL;
415   GtkWidget *hbox = NULL;
416   GtkWidget *combo_orientation = NULL;
417   GtkListStore *orientation_model = NULL;
418   GtkWidget *combo_style = NULL;
419   GtkListStore *style_model = NULL;
420   GtkCellRenderer *cell_renderer = NULL;
421   GtkTreeIter iter;
422   GtkWidget *palette = NULL;
423   GtkWidget *palette_scroller = NULL;
424   GtkWidget *notebook = NULL;
425   GtkWidget *contents = NULL;
426   GtkWidget *contents_scroller = NULL;
427
428   if (!window)
429     {
430       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
431       gtk_window_set_screen (GTK_WINDOW (window),
432                              gtk_widget_get_screen (do_widget));
433       gtk_window_set_title (GTK_WINDOW (window), "Tool Palette");
434       gtk_window_set_default_size (GTK_WINDOW (window), 200, 600);
435
436       g_signal_connect (window, "destroy",
437                         G_CALLBACK (gtk_widget_destroyed), &window);
438       gtk_container_set_border_width (GTK_CONTAINER (window), 8);
439
440       /* Add widgets to control the ToolPalette appearance: */
441       box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 6);
442       gtk_container_add (GTK_CONTAINER (window), box);
443
444       /* Orientation combo box: */
445       orientation_model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
446       gtk_list_store_append (orientation_model, &iter);
447       gtk_list_store_set (orientation_model, &iter,
448                           0, "Horizontal",
449                           1, GTK_ORIENTATION_HORIZONTAL,
450                           -1);
451       gtk_list_store_append (orientation_model, &iter);
452       gtk_list_store_set (orientation_model, &iter,
453                           0, "Vertical",
454                           1, GTK_ORIENTATION_VERTICAL,
455                           -1);
456
457       combo_orientation =
458         gtk_combo_box_new_with_model (GTK_TREE_MODEL (orientation_model));
459       cell_renderer = gtk_cell_renderer_text_new ();
460       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_orientation),
461                                   cell_renderer,
462                                   TRUE);
463       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_orientation),
464                                       cell_renderer,
465                                       "text", 0,
466                                       NULL);
467       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_orientation), &iter);
468       gtk_box_pack_start (GTK_BOX (box), combo_orientation, FALSE, FALSE, 0);
469
470       /* Style combo box: */
471       style_model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
472       gtk_list_store_append (style_model, &iter);
473       gtk_list_store_set (style_model, &iter,
474                           0, "Text",
475                           1, GTK_TOOLBAR_TEXT,
476                           -1);
477       gtk_list_store_append (style_model, &iter);
478       gtk_list_store_set (style_model, &iter,
479                           0, "Both",
480                           1, GTK_TOOLBAR_BOTH,
481                           -1);
482       gtk_list_store_append (style_model, &iter);
483       gtk_list_store_set (style_model, &iter,
484                           0, "Both: Horizontal",
485                           1, GTK_TOOLBAR_BOTH_HORIZ,
486                           -1);
487       gtk_list_store_append (style_model, &iter);
488       gtk_list_store_set (style_model, &iter,
489                           0, "Icons",
490                           1, GTK_TOOLBAR_ICONS,
491                           -1);
492       gtk_list_store_append (style_model, &iter);
493       gtk_list_store_set (style_model, &iter,
494                           0, "Default",
495                           1, -1,  /* A custom meaning for this demo. */
496                           -1);
497       combo_style = gtk_combo_box_new_with_model (GTK_TREE_MODEL (style_model));
498       cell_renderer = gtk_cell_renderer_text_new ();
499       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_style),
500                                   cell_renderer,
501                                   TRUE);
502       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_style),
503                                       cell_renderer,
504                                       "text", 0,
505                                       NULL);
506       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_style), &iter);
507       gtk_box_pack_start (GTK_BOX (box), combo_style, FALSE, FALSE, 0);
508
509       /* Add hbox */
510       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 5);
511       gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 0);
512
513       /* Add and fill the ToolPalette: */
514       palette = gtk_tool_palette_new ();
515
516       load_stock_items (GTK_TOOL_PALETTE (palette));
517       load_toggle_items (GTK_TOOL_PALETTE (palette));
518       load_special_items (GTK_TOOL_PALETTE (palette));
519
520       palette_scroller = gtk_scrolled_window_new (NULL, NULL);
521       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (palette_scroller),
522                                       GTK_POLICY_NEVER,
523                                       GTK_POLICY_AUTOMATIC);
524       gtk_container_set_border_width (GTK_CONTAINER (palette_scroller), 6);
525
526       gtk_container_add (GTK_CONTAINER (palette_scroller), palette);
527       gtk_container_add (GTK_CONTAINER (hbox), palette_scroller);
528
529       gtk_widget_show_all (box);
530
531       /* Connect signals: */
532       g_signal_connect (combo_orientation, "changed",
533                         G_CALLBACK (on_combo_orientation_changed), palette);
534       g_signal_connect (combo_style, "changed",
535                         G_CALLBACK (on_combo_style_changed), palette);
536
537       /* Keep the widgets in sync: */
538       on_combo_orientation_changed (GTK_COMBO_BOX (combo_orientation), palette);
539
540       /* ===== notebook ===== */
541
542       notebook = gtk_notebook_new ();
543       gtk_container_set_border_width (GTK_CONTAINER (notebook), 6);
544       gtk_box_pack_end (GTK_BOX(hbox), notebook, FALSE, FALSE, 0);
545
546       /* ===== DnD for tool items ===== */
547
548       g_signal_connect (palette, "drag-data-received",
549                         G_CALLBACK (palette_drag_data_received), NULL);
550
551       gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
552                                       palette,
553                                       GTK_DEST_DEFAULT_ALL,
554                                       GTK_TOOL_PALETTE_DRAG_ITEMS |
555                                       GTK_TOOL_PALETTE_DRAG_GROUPS,
556                                       GDK_ACTION_MOVE);
557
558       /* ===== passive DnD dest ===== */
559
560       contents = gtk_drawing_area_new ();
561       gtk_widget_set_app_paintable (contents, TRUE);
562
563       g_object_connect (contents,
564                         "signal::draw", canvas_draw, NULL,
565                         "signal::drag-data-received", passive_canvas_drag_data_received, NULL,
566                         NULL);
567
568       gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
569                                       contents,
570                                       GTK_DEST_DEFAULT_ALL,
571                                       GTK_TOOL_PALETTE_DRAG_ITEMS,
572                                       GDK_ACTION_COPY);
573
574       contents_scroller = gtk_scrolled_window_new (NULL, NULL);
575       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
576                                       GTK_POLICY_AUTOMATIC,
577                                       GTK_POLICY_ALWAYS);
578       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
579                                              contents);
580       gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
581
582       gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
583                                 contents_scroller,
584                                 gtk_label_new ("Passive DnD Mode"));
585
586       /* ===== interactive DnD dest ===== */
587
588       contents = gtk_drawing_area_new ();
589       gtk_widget_set_app_paintable (contents, TRUE);
590
591       g_object_connect (contents,
592                         "signal::draw", canvas_draw, NULL,
593                         "signal::drag-motion", interactive_canvas_drag_motion, NULL,
594                         "signal::drag-data-received", interactive_canvas_drag_data_received, NULL,
595                         "signal::drag-leave", interactive_canvas_drag_leave, NULL,
596                         "signal::drag-drop", interactive_canvas_drag_drop, NULL,
597                         NULL);
598
599       gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
600                                       contents,
601                                       GTK_DEST_DEFAULT_HIGHLIGHT,
602                                       GTK_TOOL_PALETTE_DRAG_ITEMS,
603                                       GDK_ACTION_COPY);
604
605       contents_scroller = gtk_scrolled_window_new (NULL, NULL);
606       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
607                                       GTK_POLICY_AUTOMATIC,
608                                       GTK_POLICY_ALWAYS);
609       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
610                                              contents);
611       gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
612
613       gtk_notebook_append_page (GTK_NOTEBOOK (notebook), contents_scroller,
614                                 gtk_label_new ("Interactive DnD Mode"));
615     }
616
617   if (!gtk_widget_get_visible (window))
618     {
619       gtk_widget_show_all (window);
620     }
621   else
622     {
623       gtk_widget_destroy (window);
624       window = NULL;
625     }
626
627   return window;
628 }
629
630
631 static void
632 load_stock_items (GtkToolPalette *palette)
633 {
634   GtkWidget *group_af = gtk_tool_item_group_new ("Stock Icons (A-F)");
635   GtkWidget *group_gn = gtk_tool_item_group_new ("Stock Icons (G-N)");
636   GtkWidget *group_or = gtk_tool_item_group_new ("Stock Icons (O-R)");
637   GtkWidget *group_sz = gtk_tool_item_group_new ("Stock Icons (S-Z)");
638   GtkWidget *group = NULL;
639
640   GtkToolItem *item;
641   GSList *stock_ids;
642   GSList *iter;
643
644   stock_ids = gtk_stock_list_ids ();
645   stock_ids = g_slist_sort (stock_ids, (GCompareFunc) strcmp);
646
647   gtk_container_add (GTK_CONTAINER (palette), group_af);
648   gtk_container_add (GTK_CONTAINER (palette), group_gn);
649   gtk_container_add (GTK_CONTAINER (palette), group_or);
650   gtk_container_add (GTK_CONTAINER (palette), group_sz);
651
652   for (iter = stock_ids; iter; iter = g_slist_next (iter))
653     {
654       GtkStockItem stock_item;
655       gchar *id = iter->data;
656
657       switch (id[4])
658         {
659           case 'a':
660             group = group_af;
661             break;
662
663           case 'g':
664             group = group_gn;
665             break;
666
667           case 'o':
668             group = group_or;
669             break;
670
671           case 's':
672             group = group_sz;
673             break;
674         }
675
676       item = gtk_tool_button_new_from_stock (id);
677       gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (item), id);
678       gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE);
679       gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
680
681       if (!gtk_stock_lookup (id, &stock_item) || !stock_item.label)
682         gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), id);
683
684       g_free (id);
685     }
686
687   g_slist_free (stock_ids);
688 }
689
690 static void
691 load_toggle_items (GtkToolPalette *palette)
692 {
693   GSList *toggle_group = NULL;
694   GtkToolItem *item;
695   GtkWidget *group;
696   char *label;
697   int i;
698
699   group = gtk_tool_item_group_new ("Radio Item");
700   gtk_container_add (GTK_CONTAINER (palette), group);
701
702   for (i = 1; i <= 10; ++i)
703     {
704       label = g_strdup_printf ("#%d", i);
705       item = gtk_radio_tool_button_new (toggle_group);
706       gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), label);
707       g_free (label);
708
709       gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
710       toggle_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item));
711     }
712 }
713
714 static GtkToolItem *
715 create_entry_item (const char *text)
716 {
717   GtkToolItem *item;
718   GtkWidget *entry;
719
720   entry = gtk_entry_new ();
721   gtk_entry_set_text (GTK_ENTRY (entry), text);
722   gtk_entry_set_width_chars (GTK_ENTRY (entry), 5);
723
724   item = gtk_tool_item_new ();
725   gtk_container_add (GTK_CONTAINER (item), entry);
726
727   return item;
728 }
729
730 static void
731 load_special_items (GtkToolPalette *palette)
732 {
733   GtkToolItem *item;
734   GtkWidget *group;
735   GtkWidget *label_button;
736
737   group = gtk_tool_item_group_new (NULL);
738   label_button = gtk_button_new_with_label ("Advanced Features");
739   gtk_widget_show (label_button);
740   gtk_tool_item_group_set_label_widget (GTK_TOOL_ITEM_GROUP (group),
741                                         label_button);
742   gtk_container_add (GTK_CONTAINER (palette), group);
743
744   item = create_entry_item ("homogeneous=FALSE");
745   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
746   gtk_container_child_set (GTK_CONTAINER (group), GTK_WIDGET (item),
747                            "homogeneous", FALSE, NULL);
748
749   item = create_entry_item ("homogeneous=FALSE, expand=TRUE");
750   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
751   gtk_container_child_set (GTK_CONTAINER (group), GTK_WIDGET (item),
752                            "homogeneous", FALSE, "expand", TRUE,
753                            NULL);
754
755   item = create_entry_item ("homogeneous=FALSE, expand=TRUE, fill=FALSE");
756   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
757   gtk_container_child_set (GTK_CONTAINER (group), GTK_WIDGET (item),
758                            "homogeneous", FALSE, "expand", TRUE,
759                            "fill", FALSE, NULL);
760
761   item = create_entry_item ("homogeneous=FALSE, expand=TRUE, new-row=TRUE");
762   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
763   gtk_container_child_set (GTK_CONTAINER (group), GTK_WIDGET (item),
764                            "homogeneous", FALSE, "expand", TRUE,
765                            "new-row", TRUE, NULL);
766
767   item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_UP);
768   gtk_tool_item_set_tooltip_text (item, "Show on vertical palettes only");
769   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
770   gtk_tool_item_set_visible_horizontal (item, FALSE);
771
772   item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD);
773   gtk_tool_item_set_tooltip_text (item, "Show on horizontal palettes only");
774   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
775   gtk_tool_item_set_visible_vertical (item, FALSE);
776
777   item = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
778   gtk_tool_item_set_tooltip_text (item, "Do not show at all");
779   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
780   gtk_widget_set_no_show_all (GTK_WIDGET (item), TRUE);
781
782   item = gtk_tool_button_new_from_stock (GTK_STOCK_FULLSCREEN);
783   gtk_tool_item_set_tooltip_text (item, "Expanded this item");
784   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
785   gtk_container_child_set (GTK_CONTAINER (group), GTK_WIDGET (item),
786                            "homogeneous", FALSE,
787                            "expand", TRUE,
788                            NULL);
789
790   item = gtk_tool_button_new_from_stock (GTK_STOCK_HELP);
791   gtk_tool_item_set_tooltip_text (item, "A regular item");
792   gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
793 }