3 * A tool palette widget shows groups of toolbar items as a grid of icons
10 #include "demo-common.h"
12 static GtkWidget *window = NULL;
14 static void load_stock_items (GtkToolPalette *palette);
15 static void load_toggle_items (GtkToolPalette *palette);
16 static void load_special_items (GtkToolPalette *palette);
18 typedef struct _CanvasItem CanvasItem;
26 static CanvasItem *drop_item = NULL;
27 static GList *canvas_items = NULL;
29 /********************************/
30 /* ====== Canvas drawing ====== */
31 /********************************/
34 canvas_item_new (GtkWidget *widget,
35 GtkToolButton *button,
39 CanvasItem *item = NULL;
40 const gchar *stock_id;
43 stock_id = gtk_tool_button_get_stock_id (button);
44 pixbuf = gtk_widget_render_icon (widget, stock_id, GTK_ICON_SIZE_DIALOG, NULL);
48 item = g_slice_new0 (CanvasItem);
49 item->pixbuf = pixbuf;
58 canvas_item_free (CanvasItem *item)
60 g_object_unref (item->pixbuf);
61 g_slice_free (CanvasItem, item);
65 canvas_item_draw (const CanvasItem *item,
69 gdouble cx = gdk_pixbuf_get_width (item->pixbuf);
70 gdouble cy = gdk_pixbuf_get_height (item->pixbuf);
72 gdk_cairo_set_source_pixbuf (cr,
78 cairo_paint_with_alpha (cr, 0.6);
84 canvas_draw (GtkWidget *widget,
89 cairo_set_source_rgb (cr, 1, 1, 1);
92 for (iter = canvas_items; iter; iter = iter->next)
93 canvas_item_draw (iter->data, cr, FALSE);
96 canvas_item_draw (drop_item, cr, TRUE);
101 /*****************************/
102 /* ====== Palette DnD ====== */
103 /*****************************/
106 palette_drop_item (GtkToolItem *drag_item,
107 GtkToolItemGroup *drop_group,
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;
116 drop_position = gtk_tool_item_group_get_item_position (GTK_TOOL_ITEM_GROUP (drop_group), drop_item);
118 if (GTK_TOOL_ITEM_GROUP (drag_group) != drop_group)
120 gboolean homogeneous, expand, fill, new_row;
122 g_object_ref (drag_item);
123 gtk_container_child_get (GTK_CONTAINER (drag_group), GTK_WIDGET (drag_item),
124 "homogeneous", &homogeneous,
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,
138 g_object_unref (drag_item);
141 gtk_tool_item_group_set_item_position (GTK_TOOL_ITEM_GROUP (drop_group),
142 drag_item, drop_position);
146 palette_drop_group (GtkToolPalette *palette,
147 GtkToolItemGroup *drag_group,
148 GtkToolItemGroup *drop_group)
150 gint drop_position = -1;
153 drop_position = gtk_tool_palette_get_group_position (palette, drop_group);
155 gtk_tool_palette_set_group_position (palette, drag_group, drop_position);
159 palette_drag_data_received (GtkWidget *widget,
160 GdkDragContext *context,
163 GtkSelectionData *selection,
168 GtkAllocation allocation;
169 GtkToolItemGroup *drop_group = NULL;
170 GtkWidget *drag_palette = gtk_drag_get_source_widget (context);
171 GtkWidget *drag_item = NULL;
173 while (drag_palette && !GTK_IS_TOOL_PALETTE (drag_palette))
174 drag_palette = gtk_widget_get_parent (drag_palette);
178 drag_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (drag_palette),
180 drop_group = gtk_tool_palette_get_drop_group (GTK_TOOL_PALETTE (widget),
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),
188 else if (GTK_IS_TOOL_ITEM (drag_item) && drop_group)
190 gtk_widget_get_allocation (GTK_WIDGET (drop_group), &allocation);
191 palette_drop_item (GTK_TOOL_ITEM (drag_item),
198 /********************************/
199 /* ====== Passive Canvas ====== */
200 /********************************/
203 passive_canvas_drag_data_received (GtkWidget *widget,
204 GdkDragContext *context,
207 GtkSelectionData *selection,
212 /* find the tool button, which is the source of this DnD operation */
214 GtkWidget *palette = gtk_drag_get_source_widget (context);
215 CanvasItem *canvas_item = NULL;
216 GtkWidget *tool_item = NULL;
218 while (palette && !GTK_IS_TOOL_PALETTE (palette))
219 palette = gtk_widget_get_parent (palette);
222 tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
225 g_assert (NULL == drop_item);
227 /* append a new canvas item when a tool button was found */
229 if (GTK_IS_TOOL_ITEM (tool_item))
230 canvas_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
234 canvas_items = g_list_append (canvas_items, canvas_item);
235 gtk_widget_queue_draw (widget);
239 /************************************/
240 /* ====== Interactive Canvas ====== */
241 /************************************/
244 interactive_canvas_drag_motion (GtkWidget *widget,
245 GdkDragContext *context,
253 /* already have a drop indicator - just update position */
258 gtk_widget_queue_draw (widget);
259 gdk_drag_status (context, GDK_ACTION_COPY, time);
263 /* request DnD data for creating a drop indicator */
265 GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
270 gtk_drag_get_data (widget, context, target, time);
277 interactive_canvas_drag_data_received (GtkWidget *widget,
278 GdkDragContext *context,
281 GtkSelectionData *selection,
287 /* find the tool button which is the source of this DnD operation */
289 GtkWidget *palette = gtk_drag_get_source_widget (context);
290 GtkWidget *tool_item = NULL;
292 while (palette && !GTK_IS_TOOL_PALETTE (palette))
293 palette = gtk_widget_get_parent (palette);
296 tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
299 /* create a drop indicator when a tool button was found */
301 g_assert (NULL == drop_item);
303 if (GTK_IS_TOOL_ITEM (tool_item))
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);
312 interactive_canvas_drag_drop (GtkWidget *widget,
313 GdkDragContext *context,
321 /* turn the drop indicator into a real canvas item */
326 canvas_items = g_list_append (canvas_items, drop_item);
329 /* signal the item was accepted and redraw */
331 gtk_drag_finish (context, TRUE, FALSE, time);
332 gtk_widget_queue_draw (widget);
341 interactive_canvas_real_drag_leave (gpointer data)
345 GtkWidget *widget = GTK_WIDGET (data);
347 canvas_item_free (drop_item);
350 gtk_widget_queue_draw (widget);
357 interactive_canvas_drag_leave (GtkWidget *widget,
358 GdkDragContext *context,
362 /* defer cleanup until a potential "drag-drop" signal was received */
363 g_idle_add (interactive_canvas_real_drag_leave, widget);
367 on_combo_orientation_changed (GtkComboBox *combo_box,
370 GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
371 GtkScrolledWindow *sw;
372 GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
376 sw = GTK_SCROLLED_WINDOW (gtk_widget_get_parent (GTK_WIDGET (palette)));
378 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
381 gtk_tree_model_get (model, &iter, 1, &val, -1);
383 gtk_orientable_set_orientation (GTK_ORIENTABLE (palette), val);
385 if (val == GTK_ORIENTATION_HORIZONTAL)
386 gtk_scrolled_window_set_policy (sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
388 gtk_scrolled_window_set_policy (sw, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
392 on_combo_style_changed (GtkComboBox *combo_box,
395 GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
396 GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
400 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
403 gtk_tree_model_get (model, &iter, 1, &val, -1);
406 gtk_tool_palette_unset_style (palette);
408 gtk_tool_palette_set_style (palette, val);
412 do_toolpalette (GtkWidget *do_widget)
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;
422 GtkWidget *palette = NULL;
423 GtkWidget *palette_scroller = NULL;
424 GtkWidget *notebook = NULL;
425 GtkWidget *contents = NULL;
426 GtkWidget *contents_scroller = NULL;
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);
436 g_signal_connect (window, "destroy",
437 G_CALLBACK (gtk_widget_destroyed), &window);
438 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
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);
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,
449 1, GTK_ORIENTATION_HORIZONTAL,
451 gtk_list_store_append (orientation_model, &iter);
452 gtk_list_store_set (orientation_model, &iter,
454 1, GTK_ORIENTATION_VERTICAL,
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),
463 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_orientation),
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);
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,
477 gtk_list_store_append (style_model, &iter);
478 gtk_list_store_set (style_model, &iter,
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,
487 gtk_list_store_append (style_model, &iter);
488 gtk_list_store_set (style_model, &iter,
490 1, GTK_TOOLBAR_ICONS,
492 gtk_list_store_append (style_model, &iter);
493 gtk_list_store_set (style_model, &iter,
495 1, -1, /* A custom meaning for this demo. */
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),
502 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_style),
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);
510 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 5);
511 gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 0);
513 /* Add and fill the ToolPalette: */
514 palette = gtk_tool_palette_new ();
516 load_stock_items (GTK_TOOL_PALETTE (palette));
517 load_toggle_items (GTK_TOOL_PALETTE (palette));
518 load_special_items (GTK_TOOL_PALETTE (palette));
520 palette_scroller = gtk_scrolled_window_new (NULL, NULL);
521 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (palette_scroller),
523 GTK_POLICY_AUTOMATIC);
524 gtk_container_set_border_width (GTK_CONTAINER (palette_scroller), 6);
526 gtk_container_add (GTK_CONTAINER (palette_scroller), palette);
527 gtk_container_add (GTK_CONTAINER (hbox), palette_scroller);
529 gtk_widget_show_all (box);
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);
537 /* Keep the widgets in sync: */
538 on_combo_orientation_changed (GTK_COMBO_BOX (combo_orientation), palette);
540 /* ===== notebook ===== */
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);
546 /* ===== DnD for tool items ===== */
548 g_signal_connect (palette, "drag-data-received",
549 G_CALLBACK (palette_drag_data_received), NULL);
551 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
553 GTK_DEST_DEFAULT_ALL,
554 GTK_TOOL_PALETTE_DRAG_ITEMS |
555 GTK_TOOL_PALETTE_DRAG_GROUPS,
558 /* ===== passive DnD dest ===== */
560 contents = gtk_drawing_area_new ();
561 gtk_widget_set_app_paintable (contents, TRUE);
563 g_object_connect (contents,
564 "signal::draw", canvas_draw, NULL,
565 "signal::drag-data-received", passive_canvas_drag_data_received, NULL,
568 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
570 GTK_DEST_DEFAULT_ALL,
571 GTK_TOOL_PALETTE_DRAG_ITEMS,
574 contents_scroller = gtk_scrolled_window_new (NULL, NULL);
575 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
576 GTK_POLICY_AUTOMATIC,
578 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
580 gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
582 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
584 gtk_label_new ("Passive DnD Mode"));
586 /* ===== interactive DnD dest ===== */
588 contents = gtk_drawing_area_new ();
589 gtk_widget_set_app_paintable (contents, TRUE);
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,
599 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
601 GTK_DEST_DEFAULT_HIGHLIGHT,
602 GTK_TOOL_PALETTE_DRAG_ITEMS,
605 contents_scroller = gtk_scrolled_window_new (NULL, NULL);
606 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
607 GTK_POLICY_AUTOMATIC,
609 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
611 gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
613 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), contents_scroller,
614 gtk_label_new ("Interactive DnD Mode"));
617 if (!gtk_widget_get_visible (window))
619 gtk_widget_show_all (window);
623 gtk_widget_destroy (window);
632 load_stock_items (GtkToolPalette *palette)
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;
644 stock_ids = gtk_stock_list_ids ();
645 stock_ids = g_slist_sort (stock_ids, (GCompareFunc) strcmp);
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);
652 for (iter = stock_ids; iter; iter = g_slist_next (iter))
654 GtkStockItem stock_item;
655 gchar *id = iter->data;
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);
681 if (!gtk_stock_lookup (id, &stock_item) || !stock_item.label)
682 gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), id);
687 g_slist_free (stock_ids);
691 load_toggle_items (GtkToolPalette *palette)
693 GSList *toggle_group = NULL;
699 group = gtk_tool_item_group_new ("Radio Item");
700 gtk_container_add (GTK_CONTAINER (palette), group);
702 for (i = 1; i <= 10; ++i)
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);
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));
715 create_entry_item (const char *text)
720 entry = gtk_entry_new ();
721 gtk_entry_set_text (GTK_ENTRY (entry), text);
722 gtk_entry_set_width_chars (GTK_ENTRY (entry), 5);
724 item = gtk_tool_item_new ();
725 gtk_container_add (GTK_CONTAINER (item), entry);
731 load_special_items (GtkToolPalette *palette)
735 GtkWidget *label_button;
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),
742 gtk_container_add (GTK_CONTAINER (palette), group);
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);
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,
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);
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);
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);
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);
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);
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,
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);