]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/toolbar-editor/egg-editable-toolbar.c
Sync
[evince.git] / cut-n-paste / toolbar-editor / egg-editable-toolbar.c
1 /*
2  *  Copyright (C) 2003-2004 Marco Pesenti Gritti
3  *  Copyright (C) 2004 Christian Persch
4  *
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)
8  *  any later version.
9  *
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.
14  *
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.
18  *
19  *  $Id$
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "egg-editable-toolbar.h"
27 #include "egg-toolbars-model.h"
28 #include "egg-toolbar-editor.h"
29
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>
44 #include <string.h>
45
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);
49
50 #define MIN_TOOLBAR_HEIGHT 20
51
52 static GtkTargetEntry dest_drag_types[] = {
53   {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0},
54 };
55 static int n_dest_drag_types = G_N_ELEMENTS (dest_drag_types);
56
57 enum
58 {
59   PROP_0,
60   PROP_TOOLBARS_MODEL,
61   PROP_UI_MANAGER
62 };
63
64 enum
65 {
66   ACTION_REQUEST,
67   LAST_SIGNAL
68 };
69
70 static guint egg_editable_toolbar_signals[LAST_SIGNAL] = { 0 };
71
72 static GObjectClass *parent_class = NULL;
73
74 #define EGG_EDITABLE_TOOLBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_EDITABLE_TOOLBAR, EggEditableToolbarPrivate))
75
76 struct EggEditableToolbarPrivate
77 {
78   GtkUIManager *manager;
79   EggToolbarsModel *model;
80   gboolean edit_mode;
81   GtkWidget *selected_toolbar;
82   GtkToolItem *fixed;
83   GtkWidget *fixed_toolbar;
84
85   gboolean pending;
86   GtkToolbar *target_toolbar;
87   GtkWidget *dragged_item;
88 };
89
90 GType
91 egg_editable_toolbar_get_type (void)
92 {
93   static GType egg_editable_toolbar_type = 0;
94
95   if (egg_editable_toolbar_type == 0)
96     {
97       static const GTypeInfo our_info = {
98         sizeof (EggEditableToolbarClass),
99         NULL,                   /* base_init */
100         NULL,                   /* base_finalize */
101         (GClassInitFunc) egg_editable_toolbar_class_init,
102         NULL,
103         NULL,                   /* class_data */
104         sizeof (EggEditableToolbar),
105         0,                      /* n_preallocs */
106         (GInstanceInitFunc) egg_editable_toolbar_init
107       };
108
109       egg_editable_toolbar_type = g_type_register_static (GTK_TYPE_VBOX,
110                                                           "EggEditableToolbar",
111                                                           &our_info, 0);
112     }
113
114   return egg_editable_toolbar_type;
115 }
116
117 static int
118 get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar)
119 {
120   GList *l;
121   int result;
122
123   l = gtk_container_get_children (GTK_CONTAINER (etoolbar));
124   result = g_list_index (l, toolbar->parent);
125   g_list_free (l);
126
127   return result;
128 }
129
130 static int
131 get_n_toolbars (EggEditableToolbar *etoolbar)
132 {
133   GList *l;
134   int result;
135
136   l = gtk_container_get_children (GTK_CONTAINER (etoolbar));
137   result = g_list_length (l);
138   g_list_free (l);
139
140   return result;
141 }
142
143 static GtkWidget *
144 get_dock_nth (EggEditableToolbar *etoolbar,
145               int                 position)
146 {
147   GList *l;
148   GtkWidget *result;
149
150   l = gtk_container_get_children (GTK_CONTAINER (etoolbar));
151   result = g_list_nth_data (l, position);
152   g_list_free (l);
153
154   return result;
155 }
156
157 static GtkWidget *
158 get_toolbar_nth (EggEditableToolbar *etoolbar,
159                  int                 position)
160 {
161   GList *l;
162   GtkWidget *dock;
163   GtkWidget *result;
164
165   dock = get_dock_nth (etoolbar, position);
166
167   l = gtk_container_get_children (GTK_CONTAINER (dock));
168   result = GTK_WIDGET (l->data);
169   g_list_free (l);
170
171   return result;
172 }
173
174 static GtkAction *
175 find_action (EggEditableToolbar *t,
176              const char         *name)
177 {
178   GList *l;
179   GtkAction *action = NULL;
180
181   l = gtk_ui_manager_get_action_groups (t->priv->manager);
182
183   g_return_val_if_fail (name != NULL, NULL);
184
185   for (; l != NULL; l = l->next)
186     {
187       GtkAction *tmp;
188
189       tmp = gtk_action_group_get_action (GTK_ACTION_GROUP (l->data), name);
190       if (tmp)
191         action = tmp;
192     }
193
194   return action;
195 }
196
197 static void
198 drag_data_delete_cb (GtkWidget          *widget,
199                      GdkDragContext     *context,
200                      EggEditableToolbar *etoolbar)
201 {
202   int pos, toolbar_pos;
203
204   g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar));
205
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);
209
210   egg_toolbars_model_remove_item (etoolbar->priv->model,
211                                   toolbar_pos, pos);
212 }
213
214 static void
215 drag_begin_cb (GtkWidget          *widget,
216                GdkDragContext     *context,
217                EggEditableToolbar *etoolbar)
218 {
219         gtk_widget_hide (widget);
220 }
221
222 static void
223 drag_end_cb (GtkWidget          *widget,
224              GdkDragContext     *context,
225              EggEditableToolbar *etoolbar)
226 {
227         gtk_widget_show (widget);
228 }
229
230 static void
231 drag_data_get_cb (GtkWidget          *widget,
232                   GdkDragContext     *context,
233                   GtkSelectionData   *selection_data,
234                   guint               info,
235                   guint32             time,
236                   EggEditableToolbar *etoolbar)
237 {
238   const char *id, *type;
239   char *target;
240
241   g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar));
242
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)
246     {
247       target = g_strdup (id);
248     }
249   else
250     {
251       target = egg_toolbars_model_get_item_data (etoolbar->priv->model,
252                                                  type, id);
253     }
254
255   gtk_selection_data_set (selection_data,
256                           selection_data->target, 8, target, strlen (target));
257
258   g_free (target);
259 }
260
261 static void
262 set_drag_cursor (GtkWidget *widget)
263 {
264   if (widget->window)
265     {
266       GdkCursor *cursor;
267       GdkPixbuf *pixbuf;
268
269       pixbuf = gdk_pixbuf_new_from_file (CURSOR_DIR "/hand-open.png", NULL);
270       cursor = gdk_cursor_new_from_pixbuf (gdk_display_get_default (),
271                                            pixbuf, 12, 12);
272       gdk_window_set_cursor (widget->window, cursor);
273       gdk_cursor_unref (cursor);
274       g_object_unref (pixbuf);
275     }
276 }
277
278 static void
279 unset_drag_cursor (GtkWidget *widget)
280 {
281   if (widget->window)
282     {
283       gdk_window_set_cursor (widget->window, NULL);
284     }
285 }
286
287 static void
288 set_item_drag_source (EggToolbarsModel *model,
289                       GtkWidget        *item,
290                       GtkAction        *action,
291                       gboolean          is_separator,
292                       const char       *type)
293 {
294   GtkTargetEntry target_entry;
295   const char *id;
296
297   target_entry.target = (char *)type;
298   target_entry.flags = GTK_TARGET_SAME_APP;
299   target_entry.info = 0;
300
301   gtk_drag_source_set (item, GDK_BUTTON1_MASK,
302                        &target_entry, 1,
303                        GDK_ACTION_MOVE);
304
305   if (is_separator)
306     {
307       GtkWidget *icon;
308       GdkPixbuf *pixbuf;
309
310       id = "separator";
311
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);
315     }
316   else
317     {
318       const char *stock_id;
319       GValue value = { 0, };
320       GdkPixbuf *pixbuf;
321
322       id = gtk_action_get_name (action);
323
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);
327
328       if (stock_id != NULL)
329         {
330           pixbuf = gtk_widget_render_icon (item, stock_id,
331                                            GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
332         }
333       else
334         {
335           pixbuf = gtk_widget_render_icon (item, GTK_STOCK_DND,
336                                            GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
337         }
338
339       gtk_drag_source_set_icon_pixbuf (item, pixbuf);
340       g_object_unref (pixbuf);
341
342       g_value_unset (&value);
343     }
344
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);
349 }
350
351 static GtkWidget *
352 create_item_from_action (EggEditableToolbar *t,
353                          const char *action_name,
354                          const char *type,
355                          gboolean is_separator,
356                          GtkAction **ret_action)
357 {
358   GtkWidget *item;
359   GtkAction *action;
360
361   if (is_separator)
362     {
363       item = GTK_WIDGET (gtk_separator_tool_item_new ());
364       action = NULL;
365     }
366   else
367     {
368       g_return_val_if_fail (action_name != NULL, NULL);
369
370       g_signal_emit (G_OBJECT (t), egg_editable_toolbar_signals[ACTION_REQUEST],
371                      0, action_name);
372
373       action = find_action (t, action_name);
374       if (action)
375         {
376           item = gtk_action_create_tool_item (action);
377         }
378       else
379         {
380           return NULL;
381         }  
382     }
383
384   gtk_widget_show (item);
385
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);
394
395   if (t->priv->edit_mode)
396     {
397       set_drag_cursor (item);
398       gtk_widget_set_sensitive (item, TRUE);
399       set_item_drag_source (t->priv->model, item, action,
400                             is_separator, type);
401       gtk_tool_item_set_use_drag_window (GTK_TOOL_ITEM (item), TRUE);
402     }
403
404   if (ret_action)
405     {
406       *ret_action = action;
407     }
408
409   return item;
410 }
411
412 static GtkWidget *
413 create_item (EggEditableToolbar *t,
414              EggToolbarsModel   *model,
415              int                 toolbar_position,
416              int                 position,
417              GtkAction         **ret_action)
418 {
419   const char *action_name, *type;
420   gboolean is_separator;
421
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);
426 }
427
428 static gboolean
429 data_is_separator (const char *data)
430 {
431   return strcmp (data, "separator") == 0;
432 }
433
434 static void
435 drag_data_received_cb (GtkWidget          *widget,
436                        GdkDragContext     *context,
437                        gint                x,
438                        gint                y,
439                        GtkSelectionData   *selection_data,
440                        guint               info,
441                        guint               time,
442                        EggEditableToolbar *etoolbar)
443 {
444   char *type;
445   char *id;
446
447   GdkAtom target;
448           
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, selection_data->data);
452
453   /* This function can be called for two reasons
454    *
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.
459    *
460    *  (2) The drag has finished, and drag_drop() wants us to
461    *      actually add a new item to the toolbar.
462    */
463
464   if (id == NULL)
465     {
466       etoolbar->priv->pending = FALSE;
467       g_free (type);
468       return;
469     }
470
471   if (etoolbar->priv->pending)
472     {
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));
479     }
480   else
481     {
482       int pos, toolbar_pos;
483
484       pos = gtk_toolbar_get_drop_index (GTK_TOOLBAR (widget), x, y);
485       toolbar_pos = get_toolbar_position (etoolbar, widget);
486
487       if (data_is_separator (selection_data->data))
488         {
489           egg_toolbars_model_add_separator (etoolbar->priv->model,
490                                             toolbar_pos, pos);
491         }
492       else
493         {
494           egg_toolbars_model_add_item (etoolbar->priv->model,
495                                        toolbar_pos, pos, id, type);
496         }
497       
498       gtk_drag_finish (context, TRUE, context->action == GDK_ACTION_MOVE,
499                        time);
500     }
501
502   g_free (type);
503   g_free (id);
504 }
505
506 static void
507 remove_toolbar_cb (GtkWidget          *menuitem,
508                    EggEditableToolbar *etoolbar)
509 {
510   int pos;
511
512   pos = get_toolbar_position (etoolbar, etoolbar->priv->selected_toolbar);
513   egg_toolbars_model_remove_toolbar (etoolbar->priv->model, pos);
514 }
515
516 static void
517 popup_toolbar_context_menu_cb (GtkWidget          *toolbar,
518                                gint                x,
519                                gint                y,
520                                gint                button_number,
521                                EggEditableToolbar *t)
522 {
523   GtkWidget *menu;
524   GtkWidget *item;
525   GtkWidget *image;
526
527   if (t->priv->edit_mode)
528     {
529       EggTbModelFlags flags;
530       int position;
531
532       t->priv->selected_toolbar = toolbar;
533
534       menu = gtk_menu_new ();
535
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),
544                         t);
545
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)
549         {
550           gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
551         }
552
553       gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 2,
554                       gtk_get_current_event_time ());
555     }
556 }
557
558 static void
559 free_dragged_item (EggEditableToolbar *etoolbar)
560 {
561   if (etoolbar->priv->dragged_item)
562     {
563       gtk_widget_destroy (etoolbar->priv->dragged_item);
564       g_object_unref (etoolbar->priv->dragged_item);
565       etoolbar->priv->dragged_item = NULL;
566     }
567 }
568
569 static gboolean
570 toolbar_drag_drop_cb (GtkWidget          *widget,
571                       GdkDragContext     *context,
572                       gint                x,
573                       gint                y,
574                       guint               time,
575                       EggEditableToolbar *etoolbar)
576 {
577   GdkAtom target;
578
579   target = gtk_drag_dest_find_target (widget, context, NULL);
580   if (target != GDK_NONE)
581     {
582       gtk_drag_get_data (widget, context,
583                          target,
584                          time);
585       return TRUE;
586     }
587   
588   free_dragged_item (etoolbar);
589   
590   return FALSE;
591 }
592
593 static gboolean
594 toolbar_drag_motion_cb (GtkWidget          *widget,
595                         GdkDragContext     *context,
596                         gint                x,
597                         gint                y,
598                         guint               time,
599                         EggEditableToolbar *etoolbar)
600 {
601   GdkAtom target;
602   int index;
603   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
604   GtkToolItem *item;
605   GtkWidget *source;
606
607   source = gtk_drag_get_source_widget (context);
608   if (source)
609     {
610       EggTbModelFlags flags;
611       int pos;
612       gboolean is_item;
613
614       pos = get_toolbar_position (etoolbar, widget);
615       flags = egg_toolbars_model_get_flags (etoolbar->priv->model, pos);
616
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));
620
621       if ((flags & EGG_TB_MODEL_ACCEPT_ITEMS_ONLY) && !is_item)
622         {
623           gdk_drag_status (context, 0, time);
624           return FALSE;
625         }
626
627       if (gtk_widget_is_ancestor (source, widget))
628         {
629           context->suggested_action = GDK_ACTION_MOVE;
630         }
631     }
632
633   target = gtk_drag_dest_find_target (widget, context, NULL);
634   if (target == GDK_NONE)
635     {
636       gdk_drag_status (context, 0, time);
637       return FALSE;
638     }
639
640   if (etoolbar->priv->target_toolbar != toolbar)
641     {
642       if (etoolbar->priv->target_toolbar)
643         gtk_toolbar_set_drop_highlight_item
644                 (etoolbar->priv->target_toolbar, NULL, 0);
645       
646       free_dragged_item (etoolbar);
647       etoolbar->priv->pending = TRUE;
648
649       etoolbar->priv->target_toolbar = toolbar;
650
651       gtk_drag_get_data (widget, context, target, time);
652     }
653
654   if (etoolbar->priv->dragged_item != NULL &&
655       etoolbar->priv->edit_mode)
656     {
657       item = GTK_TOOL_ITEM (etoolbar->priv->dragged_item);
658
659       index = gtk_toolbar_get_drop_index (toolbar, x, y);
660       gtk_toolbar_set_drop_highlight_item (toolbar, item, index);
661     }
662
663   gdk_drag_status (context, context->suggested_action, time);
664
665   return TRUE;
666 }
667
668 static void
669 toolbar_drag_leave_cb (GtkToolbar         *toolbar,
670                        GdkDragContext     *context,
671                        guint               time,
672                        EggEditableToolbar *etoolbar)
673 {
674   /* This is a workaround for bug 125557. Sometimes
675    * we seemingly enter another toolbar *before* leaving
676    * the current one.
677    *
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
681    */
682   
683   if (etoolbar->priv->target_toolbar == toolbar)
684     {
685       gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0);
686
687       etoolbar->priv->target_toolbar = NULL;
688       free_dragged_item (etoolbar);
689     }
690 }
691
692 static GtkWidget *
693 create_dock (EggEditableToolbar *t)
694 {
695   GtkWidget *toolbar, *hbox;
696
697   hbox = gtk_hbox_new (0, FALSE);
698   gtk_widget_show (hbox);
699
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);
704
705   gtk_drag_dest_set (toolbar, 0,
706                      dest_drag_types, n_dest_drag_types,
707                      GDK_ACTION_MOVE | GDK_ACTION_COPY);
708  
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);
715
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);
720
721   return hbox;
722 }
723
724 static void
725 set_fixed_style (EggEditableToolbar *t, GtkToolbarStyle style)
726 {
727   g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar));
728   gtk_toolbar_set_style (GTK_TOOLBAR (t->priv->fixed_toolbar), style);
729 }
730
731 static void
732 unset_fixed_style (EggEditableToolbar *t)
733 {
734   g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar));
735   gtk_toolbar_unset_style (GTK_TOOLBAR (t->priv->fixed_toolbar));
736 }
737
738 static void
739 toolbar_changed_cb (EggToolbarsModel   *model,
740                     int                 position,
741                     EggEditableToolbar *t)
742 {
743   GtkWidget *toolbar;
744   EggTbModelFlags flags;
745   GtkToolbarStyle style;
746
747   flags = egg_toolbars_model_get_flags (model, position);
748   toolbar = get_toolbar_nth (t, position);
749
750   if (flags & EGG_TB_MODEL_ICONS_ONLY)
751   {
752     style = GTK_TOOLBAR_ICONS;
753   }
754   else if (flags & EGG_TB_MODEL_TEXT_ONLY)
755   {
756     style = GTK_TOOLBAR_TEXT;
757   }
758   else if (flags & EGG_TB_MODEL_ICONS_TEXT)
759   {
760     style = GTK_TOOLBAR_BOTH;
761   }
762   else if (flags & EGG_TB_MODEL_ICONS_TEXT_HORIZ)
763   {
764     style = GTK_TOOLBAR_BOTH_HORIZ;
765   }
766   else
767   {
768     gtk_toolbar_unset_style (GTK_TOOLBAR (toolbar));
769     if (position == 0 && t->priv->fixed_toolbar)
770       {
771         unset_fixed_style (t);
772       }
773     return;
774   }
775
776   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), style);
777   if (position == 0 && t->priv->fixed_toolbar)
778     {
779       set_fixed_style (t, style);
780     }
781 }
782
783 static void
784 unparent_fixed (EggEditableToolbar *t)
785 {
786   GtkWidget *toolbar, *dock;
787   g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar));
788
789   toolbar = t->priv->fixed_toolbar;
790   dock = get_dock_nth (t, 0);
791
792   if (dock && toolbar->parent != NULL)
793     {
794       gtk_container_remove (GTK_CONTAINER (dock), toolbar);
795     }
796 }
797
798 static void
799 update_fixed (EggEditableToolbar *t)
800 {
801   GtkWidget *toolbar, *dock;
802   if (!t->priv->fixed_toolbar) return;
803
804   toolbar = t->priv->fixed_toolbar;
805   dock = get_dock_nth (t, 0);
806
807   if (dock && toolbar && toolbar->parent == NULL)
808     {
809       gtk_box_pack_end (GTK_BOX (dock), toolbar, FALSE, TRUE, 0);
810
811       gtk_widget_show_all (toolbar);
812     }
813 }
814
815 static void
816 toolbar_added_cb (EggToolbarsModel   *model,
817                   int                 position,
818                   EggEditableToolbar *t)
819 {
820   GtkWidget *dock;
821
822   dock = create_dock (t);
823
824   gtk_widget_set_size_request (dock, -1, MIN_TOOLBAR_HEIGHT);
825
826   gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0);
827
828   gtk_box_reorder_child (GTK_BOX (t), dock, position);
829
830   gtk_widget_show_all (dock);
831   
832   update_fixed (t);
833 }
834
835 static void
836 toolbar_removed_cb (EggToolbarsModel   *model,
837                     int                 position,
838                     EggEditableToolbar *t)
839 {
840   GtkWidget *toolbar;
841
842   toolbar = get_dock_nth (t, position);
843   gtk_widget_destroy (toolbar);
844
845   update_fixed (t);
846 }
847
848 static void
849 item_added_cb (EggToolbarsModel   *model,
850                int                 toolbar_position,
851                int                 position,
852                EggEditableToolbar *t)
853 {
854   GtkWidget *dock;
855   GtkWidget *toolbar;
856   GtkWidget *item;
857   GtkAction *action;
858
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);
863
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);
867
868   /* FIXME Hack to make tooltip work from gtk */
869   if (action)
870     {
871       g_object_notify (G_OBJECT (action), "tooltip");
872     }
873 }
874
875 static void
876 item_removed_cb (EggToolbarsModel   *model,
877                  int                 toolbar_position,
878                  int                 position,
879                  EggEditableToolbar *t)
880 {
881   GtkWidget *toolbar;
882   GtkWidget *item;
883
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);
889
890   if (egg_toolbars_model_n_items (model, toolbar_position) == 0)
891     {
892       egg_toolbars_model_remove_toolbar (model, toolbar_position);
893     }
894 }
895
896 static void
897 egg_editable_toolbar_construct (EggEditableToolbar *t)
898 {
899   int i, l, n_items, n_toolbars;
900   EggToolbarsModel *model = t->priv->model;
901
902   g_return_if_fail (model != NULL);
903   g_return_if_fail (t->priv->manager != NULL);
904
905   n_toolbars = egg_toolbars_model_n_toolbars (model);
906
907   for (i = 0; i < n_toolbars; i++)
908     {
909       GtkWidget *toolbar, *dock;
910       EggTbModelFlags flags;
911
912       dock = create_dock (t);
913       gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0);
914       toolbar = get_toolbar_nth (t, i);
915
916       flags = egg_toolbars_model_get_flags (model, i);
917       if (flags & EGG_TB_MODEL_ICONS_ONLY)
918         {
919           gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
920           if (i == 0 && t->priv->fixed_toolbar)
921             {
922               set_fixed_style (t, GTK_TOOLBAR_ICONS);
923             }
924         }
925
926       n_items = egg_toolbars_model_n_items (model, i);
927       for (l = 0; l < n_items; l++)
928         {
929           GtkWidget *item;
930           GtkAction *action;
931
932           item = create_item (t, model, i, l, &action);
933           if (item)
934             {
935               gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
936                                   GTK_TOOL_ITEM (item), l);
937               /* FIXME Hack to make tooltip work from gtk */
938               if (action)
939                 {
940                   g_object_notify (G_OBJECT (action), "tooltip");
941                 }
942             }
943           else
944             {
945               egg_toolbars_model_remove_item (model, i, l);
946               l--;
947               n_items--;
948             }
949         }
950
951       if (n_items == 0)
952         {
953             gtk_widget_set_size_request (dock, -1, MIN_TOOLBAR_HEIGHT);
954         }
955     }
956
957   update_fixed (t);
958 }
959
960 static void
961 egg_editable_toolbar_disconnect_model (EggEditableToolbar *toolbar)
962 {
963   EggToolbarsModel *model = toolbar->priv->model;
964
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);
975 }
976
977 static void
978 egg_editable_toolbar_deconstruct (EggEditableToolbar *toolbar)
979 {
980   EggToolbarsModel *model = toolbar->priv->model;
981   GList *children;
982
983   g_return_if_fail (model != NULL);
984
985   if (toolbar->priv->fixed_toolbar)
986     {
987        unset_fixed_style (toolbar);
988        unparent_fixed (toolbar);
989     }
990
991   children = gtk_container_get_children (GTK_CONTAINER (toolbar));
992   g_list_foreach (children, (GFunc) gtk_widget_destroy, NULL);
993   g_list_free (children);
994 }
995
996 void
997 egg_editable_toolbar_set_model (EggEditableToolbar *toolbar,
998                                 EggToolbarsModel   *model)
999 {
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);
1003
1004   if (toolbar->priv->model == model) return;
1005
1006   if (toolbar->priv->model)
1007     {
1008       egg_editable_toolbar_disconnect_model (toolbar);
1009       egg_editable_toolbar_deconstruct (toolbar);
1010
1011       g_object_unref (toolbar->priv->model);
1012     }
1013
1014   toolbar->priv->model = g_object_ref (model);
1015
1016   egg_editable_toolbar_construct (toolbar);
1017
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);
1028 }
1029
1030 static void
1031 egg_editable_toolbar_set_ui_manager (EggEditableToolbar *t,
1032                                      GtkUIManager       *manager)
1033 {
1034   g_return_if_fail (GTK_IS_UI_MANAGER (manager));
1035
1036   t->priv->manager = g_object_ref (manager);
1037 }
1038
1039 static void
1040 egg_editable_toolbar_set_property (GObject      *object,
1041                                    guint         prop_id,
1042                                    const GValue *value,
1043                                    GParamSpec   *pspec)
1044 {
1045   EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object);
1046
1047   switch (prop_id)
1048     {
1049     case PROP_UI_MANAGER:
1050       egg_editable_toolbar_set_ui_manager (t, g_value_get_object (value));
1051       break;
1052     case PROP_TOOLBARS_MODEL:
1053       egg_editable_toolbar_set_model (t, g_value_get_object (value));
1054       break;
1055     default:
1056       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1057       break;
1058     }
1059 }
1060
1061 static void
1062 egg_editable_toolbar_get_property (GObject    *object,
1063                                    guint       prop_id,
1064                                    GValue     *value,
1065                                    GParamSpec *pspec)
1066 {
1067   EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object);
1068
1069   switch (prop_id)
1070     {
1071     case PROP_UI_MANAGER:
1072       g_value_set_object (value, t->priv->manager);
1073       break;
1074     case PROP_TOOLBARS_MODEL:
1075       g_value_set_object (value, t->priv->model);
1076       break;
1077     default:
1078       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1079       break;
1080     }
1081 }
1082
1083 static void
1084 egg_editable_toolbar_class_init (EggEditableToolbarClass *klass)
1085 {
1086   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1087
1088   parent_class = g_type_class_peek_parent (klass);
1089
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;
1093
1094   egg_editable_toolbar_signals[ACTION_REQUEST] =
1095     g_signal_new ("action_request",
1096                   G_OBJECT_CLASS_TYPE (object_class),
1097                   G_SIGNAL_RUN_LAST,
1098                   G_STRUCT_OFFSET (EggEditableToolbarClass, action_request),
1099                   NULL, NULL, g_cclosure_marshal_VOID__STRING,
1100                   G_TYPE_NONE, 1, G_TYPE_STRING);
1101
1102   g_object_class_install_property (object_class,
1103                                    PROP_UI_MANAGER,
1104                                    g_param_spec_object ("ui-manager",
1105                                                         "UI-Mmanager",
1106                                                         "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",
1112                                                         "Model",
1113                                                         "Toolbars Model",
1114                                                         EGG_TYPE_TOOLBARS_MODEL,
1115                                                         G_PARAM_READWRITE));
1116
1117   g_type_class_add_private (object_class, sizeof (EggEditableToolbarPrivate));
1118 }
1119
1120 static void
1121 egg_editable_toolbar_init (EggEditableToolbar *t)
1122 {
1123   t->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (t);
1124 }
1125
1126 static void
1127 egg_editable_toolbar_finalize (GObject *object)
1128 {
1129   EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object);
1130
1131   if (t->priv->fixed_toolbar)
1132     {
1133       g_object_unref (t->priv->fixed_toolbar);
1134     }
1135
1136   if (t->priv->manager)
1137     {
1138       g_object_unref (t->priv->manager);
1139     }
1140
1141   if (t->priv->model)
1142     {
1143       egg_editable_toolbar_disconnect_model (t);
1144       g_object_unref (t->priv->model);
1145     }
1146
1147   G_OBJECT_CLASS (parent_class)->finalize (object);
1148 }
1149
1150 GtkWidget *
1151 egg_editable_toolbar_new (GtkUIManager     *manager)
1152 {
1153   return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
1154                                    "ui-manager", manager,
1155                                    NULL));
1156 }
1157
1158 GtkWidget *
1159 egg_editable_toolbar_new_with_model (GtkUIManager     *manager,
1160                                      EggToolbarsModel *model)
1161 {
1162   return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
1163                                    "ui-manager", manager,
1164                                    "model", model,
1165                                    NULL));
1166 }
1167
1168 gboolean
1169 egg_editable_toolbar_get_edit_mode (EggEditableToolbar *etoolbar)
1170 {
1171         return etoolbar->priv->edit_mode;
1172 }
1173
1174 void
1175 egg_editable_toolbar_set_edit_mode (EggEditableToolbar *etoolbar,
1176                                     gboolean            mode)
1177 {
1178   int i, l, n_toolbars, n_items;
1179
1180   etoolbar->priv->edit_mode = mode;
1181
1182   n_toolbars = get_n_toolbars (etoolbar);
1183   for (i = 0; i < n_toolbars; i++)
1184     {
1185       GtkWidget *toolbar;
1186
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++)
1190         {
1191           GtkToolItem *item;
1192           const char *action_name, *type;
1193           gboolean is_separator;
1194           GtkAction *action = NULL;
1195
1196           egg_toolbars_model_item_nth (etoolbar->priv->model, i, l,
1197                                        &is_separator, &action_name, &type);
1198           action = find_action (etoolbar, action_name);
1199
1200           item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), l);
1201           gtk_tool_item_set_use_drag_window (item, mode);
1202
1203           if (mode)
1204             {
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);
1209             }
1210           else
1211             {
1212               unset_drag_cursor (GTK_WIDGET (item));
1213               gtk_drag_source_unset (GTK_WIDGET (item));
1214
1215               if (!is_separator)
1216                 {
1217                   g_object_notify (G_OBJECT (action), "sensitive");
1218                 }
1219             }
1220         }
1221     }
1222 }
1223
1224 void
1225 egg_editable_toolbar_show (EggEditableToolbar *etoolbar,
1226                            const char         *name)
1227 {
1228   int i, n_toolbars;
1229   EggToolbarsModel *model = etoolbar->priv->model;
1230
1231   g_return_if_fail (model != NULL);
1232
1233   n_toolbars = egg_toolbars_model_n_toolbars (model);
1234   for (i = 0; i < n_toolbars; i++)
1235     {
1236       const char *toolbar_name;
1237
1238       toolbar_name = egg_toolbars_model_toolbar_nth (model, i);
1239       if (strcmp (toolbar_name, name) == 0)
1240       {
1241         gtk_widget_show (get_dock_nth (etoolbar, i));
1242       }
1243     }
1244 }
1245
1246 void
1247 egg_editable_toolbar_hide (EggEditableToolbar *etoolbar,
1248                            const char         *name)
1249 {
1250   int i, n_toolbars;
1251   EggToolbarsModel *model = etoolbar->priv->model;
1252
1253   g_return_if_fail (model != NULL);
1254
1255   n_toolbars = egg_toolbars_model_n_toolbars (model);
1256   for (i = 0; i < n_toolbars; i++)
1257     {
1258       const char *toolbar_name;
1259
1260       toolbar_name = egg_toolbars_model_toolbar_nth (model, i);
1261       if (strcmp (toolbar_name, name) == 0)
1262       {
1263         gtk_widget_hide (get_dock_nth (etoolbar, i));
1264       }
1265     }
1266 }
1267
1268 void
1269 egg_editable_toolbar_set_fixed (EggEditableToolbar *toolbar,
1270                                 GtkToolItem        *fixed)
1271 {
1272   g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (toolbar));
1273   g_return_if_fail (!fixed || GTK_IS_TOOL_ITEM (fixed));
1274
1275   if (!toolbar->priv->fixed_toolbar)
1276     {
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));
1281     }
1282
1283   if (toolbar->priv->fixed)
1284     {
1285       gtk_container_remove (GTK_CONTAINER (toolbar->priv->fixed_toolbar),
1286                             GTK_WIDGET (toolbar->priv->fixed));
1287       g_object_unref (toolbar->priv->fixed);
1288     }
1289
1290   toolbar->priv->fixed = fixed;
1291
1292   if (fixed)
1293     {
1294       g_object_ref (fixed);
1295       gtk_object_sink (GTK_OBJECT (fixed));
1296
1297       gtk_toolbar_insert (GTK_TOOLBAR (toolbar->priv->fixed_toolbar), fixed, 0);
1298     }
1299 }
1300
1301 void
1302 egg_editable_toolbar_set_drag_dest (EggEditableToolbar   *etoolbar,
1303                                     const GtkTargetEntry *targets,
1304                                     gint                  n_targets,
1305                                     const char           *toolbar_name)
1306 {
1307   int i, n_toolbars;
1308   EggToolbarsModel *model = etoolbar->priv->model;
1309
1310   g_return_if_fail (model != NULL);
1311
1312   n_toolbars = egg_toolbars_model_n_toolbars (model);
1313   for (i = 0; i < n_toolbars; i++)
1314     {
1315       const char *name;
1316
1317       name = egg_toolbars_model_toolbar_nth (model, i);
1318       if (strcmp (toolbar_name, name) == 0)
1319       {
1320         GtkWidget *widget = get_toolbar_nth (etoolbar, i);
1321
1322         gtk_drag_dest_unset (widget);
1323         gtk_drag_dest_set (widget, 0,
1324                            targets, n_targets,
1325                            GDK_ACTION_MOVE | GDK_ACTION_COPY);
1326       }
1327     }
1328 }
1329
1330 #define DEFAULT_ICON_HEIGHT 20
1331 #define DEFAULT_ICON_WIDTH 0
1332
1333 static void
1334 fake_expose_widget (GtkWidget *widget,
1335                     GdkPixmap *pixmap)
1336 {
1337   GdkWindow *tmp_window;
1338   GdkEventExpose event;
1339
1340   event.type = GDK_EXPOSE;
1341   event.window = pixmap;
1342   event.send_event = FALSE;
1343   event.area = widget->allocation;
1344   event.region = NULL;
1345   event.count = 0;
1346
1347   tmp_window = widget->window;
1348   widget->window = pixmap;
1349   gtk_widget_send_expose (widget, (GdkEvent *) &event);
1350   widget->window = tmp_window;
1351 }
1352
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.
1357  */
1358 static GdkPixbuf *
1359 new_pixbuf_from_widget (GtkWidget *widget)
1360 {
1361   GtkWidget *window;
1362   GdkPixbuf *pixbuf;
1363   GtkRequisition requisition;
1364   GtkAllocation allocation;
1365   GdkPixmap *pixmap;
1366   GdkVisual *visual;
1367   gint icon_width;
1368   gint icon_height;
1369
1370   icon_width = DEFAULT_ICON_WIDTH;
1371
1372   if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default (), 
1373                                           GTK_ICON_SIZE_LARGE_TOOLBAR,
1374                                           NULL, 
1375                                           &icon_height))
1376     {
1377       icon_height = DEFAULT_ICON_HEIGHT;
1378     }
1379
1380   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1381   
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);
1387
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.
1392    */
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);
1395
1396   gtk_widget_size_request (window, &requisition);
1397   allocation.x = 0;
1398   allocation.y = 0;
1399   allocation.width = icon_width;
1400   allocation.height = icon_height;
1401   gtk_widget_size_allocate (window, &allocation);
1402   gtk_widget_size_request (window, &requisition);
1403   
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));
1408
1409   /* Draw the window */
1410   gtk_widget_ensure_style (window);
1411   g_assert (window->style);
1412   g_assert (window->style->font_desc);
1413   
1414   fake_expose_widget (window, pixmap);
1415   fake_expose_widget (widget, pixmap);
1416   
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);
1419
1420   return pixbuf;
1421 }
1422
1423 static GdkPixbuf *
1424 new_separator_pixbuf ()
1425 {
1426   GtkWidget *separator;
1427   GdkPixbuf *pixbuf;
1428
1429   separator = gtk_vseparator_new ();
1430   pixbuf = new_pixbuf_from_widget (separator);
1431   gtk_widget_destroy (separator);
1432   return pixbuf;
1433 }
1434
1435 static void
1436 update_separator_image (GtkImage *image)
1437 {
1438   GdkPixbuf *pixbuf = new_separator_pixbuf ();
1439   gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
1440   g_object_unref (pixbuf);
1441 }
1442
1443 static gboolean
1444 style_set_cb (GtkWidget *widget,
1445               GtkStyle *previous_style,
1446               GtkImage *image)
1447 {
1448
1449   update_separator_image (image);
1450   return FALSE;
1451 }
1452
1453 GtkWidget *
1454 _egg_editable_toolbar_new_separator_image (void)
1455 {
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));
1460
1461   return image;
1462 }
1463
1464 EggToolbarsModel *
1465 egg_editable_toolbar_get_model (EggEditableToolbar *etoolbar)
1466 {
1467   return etoolbar->priv->model;
1468 }