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