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