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_expose_event (GtkWidget *widget,
85 GdkEventExpose *event)
90 cr = gdk_cairo_create (widget->window);
91 gdk_cairo_region (cr, event->region);
94 cairo_set_source_rgb (cr, 1, 1, 1);
95 cairo_rectangle (cr, 0, 0, widget->allocation.width, widget->allocation.height);
98 for (iter = canvas_items; iter; iter = iter->next)
99 canvas_item_draw (iter->data, cr, FALSE);
102 canvas_item_draw (drop_item, cr, TRUE);
109 /*****************************/
110 /* ====== Palette DnD ====== */
111 /*****************************/
114 palette_drop_item (GtkToolItem *drag_item,
115 GtkToolItemGroup *drop_group,
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;
124 drop_position = gtk_tool_item_group_get_item_position (GTK_TOOL_ITEM_GROUP (drop_group), drop_item);
126 if (GTK_TOOL_ITEM_GROUP (drag_group) != drop_group)
128 gboolean homogeneous, expand, fill, new_row;
130 g_object_ref (drag_item);
131 gtk_container_child_get (GTK_CONTAINER (drag_group), GTK_WIDGET (drag_item),
132 "homogeneous", &homogeneous,
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,
146 g_object_unref (drag_item);
149 gtk_tool_item_group_set_item_position (GTK_TOOL_ITEM_GROUP (drop_group),
150 drag_item, drop_position);
154 palette_drop_group (GtkToolPalette *palette,
155 GtkToolItemGroup *drag_group,
156 GtkToolItemGroup *drop_group)
158 gint drop_position = -1;
161 drop_position = gtk_tool_palette_get_group_position (palette, drop_group);
163 gtk_tool_palette_set_group_position (palette, drag_group, drop_position);
167 palette_drag_data_received (GtkWidget *widget,
168 GdkDragContext *context,
171 GtkSelectionData *selection,
176 GtkToolItemGroup *drop_group = NULL;
177 GtkWidget *drag_palette = gtk_drag_get_source_widget (context);
178 GtkWidget *drag_item = NULL;
180 while (drag_palette && !GTK_IS_TOOL_PALETTE (drag_palette))
181 drag_palette = gtk_widget_get_parent (drag_palette);
185 drag_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (drag_palette),
187 drop_group = gtk_tool_palette_get_drop_group (GTK_TOOL_PALETTE (widget),
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),
195 else if (GTK_IS_TOOL_ITEM (drag_item) && drop_group)
196 palette_drop_item (GTK_TOOL_ITEM (drag_item),
198 x - GTK_WIDGET (drop_group)->allocation.x,
199 y - GTK_WIDGET (drop_group)->allocation.y);
202 /********************************/
203 /* ====== Passive Canvas ====== */
204 /********************************/
207 passive_canvas_drag_data_received (GtkWidget *widget,
208 GdkDragContext *context,
211 GtkSelectionData *selection,
216 /* find the tool button, which is the source of this DnD operation */
218 GtkWidget *palette = gtk_drag_get_source_widget (context);
219 CanvasItem *canvas_item = NULL;
220 GtkWidget *tool_item = NULL;
222 while (palette && !GTK_IS_TOOL_PALETTE (palette))
223 palette = gtk_widget_get_parent (palette);
226 tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
229 g_assert (NULL == drop_item);
231 /* append a new canvas item when a tool button was found */
233 if (GTK_IS_TOOL_ITEM (tool_item))
234 canvas_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
238 canvas_items = g_list_append (canvas_items, canvas_item);
239 gtk_widget_queue_draw (widget);
243 /************************************/
244 /* ====== Interactive Canvas ====== */
245 /************************************/
248 interactive_canvas_drag_motion (GtkWidget *widget,
249 GdkDragContext *context,
257 /* already have a drop indicator - just update position */
262 gtk_widget_queue_draw (widget);
263 gdk_drag_status (context, GDK_ACTION_COPY, time);
267 /* request DnD data for creating a drop indicator */
269 GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
274 gtk_drag_get_data (widget, context, target, time);
281 interactive_canvas_drag_data_received (GtkWidget *widget,
282 GdkDragContext *context,
285 GtkSelectionData *selection,
291 /* find the tool button which is the source of this DnD operation */
293 GtkWidget *palette = gtk_drag_get_source_widget (context);
294 GtkWidget *tool_item = NULL;
296 while (palette && !GTK_IS_TOOL_PALETTE (palette))
297 palette = gtk_widget_get_parent (palette);
300 tool_item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette),
303 /* create a drop indicator when a tool button was found */
305 g_assert (NULL == drop_item);
307 if (GTK_IS_TOOL_ITEM (tool_item))
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);
316 interactive_canvas_drag_drop (GtkWidget *widget,
317 GdkDragContext *context,
325 /* turn the drop indicator into a real canvas item */
330 canvas_items = g_list_append (canvas_items, drop_item);
333 /* signal the item was accepted and redraw */
335 gtk_drag_finish (context, TRUE, FALSE, time);
336 gtk_widget_queue_draw (widget);
345 interactive_canvas_real_drag_leave (gpointer data)
349 GtkWidget *widget = GTK_WIDGET (data);
351 canvas_item_free (drop_item);
354 gtk_widget_queue_draw (widget);
361 interactive_canvas_drag_leave (GtkWidget *widget,
362 GdkDragContext *context,
366 /* defer cleanup until a potential "drag-drop" signal was received */
367 g_idle_add (interactive_canvas_real_drag_leave, widget);
371 on_combo_orientation_changed (GtkComboBox *combo_box,
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);
380 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
383 gtk_tree_model_get (model, &iter, 1, &val, -1);
385 gtk_orientable_set_orientation (GTK_ORIENTABLE (palette), val);
387 if (val == GTK_ORIENTATION_HORIZONTAL)
388 gtk_scrolled_window_set_policy (sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
390 gtk_scrolled_window_set_policy (sw, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
394 on_combo_style_changed (GtkComboBox *combo_box,
397 GtkToolPalette *palette = GTK_TOOL_PALETTE (user_data);
398 GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
402 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
405 gtk_tree_model_get (model, &iter, 1, &val, -1);
408 gtk_tool_palette_unset_style (palette);
410 gtk_tool_palette_set_style (palette, val);
414 do_toolpalette (GtkWidget *do_widget)
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;
424 GtkWidget *palette = NULL;
425 GtkWidget *palette_scroller = NULL;
426 GtkWidget *notebook = NULL;
427 GtkWidget *contents = NULL;
428 GtkWidget *contents_scroller = NULL;
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);
438 g_signal_connect (window, "destroy",
439 G_CALLBACK (gtk_widget_destroyed), &window);
440 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
442 /* Add widgets to control the ToolPalette appearance: */
443 box = gtk_vbox_new (FALSE, 6);
444 gtk_container_add (GTK_CONTAINER (window), box);
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,
451 1, GTK_ORIENTATION_HORIZONTAL,
453 gtk_list_store_append (orientation_model, &iter);
454 gtk_list_store_set (orientation_model, &iter,
456 1, GTK_ORIENTATION_VERTICAL,
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),
465 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_orientation),
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);
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,
479 gtk_list_store_append (style_model, &iter);
480 gtk_list_store_set (style_model, &iter,
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,
489 gtk_list_store_append (style_model, &iter);
490 gtk_list_store_set (style_model, &iter,
492 1, GTK_TOOLBAR_ICONS,
494 gtk_list_store_append (style_model, &iter);
495 gtk_list_store_set (style_model, &iter,
497 1, -1, /* A custom meaning for this demo. */
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),
504 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_style),
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);
512 hbox = gtk_hbox_new (FALSE, 5);
513 gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 0);
515 /* Add and fill the ToolPalette: */
516 palette = gtk_tool_palette_new ();
518 load_stock_items (GTK_TOOL_PALETTE (palette));
519 load_toggle_items (GTK_TOOL_PALETTE (palette));
520 load_special_items (GTK_TOOL_PALETTE (palette));
522 palette_scroller = gtk_scrolled_window_new (NULL, NULL);
523 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (palette_scroller),
525 GTK_POLICY_AUTOMATIC);
526 gtk_container_set_border_width (GTK_CONTAINER (palette_scroller), 6);
528 gtk_container_add (GTK_CONTAINER (palette_scroller), palette);
529 gtk_container_add (GTK_CONTAINER (hbox), palette_scroller);
531 gtk_widget_show_all (box);
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);
539 /* Keep the widgets in sync: */
540 on_combo_orientation_changed (GTK_COMBO_BOX (combo_orientation), palette);
542 /* ===== notebook ===== */
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);
548 /* ===== DnD for tool items ===== */
550 g_signal_connect (palette, "drag-data-received",
551 G_CALLBACK (palette_drag_data_received), NULL);
553 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
555 GTK_DEST_DEFAULT_ALL,
556 GTK_TOOL_PALETTE_DRAG_ITEMS |
557 GTK_TOOL_PALETTE_DRAG_GROUPS,
560 /* ===== passive DnD dest ===== */
562 contents = gtk_drawing_area_new ();
563 gtk_widget_set_app_paintable (contents, TRUE);
565 g_object_connect (contents,
566 "signal::expose-event", canvas_expose_event, NULL,
567 "signal::drag-data-received", passive_canvas_drag_data_received, NULL,
570 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
572 GTK_DEST_DEFAULT_ALL,
573 GTK_TOOL_PALETTE_DRAG_ITEMS,
576 contents_scroller = gtk_scrolled_window_new (NULL, NULL);
577 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
578 GTK_POLICY_AUTOMATIC,
580 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
582 gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
584 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
586 gtk_label_new ("Passive DnD Mode"));
588 /* ===== interactive DnD dest ===== */
590 contents = gtk_drawing_area_new ();
591 gtk_widget_set_app_paintable (contents, TRUE);
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,
601 gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette),
603 GTK_DEST_DEFAULT_HIGHLIGHT,
604 GTK_TOOL_PALETTE_DRAG_ITEMS,
607 contents_scroller = gtk_scrolled_window_new (NULL, NULL);
608 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
609 GTK_POLICY_AUTOMATIC,
611 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller),
613 gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
615 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), contents_scroller,
616 gtk_label_new ("Interactive DnD Mode"));
619 if (!GTK_WIDGET_VISIBLE (window))
621 gtk_widget_show_all (window);
625 gtk_widget_destroy (window);
634 load_stock_items (GtkToolPalette *palette)
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;
646 stock_ids = gtk_stock_list_ids ();
647 stock_ids = g_slist_sort (stock_ids, (GCompareFunc) strcmp);
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);
654 for (iter = stock_ids; iter; iter = g_slist_next (iter))
656 GtkStockItem stock_item;
657 gchar *id = iter->data;
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);
683 if (!gtk_stock_lookup (id, &stock_item) || !stock_item.label)
684 gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), id);
689 g_slist_free (stock_ids);
693 load_toggle_items (GtkToolPalette *palette)
695 GSList *toggle_group = NULL;
701 group = gtk_tool_item_group_new ("Radio Item");
702 gtk_container_add (GTK_CONTAINER (palette), group);
704 for (i = 1; i <= 10; ++i)
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);
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));
717 create_entry_item (const char *text)
722 entry = gtk_entry_new ();
723 gtk_entry_set_text (GTK_ENTRY (entry), text);
724 gtk_entry_set_width_chars (GTK_ENTRY (entry), 5);
726 item = gtk_tool_item_new ();
727 gtk_container_add (GTK_CONTAINER (item), entry);
733 load_special_items (GtkToolPalette *palette)
737 GtkWidget *label_button;
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),
744 gtk_container_add (GTK_CONTAINER (palette), group);
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);
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,
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);
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);
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);
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);
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);
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,
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);