2 * Copyright (C) 2003-2004 Marco Pesenti Gritti
3 * Copyright (C) 2004 Christian Persch
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include "egg-editable-toolbar.h"
27 #include "egg-toolbars-model.h"
28 #include "egg-toolbar-editor.h"
30 #include <gtk/gtkvseparator.h>
31 #include <gtk/gtkiconfactory.h>
32 #include <gtk/gtkwindow.h>
33 #include <gtk/gtkmain.h>
34 #include <gtk/gtkdnd.h>
35 #include <gtk/gtkhbox.h>
36 #include <gtk/gtkimage.h>
37 #include <gtk/gtkimagemenuitem.h>
38 #include <gtk/gtkmenu.h>
39 #include <gtk/gtkstock.h>
40 #include <gtk/gtktoolbar.h>
41 #include <gtk/gtktoolitem.h>
42 #include <gtk/gtkseparatortoolitem.h>
43 #include <glib/gi18n.h>
46 static void egg_editable_toolbar_class_init (EggEditableToolbarClass *klass);
47 static void egg_editable_toolbar_init (EggEditableToolbar *t);
48 static void egg_editable_toolbar_finalize (GObject *object);
50 #define MIN_TOOLBAR_HEIGHT 20
52 static GtkTargetEntry dest_drag_types[] = {
53 {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0},
55 static int n_dest_drag_types = G_N_ELEMENTS (dest_drag_types);
70 static guint egg_editable_toolbar_signals[LAST_SIGNAL] = { 0 };
72 static GObjectClass *parent_class = NULL;
74 #define EGG_EDITABLE_TOOLBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_EDITABLE_TOOLBAR, EggEditableToolbarPrivate))
76 struct EggEditableToolbarPrivate
78 GtkUIManager *manager;
79 EggToolbarsModel *model;
81 GtkWidget *selected_toolbar;
83 GtkWidget *fixed_toolbar;
86 GtkToolbar *target_toolbar;
87 GtkWidget *dragged_item;
91 egg_editable_toolbar_get_type (void)
93 static GType egg_editable_toolbar_type = 0;
95 if (egg_editable_toolbar_type == 0)
97 static const GTypeInfo our_info = {
98 sizeof (EggEditableToolbarClass),
100 NULL, /* base_finalize */
101 (GClassInitFunc) egg_editable_toolbar_class_init,
103 NULL, /* class_data */
104 sizeof (EggEditableToolbar),
106 (GInstanceInitFunc) egg_editable_toolbar_init
109 egg_editable_toolbar_type = g_type_register_static (GTK_TYPE_VBOX,
110 "EggEditableToolbar",
114 return egg_editable_toolbar_type;
118 get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar)
123 l = gtk_container_get_children (GTK_CONTAINER (etoolbar));
124 result = g_list_index (l, toolbar->parent);
131 get_n_toolbars (EggEditableToolbar *etoolbar)
136 l = gtk_container_get_children (GTK_CONTAINER (etoolbar));
137 result = g_list_length (l);
144 get_dock_nth (EggEditableToolbar *etoolbar,
150 l = gtk_container_get_children (GTK_CONTAINER (etoolbar));
151 result = g_list_nth_data (l, position);
158 get_toolbar_nth (EggEditableToolbar *etoolbar,
165 dock = get_dock_nth (etoolbar, position);
167 l = gtk_container_get_children (GTK_CONTAINER (dock));
168 result = GTK_WIDGET (l->data);
175 find_action (EggEditableToolbar *t,
179 GtkAction *action = NULL;
181 l = gtk_ui_manager_get_action_groups (t->priv->manager);
183 g_return_val_if_fail (name != NULL, NULL);
185 for (; l != NULL; l = l->next)
189 tmp = gtk_action_group_get_action (GTK_ACTION_GROUP (l->data), name);
198 drag_data_delete_cb (GtkWidget *widget,
199 GdkDragContext *context,
200 EggEditableToolbar *etoolbar)
202 int pos, toolbar_pos;
204 g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar));
206 pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (widget->parent),
207 GTK_TOOL_ITEM (widget));
208 toolbar_pos = get_toolbar_position (etoolbar, widget->parent);
210 egg_toolbars_model_remove_item (etoolbar->priv->model,
215 drag_begin_cb (GtkWidget *widget,
216 GdkDragContext *context,
217 EggEditableToolbar *etoolbar)
219 gtk_widget_hide (widget);
223 drag_end_cb (GtkWidget *widget,
224 GdkDragContext *context,
225 EggEditableToolbar *etoolbar)
227 gtk_widget_show (widget);
231 drag_data_get_cb (GtkWidget *widget,
232 GdkDragContext *context,
233 GtkSelectionData *selection_data,
236 EggEditableToolbar *etoolbar)
238 const char *id, *type;
241 g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar));
243 type = g_object_get_data (G_OBJECT (widget), "type");
244 id = g_object_get_data (G_OBJECT (widget), "id");
245 if (strcmp (id, "separator") == 0)
247 target = g_strdup (id);
251 target = egg_toolbars_model_get_item_data (etoolbar->priv->model,
255 gtk_selection_data_set (selection_data,
256 selection_data->target, 8, (unsigned char *)target, strlen (target));
262 set_drag_cursor (GtkWidget *widget)
269 pixbuf = gdk_pixbuf_new_from_file (CURSOR_DIR "/hand-open.png", NULL);
270 cursor = gdk_cursor_new_from_pixbuf (gdk_display_get_default (),
272 gdk_window_set_cursor (widget->window, cursor);
273 gdk_cursor_unref (cursor);
274 g_object_unref (pixbuf);
279 unset_drag_cursor (GtkWidget *widget)
283 gdk_window_set_cursor (widget->window, NULL);
288 set_item_drag_source (EggToolbarsModel *model,
291 gboolean is_separator,
294 GtkTargetEntry target_entry;
297 target_entry.target = (char *)type;
298 target_entry.flags = GTK_TARGET_SAME_APP;
299 target_entry.info = 0;
301 gtk_drag_source_set (item, GDK_BUTTON1_MASK,
312 icon = _egg_editable_toolbar_new_separator_image ();
313 pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (icon));
314 gtk_drag_source_set_icon_pixbuf (item, pixbuf);
318 const char *stock_id;
319 GValue value = { 0, };
322 id = gtk_action_get_name (action);
324 g_value_init (&value, G_TYPE_STRING);
325 g_object_get_property (G_OBJECT (action), "stock_id", &value);
326 stock_id = g_value_get_string (&value);
328 if (stock_id != NULL)
330 pixbuf = gtk_widget_render_icon (item, stock_id,
331 GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
335 pixbuf = gtk_widget_render_icon (item, GTK_STOCK_DND,
336 GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
339 gtk_drag_source_set_icon_pixbuf (item, pixbuf);
340 g_object_unref (pixbuf);
342 g_value_unset (&value);
345 g_object_set_data_full (G_OBJECT (item), "id",
346 g_strdup (id), g_free);
347 g_object_set_data_full (G_OBJECT (item), "type",
348 g_strdup (type), g_free);
352 create_item_from_action (EggEditableToolbar *t,
353 const char *action_name,
355 gboolean is_separator,
356 GtkAction **ret_action)
363 item = GTK_WIDGET (gtk_separator_tool_item_new ());
368 g_return_val_if_fail (action_name != NULL, NULL);
370 g_signal_emit (G_OBJECT (t), egg_editable_toolbar_signals[ACTION_REQUEST],
373 action = find_action (t, action_name);
376 item = gtk_action_create_tool_item (action);
384 gtk_widget_show (item);
386 g_signal_connect (item, "drag_begin",
387 G_CALLBACK (drag_begin_cb), t);
388 g_signal_connect (item, "drag_end",
389 G_CALLBACK (drag_end_cb), t);
390 g_signal_connect (item, "drag_data_get",
391 G_CALLBACK (drag_data_get_cb), t);
392 g_signal_connect (item, "drag_data_delete",
393 G_CALLBACK (drag_data_delete_cb), t);
395 if (t->priv->edit_mode)
397 set_drag_cursor (item);
398 gtk_widget_set_sensitive (item, TRUE);
399 set_item_drag_source (t->priv->model, item, action,
401 gtk_tool_item_set_use_drag_window (GTK_TOOL_ITEM (item), TRUE);
406 *ret_action = action;
413 create_item (EggEditableToolbar *t,
414 EggToolbarsModel *model,
415 int toolbar_position,
417 GtkAction **ret_action)
419 const char *action_name, *type;
420 gboolean is_separator;
422 egg_toolbars_model_item_nth (model, toolbar_position, position,
423 &is_separator, &action_name, &type);
424 return create_item_from_action (t, action_name, type,
425 is_separator, ret_action);
429 data_is_separator (const char *data)
431 return strcmp (data, "separator") == 0;
435 drag_data_received_cb (GtkWidget *widget,
436 GdkDragContext *context,
439 GtkSelectionData *selection_data,
442 EggEditableToolbar *etoolbar)
449 target = gtk_drag_dest_find_target (widget, context, NULL);
450 type = egg_toolbars_model_get_item_type (etoolbar->priv->model, target);
451 id = egg_toolbars_model_get_item_id (etoolbar->priv->model, type, (char *)selection_data->data);
453 /* This function can be called for two reasons
455 * (1) drag_motion() needs an item to pass to
456 * gtk_toolbar_set_drop_highlight_item(). We can
457 * recognize this case by etoolbar->priv->pending being TRUE
458 * We should just create an item and return.
460 * (2) The drag has finished, and drag_drop() wants us to
461 * actually add a new item to the toolbar.
466 etoolbar->priv->pending = FALSE;
471 if (etoolbar->priv->pending)
473 etoolbar->priv->pending = FALSE;
474 etoolbar->priv->dragged_item =
475 create_item_from_action (etoolbar, id, type,
476 data_is_separator (id), NULL);
477 g_object_ref (etoolbar->priv->dragged_item);
478 gtk_object_sink (GTK_OBJECT (etoolbar->priv->dragged_item));
482 int pos, toolbar_pos;
484 pos = gtk_toolbar_get_drop_index (GTK_TOOLBAR (widget), x, y);
485 toolbar_pos = get_toolbar_position (etoolbar, widget);
487 if (data_is_separator ((char *)selection_data->data))
489 egg_toolbars_model_add_separator (etoolbar->priv->model,
494 egg_toolbars_model_add_item (etoolbar->priv->model,
495 toolbar_pos, pos, id, type);
498 gtk_drag_finish (context, TRUE, context->action == GDK_ACTION_MOVE,
507 remove_toolbar_cb (GtkWidget *menuitem,
508 EggEditableToolbar *etoolbar)
512 pos = get_toolbar_position (etoolbar, etoolbar->priv->selected_toolbar);
513 egg_toolbars_model_remove_toolbar (etoolbar->priv->model, pos);
517 popup_toolbar_context_menu_cb (GtkWidget *toolbar,
521 EggEditableToolbar *t)
527 if (t->priv->edit_mode)
529 EggTbModelFlags flags;
532 t->priv->selected_toolbar = toolbar;
534 menu = gtk_menu_new ();
536 item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Toolbar"));
537 gtk_widget_show (item);
538 image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
539 gtk_widget_show (image);
540 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
541 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
542 g_signal_connect (item, "activate",
543 G_CALLBACK (remove_toolbar_cb),
546 position = get_toolbar_position (t, toolbar);
547 flags = egg_toolbars_model_get_flags (t->priv->model, position);
548 if (flags & EGG_TB_MODEL_NOT_REMOVABLE)
550 gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
553 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 2,
554 gtk_get_current_event_time ());
559 free_dragged_item (EggEditableToolbar *etoolbar)
561 if (etoolbar->priv->dragged_item)
563 gtk_widget_destroy (etoolbar->priv->dragged_item);
564 g_object_unref (etoolbar->priv->dragged_item);
565 etoolbar->priv->dragged_item = NULL;
570 toolbar_drag_drop_cb (GtkWidget *widget,
571 GdkDragContext *context,
575 EggEditableToolbar *etoolbar)
579 target = gtk_drag_dest_find_target (widget, context, NULL);
580 if (target != GDK_NONE)
582 gtk_drag_get_data (widget, context,
588 free_dragged_item (etoolbar);
594 toolbar_drag_motion_cb (GtkWidget *widget,
595 GdkDragContext *context,
599 EggEditableToolbar *etoolbar)
603 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
607 source = gtk_drag_get_source_widget (context);
610 EggTbModelFlags flags;
614 pos = get_toolbar_position (etoolbar, widget);
615 flags = egg_toolbars_model_get_flags (etoolbar->priv->model, pos);
617 is_item = etoolbar->priv->edit_mode &&
618 (gtk_widget_get_ancestor (source, EGG_TYPE_EDITABLE_TOOLBAR) ||
619 gtk_widget_get_ancestor (source, EGG_TYPE_TOOLBAR_EDITOR));
621 if ((flags & EGG_TB_MODEL_ACCEPT_ITEMS_ONLY) && !is_item)
623 gdk_drag_status (context, 0, time);
627 if (gtk_widget_is_ancestor (source, widget))
629 context->suggested_action = GDK_ACTION_MOVE;
633 target = gtk_drag_dest_find_target (widget, context, NULL);
634 if (target == GDK_NONE)
636 gdk_drag_status (context, 0, time);
640 if (etoolbar->priv->target_toolbar != toolbar)
642 if (etoolbar->priv->target_toolbar)
643 gtk_toolbar_set_drop_highlight_item
644 (etoolbar->priv->target_toolbar, NULL, 0);
646 free_dragged_item (etoolbar);
647 etoolbar->priv->pending = TRUE;
649 etoolbar->priv->target_toolbar = toolbar;
651 gtk_drag_get_data (widget, context, target, time);
654 if (etoolbar->priv->dragged_item != NULL &&
655 etoolbar->priv->edit_mode)
657 item = GTK_TOOL_ITEM (etoolbar->priv->dragged_item);
659 index = gtk_toolbar_get_drop_index (toolbar, x, y);
660 gtk_toolbar_set_drop_highlight_item (toolbar, item, index);
663 gdk_drag_status (context, context->suggested_action, time);
669 toolbar_drag_leave_cb (GtkToolbar *toolbar,
670 GdkDragContext *context,
672 EggEditableToolbar *etoolbar)
674 /* This is a workaround for bug 125557. Sometimes
675 * we seemingly enter another toolbar *before* leaving
678 * In that case etoolbar->priv->target_toolbar will
679 * have been set to something else and the highlighting
680 * will already have been turned off
683 if (etoolbar->priv->target_toolbar == toolbar)
685 gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0);
687 etoolbar->priv->target_toolbar = NULL;
688 free_dragged_item (etoolbar);
693 create_dock (EggEditableToolbar *t)
695 GtkWidget *toolbar, *hbox;
697 hbox = gtk_hbox_new (0, FALSE);
698 gtk_widget_show (hbox);
700 toolbar = gtk_toolbar_new ();
701 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), TRUE);
702 gtk_widget_show (toolbar);
703 gtk_box_pack_start (GTK_BOX (hbox), toolbar, TRUE, TRUE, 0);
705 gtk_drag_dest_set (toolbar, 0,
706 dest_drag_types, n_dest_drag_types,
707 GDK_ACTION_MOVE | GDK_ACTION_COPY);
709 g_signal_connect (toolbar, "drag_drop",
710 G_CALLBACK (toolbar_drag_drop_cb), t);
711 g_signal_connect (toolbar, "drag_motion",
712 G_CALLBACK (toolbar_drag_motion_cb), t);
713 g_signal_connect (toolbar, "drag_leave",
714 G_CALLBACK (toolbar_drag_leave_cb), t);
716 g_signal_connect (toolbar, "drag_data_received",
717 G_CALLBACK (drag_data_received_cb), t);
718 g_signal_connect (toolbar, "popup_context_menu",
719 G_CALLBACK (popup_toolbar_context_menu_cb), t);
725 set_fixed_style (EggEditableToolbar *t, GtkToolbarStyle style)
727 g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar));
728 gtk_toolbar_set_style (GTK_TOOLBAR (t->priv->fixed_toolbar), style);
732 unset_fixed_style (EggEditableToolbar *t)
734 g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar));
735 gtk_toolbar_unset_style (GTK_TOOLBAR (t->priv->fixed_toolbar));
739 toolbar_changed_cb (EggToolbarsModel *model,
741 EggEditableToolbar *t)
744 EggTbModelFlags flags;
745 GtkToolbarStyle style;
747 flags = egg_toolbars_model_get_flags (model, position);
748 toolbar = get_toolbar_nth (t, position);
750 if (flags & EGG_TB_MODEL_ICONS_ONLY)
752 style = GTK_TOOLBAR_ICONS;
754 else if (flags & EGG_TB_MODEL_TEXT_ONLY)
756 style = GTK_TOOLBAR_TEXT;
758 else if (flags & EGG_TB_MODEL_ICONS_TEXT)
760 style = GTK_TOOLBAR_BOTH;
762 else if (flags & EGG_TB_MODEL_ICONS_TEXT_HORIZ)
764 style = GTK_TOOLBAR_BOTH_HORIZ;
768 gtk_toolbar_unset_style (GTK_TOOLBAR (toolbar));
769 if (position == 0 && t->priv->fixed_toolbar)
771 unset_fixed_style (t);
776 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), style);
777 if (position == 0 && t->priv->fixed_toolbar)
779 set_fixed_style (t, style);
784 unparent_fixed (EggEditableToolbar *t)
786 GtkWidget *toolbar, *dock;
787 g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar));
789 toolbar = t->priv->fixed_toolbar;
790 dock = get_dock_nth (t, 0);
792 if (dock && toolbar->parent != NULL)
794 gtk_container_remove (GTK_CONTAINER (dock), toolbar);
799 update_fixed (EggEditableToolbar *t)
801 GtkWidget *toolbar, *dock;
802 if (!t->priv->fixed_toolbar) return;
804 toolbar = t->priv->fixed_toolbar;
805 dock = get_dock_nth (t, 0);
807 if (dock && toolbar && toolbar->parent == NULL)
809 gtk_box_pack_end (GTK_BOX (dock), toolbar, FALSE, TRUE, 0);
811 gtk_widget_show_all (toolbar);
816 toolbar_added_cb (EggToolbarsModel *model,
818 EggEditableToolbar *t)
822 dock = create_dock (t);
824 gtk_widget_set_size_request (dock, -1, MIN_TOOLBAR_HEIGHT);
826 gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0);
828 gtk_box_reorder_child (GTK_BOX (t), dock, position);
830 gtk_widget_show_all (dock);
836 toolbar_removed_cb (EggToolbarsModel *model,
838 EggEditableToolbar *t)
842 toolbar = get_dock_nth (t, position);
843 gtk_widget_destroy (toolbar);
849 item_added_cb (EggToolbarsModel *model,
850 int toolbar_position,
852 EggEditableToolbar *t)
859 toolbar = get_toolbar_nth (t, toolbar_position);
860 item = create_item (t, model, toolbar_position, position, &action);
861 gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
862 GTK_TOOL_ITEM (item), position);
864 dock = get_dock_nth (t, toolbar_position);
865 gtk_widget_set_size_request (dock, -1, -1);
866 gtk_widget_queue_resize_no_redraw (dock);
868 /* FIXME Hack to make tooltip work from gtk */
871 g_object_notify (G_OBJECT (action), "tooltip");
876 item_removed_cb (EggToolbarsModel *model,
877 int toolbar_position,
879 EggEditableToolbar *t)
884 toolbar = get_toolbar_nth (t, toolbar_position);
885 item = GTK_WIDGET (gtk_toolbar_get_nth_item
886 (GTK_TOOLBAR (toolbar), position));
887 g_return_if_fail (item != NULL);
888 gtk_container_remove (GTK_CONTAINER (toolbar), item);
890 if (egg_toolbars_model_n_items (model, toolbar_position) == 0)
892 egg_toolbars_model_remove_toolbar (model, toolbar_position);
897 egg_editable_toolbar_construct (EggEditableToolbar *t)
899 int i, l, n_items, n_toolbars;
900 EggToolbarsModel *model = t->priv->model;
902 g_return_if_fail (model != NULL);
903 g_return_if_fail (t->priv->manager != NULL);
905 n_toolbars = egg_toolbars_model_n_toolbars (model);
907 for (i = 0; i < n_toolbars; i++)
909 GtkWidget *toolbar, *dock;
910 EggTbModelFlags flags;
912 dock = create_dock (t);
913 gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0);
914 toolbar = get_toolbar_nth (t, i);
916 flags = egg_toolbars_model_get_flags (model, i);
917 if (flags & EGG_TB_MODEL_ICONS_ONLY)
919 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
920 if (i == 0 && t->priv->fixed_toolbar)
922 set_fixed_style (t, GTK_TOOLBAR_ICONS);
926 n_items = egg_toolbars_model_n_items (model, i);
927 for (l = 0; l < n_items; l++)
932 item = create_item (t, model, i, l, &action);
935 gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
936 GTK_TOOL_ITEM (item), l);
937 /* FIXME Hack to make tooltip work from gtk */
940 g_object_notify (G_OBJECT (action), "tooltip");
945 egg_toolbars_model_remove_item (model, i, l);
953 gtk_widget_set_size_request (dock, -1, MIN_TOOLBAR_HEIGHT);
961 egg_editable_toolbar_disconnect_model (EggEditableToolbar *toolbar)
963 EggToolbarsModel *model = toolbar->priv->model;
965 g_signal_handlers_disconnect_by_func
966 (model, G_CALLBACK (item_added_cb), toolbar);
967 g_signal_handlers_disconnect_by_func
968 (model, G_CALLBACK (item_removed_cb), toolbar);
969 g_signal_handlers_disconnect_by_func
970 (model, G_CALLBACK (toolbar_added_cb), toolbar);
971 g_signal_handlers_disconnect_by_func
972 (model, G_CALLBACK (toolbar_removed_cb), toolbar);
973 g_signal_handlers_disconnect_by_func
974 (model, G_CALLBACK (toolbar_changed_cb), toolbar);
978 egg_editable_toolbar_deconstruct (EggEditableToolbar *toolbar)
980 EggToolbarsModel *model = toolbar->priv->model;
983 g_return_if_fail (model != NULL);
985 if (toolbar->priv->fixed_toolbar)
987 unset_fixed_style (toolbar);
988 unparent_fixed (toolbar);
991 children = gtk_container_get_children (GTK_CONTAINER (toolbar));
992 g_list_foreach (children, (GFunc) gtk_widget_destroy, NULL);
993 g_list_free (children);
997 egg_editable_toolbar_set_model (EggEditableToolbar *toolbar,
998 EggToolbarsModel *model)
1000 g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model));
1001 g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (toolbar));
1002 g_return_if_fail (toolbar->priv->manager);
1004 if (toolbar->priv->model == model) return;
1006 if (toolbar->priv->model)
1008 egg_editable_toolbar_disconnect_model (toolbar);
1009 egg_editable_toolbar_deconstruct (toolbar);
1011 g_object_unref (toolbar->priv->model);
1014 toolbar->priv->model = g_object_ref (model);
1016 egg_editable_toolbar_construct (toolbar);
1018 g_signal_connect (model, "item_added",
1019 G_CALLBACK (item_added_cb), toolbar);
1020 g_signal_connect (model, "item_removed",
1021 G_CALLBACK (item_removed_cb), toolbar);
1022 g_signal_connect (model, "toolbar_added",
1023 G_CALLBACK (toolbar_added_cb), toolbar);
1024 g_signal_connect (model, "toolbar_removed",
1025 G_CALLBACK (toolbar_removed_cb), toolbar);
1026 g_signal_connect (model, "toolbar_changed",
1027 G_CALLBACK (toolbar_changed_cb), toolbar);
1031 egg_editable_toolbar_set_ui_manager (EggEditableToolbar *t,
1032 GtkUIManager *manager)
1034 g_return_if_fail (GTK_IS_UI_MANAGER (manager));
1036 t->priv->manager = g_object_ref (manager);
1040 egg_editable_toolbar_set_property (GObject *object,
1042 const GValue *value,
1045 EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object);
1049 case PROP_UI_MANAGER:
1050 egg_editable_toolbar_set_ui_manager (t, g_value_get_object (value));
1052 case PROP_TOOLBARS_MODEL:
1053 egg_editable_toolbar_set_model (t, g_value_get_object (value));
1056 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1062 egg_editable_toolbar_get_property (GObject *object,
1067 EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object);
1071 case PROP_UI_MANAGER:
1072 g_value_set_object (value, t->priv->manager);
1074 case PROP_TOOLBARS_MODEL:
1075 g_value_set_object (value, t->priv->model);
1078 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1084 egg_editable_toolbar_class_init (EggEditableToolbarClass *klass)
1086 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1088 parent_class = g_type_class_peek_parent (klass);
1090 object_class->finalize = egg_editable_toolbar_finalize;
1091 object_class->set_property = egg_editable_toolbar_set_property;
1092 object_class->get_property = egg_editable_toolbar_get_property;
1094 egg_editable_toolbar_signals[ACTION_REQUEST] =
1095 g_signal_new ("action_request",
1096 G_OBJECT_CLASS_TYPE (object_class),
1098 G_STRUCT_OFFSET (EggEditableToolbarClass, action_request),
1099 NULL, NULL, g_cclosure_marshal_VOID__STRING,
1100 G_TYPE_NONE, 1, G_TYPE_STRING);
1102 g_object_class_install_property (object_class,
1104 g_param_spec_object ("ui-manager",
1107 GTK_TYPE_UI_MANAGER,
1108 G_PARAM_READWRITE));
1109 g_object_class_install_property (object_class,
1110 PROP_TOOLBARS_MODEL,
1111 g_param_spec_object ("model",
1114 EGG_TYPE_TOOLBARS_MODEL,
1115 G_PARAM_READWRITE));
1117 g_type_class_add_private (object_class, sizeof (EggEditableToolbarPrivate));
1121 egg_editable_toolbar_init (EggEditableToolbar *t)
1123 t->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (t);
1127 egg_editable_toolbar_finalize (GObject *object)
1129 EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object);
1131 if (t->priv->fixed_toolbar)
1133 g_object_unref (t->priv->fixed_toolbar);
1136 if (t->priv->manager)
1138 g_object_unref (t->priv->manager);
1143 egg_editable_toolbar_disconnect_model (t);
1144 g_object_unref (t->priv->model);
1147 G_OBJECT_CLASS (parent_class)->finalize (object);
1151 egg_editable_toolbar_new (GtkUIManager *manager)
1153 return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
1154 "ui-manager", manager,
1159 egg_editable_toolbar_new_with_model (GtkUIManager *manager,
1160 EggToolbarsModel *model)
1162 return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
1163 "ui-manager", manager,
1169 egg_editable_toolbar_get_edit_mode (EggEditableToolbar *etoolbar)
1171 return etoolbar->priv->edit_mode;
1175 egg_editable_toolbar_set_edit_mode (EggEditableToolbar *etoolbar,
1178 int i, l, n_toolbars, n_items;
1180 etoolbar->priv->edit_mode = mode;
1182 n_toolbars = get_n_toolbars (etoolbar);
1183 for (i = 0; i < n_toolbars; i++)
1187 toolbar = get_toolbar_nth (etoolbar, i);
1188 n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar));
1189 for (l = 0; l < n_items; l++)
1192 const char *action_name, *type;
1193 gboolean is_separator;
1194 GtkAction *action = NULL;
1196 egg_toolbars_model_item_nth (etoolbar->priv->model, i, l,
1197 &is_separator, &action_name, &type);
1198 action = find_action (etoolbar, action_name);
1200 item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), l);
1201 gtk_tool_item_set_use_drag_window (item, mode);
1205 set_drag_cursor (GTK_WIDGET (item));
1206 gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
1207 set_item_drag_source (etoolbar->priv->model, GTK_WIDGET (item),
1208 action, is_separator, type);
1212 unset_drag_cursor (GTK_WIDGET (item));
1213 gtk_drag_source_unset (GTK_WIDGET (item));
1217 g_object_notify (G_OBJECT (action), "sensitive");
1225 egg_editable_toolbar_show (EggEditableToolbar *etoolbar,
1229 EggToolbarsModel *model = etoolbar->priv->model;
1231 g_return_if_fail (model != NULL);
1233 n_toolbars = egg_toolbars_model_n_toolbars (model);
1234 for (i = 0; i < n_toolbars; i++)
1236 const char *toolbar_name;
1238 toolbar_name = egg_toolbars_model_toolbar_nth (model, i);
1239 if (strcmp (toolbar_name, name) == 0)
1241 gtk_widget_show (get_dock_nth (etoolbar, i));
1247 egg_editable_toolbar_hide (EggEditableToolbar *etoolbar,
1251 EggToolbarsModel *model = etoolbar->priv->model;
1253 g_return_if_fail (model != NULL);
1255 n_toolbars = egg_toolbars_model_n_toolbars (model);
1256 for (i = 0; i < n_toolbars; i++)
1258 const char *toolbar_name;
1260 toolbar_name = egg_toolbars_model_toolbar_nth (model, i);
1261 if (strcmp (toolbar_name, name) == 0)
1263 gtk_widget_hide (get_dock_nth (etoolbar, i));
1269 egg_editable_toolbar_set_fixed (EggEditableToolbar *toolbar,
1272 g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (toolbar));
1273 g_return_if_fail (!fixed || GTK_IS_TOOL_ITEM (fixed));
1275 if (!toolbar->priv->fixed_toolbar)
1277 toolbar->priv->fixed_toolbar = gtk_toolbar_new ();
1278 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar->priv->fixed_toolbar), FALSE);
1279 g_object_ref (toolbar->priv->fixed_toolbar);
1280 gtk_object_sink (GTK_OBJECT (toolbar->priv->fixed_toolbar));
1283 if (toolbar->priv->fixed)
1285 gtk_container_remove (GTK_CONTAINER (toolbar->priv->fixed_toolbar),
1286 GTK_WIDGET (toolbar->priv->fixed));
1287 g_object_unref (toolbar->priv->fixed);
1290 toolbar->priv->fixed = fixed;
1294 g_object_ref (fixed);
1295 gtk_object_sink (GTK_OBJECT (fixed));
1297 gtk_toolbar_insert (GTK_TOOLBAR (toolbar->priv->fixed_toolbar), fixed, 0);
1302 egg_editable_toolbar_set_drag_dest (EggEditableToolbar *etoolbar,
1303 const GtkTargetEntry *targets,
1305 const char *toolbar_name)
1308 EggToolbarsModel *model = etoolbar->priv->model;
1310 g_return_if_fail (model != NULL);
1312 n_toolbars = egg_toolbars_model_n_toolbars (model);
1313 for (i = 0; i < n_toolbars; i++)
1317 name = egg_toolbars_model_toolbar_nth (model, i);
1318 if (strcmp (toolbar_name, name) == 0)
1320 GtkWidget *widget = get_toolbar_nth (etoolbar, i);
1322 gtk_drag_dest_unset (widget);
1323 gtk_drag_dest_set (widget, 0,
1325 GDK_ACTION_MOVE | GDK_ACTION_COPY);
1330 #define DEFAULT_ICON_HEIGHT 20
1331 #define DEFAULT_ICON_WIDTH 0
1334 fake_expose_widget (GtkWidget *widget,
1337 GdkWindow *tmp_window;
1338 GdkEventExpose event;
1340 event.type = GDK_EXPOSE;
1341 event.window = pixmap;
1342 event.send_event = FALSE;
1343 event.area = widget->allocation;
1344 event.region = NULL;
1347 tmp_window = widget->window;
1348 widget->window = pixmap;
1349 gtk_widget_send_expose (widget, (GdkEvent *) &event);
1350 widget->window = tmp_window;
1353 /* We should probably experiment some more with this.
1354 * Right now the rendered icon is pretty good for most
1355 * themes. However, the icon is slightly large for themes
1356 * with large toolbar icons.
1359 new_pixbuf_from_widget (GtkWidget *widget)
1363 GtkRequisition requisition;
1364 GtkAllocation allocation;
1370 icon_width = DEFAULT_ICON_WIDTH;
1372 if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default (),
1373 GTK_ICON_SIZE_LARGE_TOOLBAR,
1377 icon_height = DEFAULT_ICON_HEIGHT;
1380 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1382 gtk_container_add (GTK_CONTAINER (window), widget);
1383 gtk_widget_realize (window);
1384 gtk_widget_show (widget);
1385 gtk_widget_realize (widget);
1386 gtk_widget_map (widget);
1388 /* Gtk will never set the width or height of a window to 0. So setting the width to
1389 * 0 and than getting it will provide us with the minimum width needed to render
1390 * the icon correctly, without any additional window background noise.
1391 * This is needed mostly for pixmap based themes.
1393 gtk_window_set_default_size (GTK_WINDOW (window), icon_width, icon_height);
1394 gtk_window_get_size (GTK_WINDOW (window),&icon_width, &icon_height);
1396 gtk_widget_size_request (window, &requisition);
1399 allocation.width = icon_width;
1400 allocation.height = icon_height;
1401 gtk_widget_size_allocate (window, &allocation);
1402 gtk_widget_size_request (window, &requisition);
1404 /* Create a pixmap */
1405 visual = gtk_widget_get_visual (window);
1406 pixmap = gdk_pixmap_new (NULL, icon_width, icon_height, visual->depth);
1407 gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), gtk_widget_get_colormap (window));
1409 /* Draw the window */
1410 gtk_widget_ensure_style (window);
1411 g_assert (window->style);
1412 g_assert (window->style->font_desc);
1414 fake_expose_widget (window, pixmap);
1415 fake_expose_widget (widget, pixmap);
1417 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, icon_width, icon_height);
1418 gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, icon_width, icon_height);
1424 new_separator_pixbuf ()
1426 GtkWidget *separator;
1429 separator = gtk_vseparator_new ();
1430 pixbuf = new_pixbuf_from_widget (separator);
1431 gtk_widget_destroy (separator);
1436 update_separator_image (GtkImage *image)
1438 GdkPixbuf *pixbuf = new_separator_pixbuf ();
1439 gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
1440 g_object_unref (pixbuf);
1444 style_set_cb (GtkWidget *widget,
1445 GtkStyle *previous_style,
1449 update_separator_image (image);
1454 _egg_editable_toolbar_new_separator_image (void)
1456 GtkWidget *image = gtk_image_new ();
1457 update_separator_image (GTK_IMAGE (image));
1458 g_signal_connect (G_OBJECT (image), "style_set",
1459 G_CALLBACK (style_set_cb), GTK_IMAGE (image));
1465 egg_editable_toolbar_get_model (EggEditableToolbar *etoolbar)
1467 return etoolbar->priv->model;