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,
87 GtkAllocation allocation;
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);
97 for (iter = canvas_items; iter; iter = iter->next)
98 canvas_item_draw (iter->data, cr, FALSE);
101 canvas_item_draw (drop_item, cr, TRUE);
106 /*****************************/
107 /* ====== Palette DnD ====== */
108 /*****************************/
111 palette_drop_item (GtkToolItem *drag_item,
112 GtkToolItemGroup *drop_group,
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;
121 drop_position = gtk_tool_item_group_get_item_position (GTK_TOOL_ITEM_GROUP (drop_group), drop_item);
123 if (GTK_TOOL_ITEM_GROUP (drag_group) != drop_group)
125 gboolean homogeneous, expand, fill, new_row;
127 g_object_ref (drag_item);
128 gtk_container_child_get (GTK_CONTAINER (drag_group), GTK_WIDGET (drag_item),
129 "homogeneous", &homogeneous,
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,
143 g_object_unref (drag_item);
146 gtk_tool_item_group_set_item_position (GTK_TOOL_ITEM_GROUP (drop_group),
147 drag_item, drop_position);
151 palette_drop_group (GtkToolPalette *palette,
152 GtkToolItemGroup *drag_group,
153 GtkToolItemGroup *drop_group)
155 gint drop_position = -1;
158 drop_position = gtk_tool_palette_get_group_position (palette, drop_group);
160 gtk_tool_palette_set_group_position (palette, drag_group, drop_position);
164 palette_drag_data_received (GtkWidget *widget,
165 GdkDragContext *context,
168 GtkSelectionData *selection,
173 GtkAllocation allocation;
174 GtkToolItemGroup *drop_group = NULL;
175 GtkWidget *drag_palette = gtk_drag_get_source_widget (context);
176 GtkWidget *drag_item = NULL;
178 while (drag_palette && !GTK_IS_TOOL_PALETTE (drag_palette))
179 drag_palette = gtk_widget_get_parent (drag_palette);
183 drag_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (drag_palette),
185 drop_group = gtk_tool_palette_get_drop_group (GTK_TOOL_PALETTE (widget),
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),
193 else if (GTK_IS_TOOL_ITEM (drag_item) && drop_group)
195 gtk_widget_get_allocation (GTK_WIDGET (drop_group), &allocation);
196 palette_drop_item (GTK_TOOL_ITEM (drag_item),
203 /********************************/
204 /* ====== Passive Canvas ====== */
205 /********************************/
208 passive_canvas_drag_data_received (GtkWidget *widget,
209 GdkDragContext *context,
212 GtkSelectionData *selection,
217 /* find the tool button, which is the source of this DnD operation */
219 GtkWidget *palette = gtk_drag_get_source_widget (context);
220 CanvasItem *canvas_item = NULL;
221 GtkWidget *tool_item = NULL;
223 while (palette && !GTK_IS_TOOL_PALETTE (palette))
224 palette = gtk_widget_get_parent (palette);
227 tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
230 g_assert (NULL == drop_item);
232 /* append a new canvas item when a tool button was found */
234 if (GTK_IS_TOOL_ITEM (tool_item))
235 canvas_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
239 canvas_items = g_list_append (canvas_items, canvas_item);
240 gtk_widget_queue_draw (widget);
244 /************************************/
245 /* ====== Interactive Canvas ====== */
246 /************************************/
249 interactive_canvas_drag_motion (GtkWidget *widget,
250 GdkDragContext *context,
258 /* already have a drop indicator - just update position */
263 gtk_widget_queue_draw (widget);
264 gdk_drag_status (context, GDK_ACTION_COPY, time);
268 /* request DnD data for creating a drop indicator */
270 GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
275 gtk_drag_get_data (widget, context, target, time);
282 interactive_canvas_drag_data_received (GtkWidget *widget,
283 GdkDragContext *context,
286 GtkSelectionData *selection,
292 /* find the tool button which is the source of this DnD operation */
294 GtkWidget *palette = gtk_drag_get_source_widget (context);
295 GtkWidget *tool_item = NULL;
297 while (palette && !GTK_IS_TOOL_PALETTE (palette))
298 palette = gtk_widget_get_parent (palette);
301 tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
304 /* create a drop indicator when a tool button was found */
306 g_assert (NULL == drop_item);
308 if (GTK_IS_TOOL_ITEM (tool_item))
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);
317 interactive_canvas_drag_drop (GtkWidget *widget,
318 GdkDragContext *context,
326 /* turn the drop indicator into a real canvas item */
331 canvas_items = g_list_append (canvas_items, drop_item);
334 /* signal the item was accepted and redraw */
336 gtk_drag_finish (context, TRUE, FALSE, time);
337 gtk_widget_queue_draw (widget);
346 interactive_canvas_real_drag_leave (gpointer data)
350 GtkWidget *widget = GTK_WIDGET (data);
352 canvas_item_free (drop_item);
355 gtk_widget_queue_draw (widget);
362 interactive_canvas_drag_leave (GtkWidget *widget,
363 GdkDragContext *context,
367 /* defer cleanup until a potential "drag-drop" signal was received */
368 g_idle_add (interactive_canvas_real_drag_leave, widget);
372 on_combo_orientation_changed (GtkComboBox *combo_box,
375 GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
376 GtkScrolledWindow *sw;
377 GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
381 sw = GTK_SCROLLED_WINDOW (gtk_widget_get_parent (GTK_WIDGET (palette)));
383 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
386 gtk_tree_model_get (model, &iter, 1, &val, -1);
388 gtk_orientable_set_orientation (GTK_ORIENTABLE (palette), val);
390 if (val == GTK_ORIENTATION_HORIZONTAL)
391 gtk_scrolled_window_set_policy (sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
393 gtk_scrolled_window_set_policy (sw, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
397 on_combo_style_changed (GtkComboBox *combo_box,
400 GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
401 GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
405 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
408 gtk_tree_model_get (model, &iter, 1, &val, -1);
411 gtk_tool_palette_unset_style (palette);
413 gtk_tool_palette_set_style (palette, val);
417 do_toolpalette (GtkWidget *do_widget)
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;
427 GtkWidget *palette = NULL;
428 GtkWidget *palette_scroller = NULL;
429 GtkWidget *notebook = NULL;
430 GtkWidget *contents = NULL;
431 GtkWidget *contents_scroller = NULL;
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);
441 g_signal_connect (window, "destroy",
442 G_CALLBACK (gtk_widget_destroyed), &window);
443 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
445 /* Add widgets to control the ToolPalette appearance: */
446 box = gtk_vbox_new (FALSE, 6);
447 gtk_container_add (GTK_CONTAINER (window), box);
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,
454 1, GTK_ORIENTATION_HORIZONTAL,
456 gtk_list_store_append (orientation_model, &iter);
457 gtk_list_store_set (orientation_model, &iter,
459 1, GTK_ORIENTATION_VERTICAL,
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),
468 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_orientation),
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);
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,
482 gtk_list_store_append (style_model, &iter);
483 gtk_list_store_set (style_model, &iter,
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,
492 gtk_list_store_append (style_model, &iter);
493 gtk_list_store_set (style_model, &iter,
495 1, GTK_TOOLBAR_ICONS,
497 gtk_list_store_append (style_model, &iter);
498 gtk_list_store_set (style_model, &iter,
500 1, -1, /* A custom meaning for this demo. */
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),
507 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_style),
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);
515 hbox = gtk_hbox_new (FALSE, 5);
516 gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 0);
518 /* Add and fill the ToolPalette: */
519 palette = gtk_tool_palette_new ();
521 load_stock_items (GTK_TOOL_PALETTE (palette));
522 load_toggle_items (GTK_TOOL_PALETTE (palette));
523 load_special_items (GTK_TOOL_PALETTE (palette));
525 palette_scroller = gtk_scrolled_window_new (NULL, NULL);
526 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (palette_scroller),
528 GTK_POLICY_AUTOMATIC);
529 gtk_container_set_border_width (GTK_CONTAINER (palette_scroller), 6);
531 gtk_container_add (GTK_CONTAINER (palette_scroller), palette);
532 gtk_container_add (GTK_CONTAINER (hbox), palette_scroller);
534 gtk_widget_show_all (box);
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);
542 /* Keep the widgets in sync: */
543 on_combo_orientation_changed (GTK_COMBO_BOX (combo_orientation), palette);
545 /* ===== notebook ===== */
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);
551 /* ===== DnD for tool items ===== */
553 g_signal_connect (palette, "drag-data-received",
554 G_CALLBACK (palette_drag_data_received), NULL);
556 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
558 GTK_DEST_DEFAULT_ALL,
559 GTK_TOOL_PALETTE_DRAG_ITEMS |
560 GTK_TOOL_PALETTE_DRAG_GROUPS,
563 /* ===== passive DnD dest ===== */
565 contents = gtk_drawing_area_new ();
566 gtk_widget_set_app_paintable (contents, TRUE);
568 g_object_connect (contents,
569 "signal::draw", canvas_draw, NULL,
570 "signal::drag-data-received", passive_canvas_drag_data_received, NULL,
573 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
575 GTK_DEST_DEFAULT_ALL,
576 GTK_TOOL_PALETTE_DRAG_ITEMS,
579 contents_scroller = gtk_scrolled_window_new (NULL, NULL);
580 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
581 GTK_POLICY_AUTOMATIC,
583 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
585 gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
587 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
589 gtk_label_new ("Passive DnD Mode"));
591 /* ===== interactive DnD dest ===== */
593 contents = gtk_drawing_area_new ();
594 gtk_widget_set_app_paintable (contents, TRUE);
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,
604 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
606 GTK_DEST_DEFAULT_HIGHLIGHT,
607 GTK_TOOL_PALETTE_DRAG_ITEMS,
610 contents_scroller = gtk_scrolled_window_new (NULL, NULL);
611 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
612 GTK_POLICY_AUTOMATIC,
614 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
616 gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
618 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), contents_scroller,
619 gtk_label_new ("Interactive DnD Mode"));
622 if (!gtk_widget_get_visible (window))
624 gtk_widget_show_all (window);
628 gtk_widget_destroy (window);
637 load_stock_items (GtkToolPalette *palette)
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;
649 stock_ids = gtk_stock_list_ids ();
650 stock_ids = g_slist_sort (stock_ids, (GCompareFunc) strcmp);
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);
657 for (iter = stock_ids; iter; iter = g_slist_next (iter))
659 GtkStockItem stock_item;
660 gchar *id = iter->data;
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);
686 if (!gtk_stock_lookup (id, &stock_item) || !stock_item.label)
687 gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), id);
692 g_slist_free (stock_ids);
696 load_toggle_items (GtkToolPalette *palette)
698 GSList *toggle_group = NULL;
704 group = gtk_tool_item_group_new ("Radio Item");
705 gtk_container_add (GTK_CONTAINER (palette), group);
707 for (i = 1; i <= 10; ++i)
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);
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));
720 create_entry_item (const char *text)
725 entry = gtk_entry_new ();
726 gtk_entry_set_text (GTK_ENTRY (entry), text);
727 gtk_entry_set_width_chars (GTK_ENTRY (entry), 5);
729 item = gtk_tool_item_new ();
730 gtk_container_add (GTK_CONTAINER (item), entry);
736 load_special_items (GtkToolPalette *palette)
740 GtkWidget *label_button;
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),
747 gtk_container_add (GTK_CONTAINER (palette), group);
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);
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,
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);
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);
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);
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);
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);
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,
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);