diff options
Diffstat (limited to 'lib/egg/eggtoolbar.c')
-rw-r--r-- | lib/egg/eggtoolbar.c | 1850 |
1 files changed, 1850 insertions, 0 deletions
diff --git a/lib/egg/eggtoolbar.c b/lib/egg/eggtoolbar.c new file mode 100644 index 000000000..3f90fed6a --- /dev/null +++ b/lib/egg/eggtoolbar.c @@ -0,0 +1,1850 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * GtkToolbar copyright (C) Federico Mena + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <gtk/gtkarrow.h> +#include "eggtoolbar.h" +#include "eggradiotoolbutton.h" +#include "eggseparatortoolitem.h" +#include <gtk/gtkmenu.h> +#include <gtk/gtkradiobutton.h> +#include <gtk/gtktoolbar.h> + +#define DEFAULT_IPADDING 0 +#define DEFAULT_SPACE_SIZE 5 +#define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE + +#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR +#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH + +#define SPACE_LINE_DIVISION 10 +#define SPACE_LINE_START 3 +#define SPACE_LINE_END 7 + +#define TOOLBAR_ITEM_VISIBLE(item) \ +(GTK_WIDGET_VISIBLE (item) && \ +((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL && item->visible_horizontal) || \ + (toolbar->orientation == GTK_ORIENTATION_VERTICAL && item->visible_vertical))) + +#ifndef _ +# define _(s) (s) +#endif + +enum { + PROP_0, + PROP_ORIENTATION, + PROP_TOOLBAR_STYLE, + PROP_SHOW_ARROW +}; + +enum { + ORIENTATION_CHANGED, + STYLE_CHANGED, + LAST_SIGNAL +}; + +static void egg_toolbar_init (EggToolbar *toolbar); +static void egg_toolbar_class_init (EggToolbarClass *klass); + +static void egg_toolbar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void egg_toolbar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static gint egg_toolbar_expose (GtkWidget *widget, + GdkEventExpose *event); +static void egg_toolbar_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void egg_toolbar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void egg_toolbar_style_set (GtkWidget *widget, + GtkStyle *prev_style); +static gboolean egg_toolbar_focus (GtkWidget *widget, + GtkDirectionType dir); +static void egg_toolbar_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen); + +static void egg_toolbar_add (GtkContainer *container, + GtkWidget *widget); +static void egg_toolbar_remove (GtkContainer *container, + GtkWidget *widget); +static void egg_toolbar_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static GType egg_toolbar_child_type (GtkContainer *container); + + +static void egg_toolbar_real_orientation_changed (EggToolbar *toolbar, + GtkOrientation orientation); +static void egg_toolbar_real_style_changed (EggToolbar *toolbar, + GtkToolbarStyle style); + +static void egg_toolbar_button_press (GtkWidget *button, + GdkEventButton *event, + EggToolbar *toolbar); +static void egg_toolbar_update_button_relief (EggToolbar *toolbar); +static GtkReliefStyle get_button_relief (EggToolbar *toolbar); +static gint get_space_size (EggToolbar *toolbar); +static GtkToolbarSpaceStyle get_space_style (EggToolbar *toolbar); + +static GtkWidget *egg_toolbar_internal_insert_element (EggToolbar *toolbar, + EggToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data, + gint position, + gboolean use_stock); + + +#define PRIVATE_KEY "egg-toolbar-private" + +#define EGG_TOOLBAR_GET_PRIVATE(toolbar) (g_object_get_data (G_OBJECT (toolbar), PRIVATE_KEY)) + +typedef struct +{ + GList *items; + GList *first_non_fitting_item; + + gint total_button_maxw; + gint total_button_maxh; + + GtkWidget *button; + GtkWidget *arrow; + + gboolean show_arrow; +} EggToolbarPrivate; + +static GtkContainerClass *parent_class = NULL; +static guint toolbar_signals [LAST_SIGNAL] = { 0 }; + +GType +egg_toolbar_get_type (void) +{ + static GtkType type = 0; + + if (!type) + { + static const GTypeInfo type_info = + { + sizeof (EggToolbarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) egg_toolbar_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (EggToolbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) egg_toolbar_init, + }; + + type = g_type_register_static (GTK_TYPE_CONTAINER, + "EggToolbar", + &type_info, 0); + } + + return type; +} + +static void +egg_toolbar_class_init (EggToolbarClass *klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + gobject_class = (GObjectClass *)klass; + widget_class = (GtkWidgetClass *)klass; + container_class = (GtkContainerClass *)klass; + + gobject_class->set_property = egg_toolbar_set_property; + gobject_class->get_property = egg_toolbar_get_property; + + widget_class->expose_event = egg_toolbar_expose; + widget_class->size_request = egg_toolbar_size_request; + widget_class->size_allocate = egg_toolbar_size_allocate; + widget_class->style_set = egg_toolbar_style_set; + widget_class->focus = egg_toolbar_focus; + widget_class->screen_changed = egg_toolbar_screen_changed; + + container_class->add = egg_toolbar_add; + container_class->remove = egg_toolbar_remove; + container_class->forall = egg_toolbar_forall; + container_class->child_type = egg_toolbar_child_type; + + klass->orientation_changed = egg_toolbar_real_orientation_changed; + klass->style_changed = egg_toolbar_real_style_changed; + + toolbar_signals[ORIENTATION_CHANGED] = + g_signal_new ("orientation_changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EggToolbarClass, orientation_changed), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_ORIENTATION); + toolbar_signals[STYLE_CHANGED] = + g_signal_new ("style_changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EggToolbarClass, style_changed), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_TOOLBAR_STYLE); + + g_object_class_install_property (gobject_class, + PROP_ORIENTATION, + g_param_spec_enum ("orientation", + _("Orientation"), + _("The orientation of the toolbar"), + GTK_TYPE_ORIENTATION, + GTK_ORIENTATION_HORIZONTAL, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_TOOLBAR_STYLE, + g_param_spec_enum ("toolbar_style", + _("Toolbar Style"), + _("How to draw the toolbar"), + GTK_TYPE_TOOLBAR_STYLE, + GTK_TOOLBAR_ICONS, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_SHOW_ARROW, + g_param_spec_boolean ("show_arrow", + _("Show Arrow"), + _("If an arrow should be shown if the toolbar doesn't fit"), + FALSE, + G_PARAM_READWRITE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("space_size", + _("Spacer size"), + _("Size of spacers"), + 0, + G_MAXINT, + DEFAULT_SPACE_SIZE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("internal_padding", + _("Internal padding"), + _("Amount of border space between the toolbar shadow and the buttons"), + 0, + G_MAXINT, + DEFAULT_IPADDING, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_enum ("space_style", + _("Space style"), + _("Whether spacers are vertical lines or just blank"), + GTK_TYPE_TOOLBAR_SPACE_STYLE, + DEFAULT_SPACE_STYLE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_enum ("button_relief", + _("Button relief"), + _("Type of bevel around toolbar buttons"), + GTK_TYPE_RELIEF_STYLE, + GTK_RELIEF_NONE, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property (widget_class, + g_param_spec_enum ("shadow_type", + _("Shadow type"), + _("Style of bevel around the toolbar"), + GTK_TYPE_SHADOW_TYPE, + GTK_SHADOW_OUT, + G_PARAM_READABLE)); + + gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style", + _("Toolbar style"), + _("Whether default toolbars have text only, text and icons, icons only, etc."), + GTK_TYPE_TOOLBAR_STYLE, + DEFAULT_TOOLBAR_STYLE, + G_PARAM_READWRITE)); + + gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size", + _("Toolbar icon size"), + _("Size of icons in default toolbars"), + GTK_TYPE_ICON_SIZE, + DEFAULT_ICON_SIZE, + G_PARAM_READWRITE)); +} + +static void +egg_toolbar_init (EggToolbar *toolbar) +{ + EggToolbarPrivate *priv; + + GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW); + GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS); + + priv = g_new0 (EggToolbarPrivate, 1); + g_object_set_data (G_OBJECT (toolbar), PRIVATE_KEY, priv); + + toolbar->orientation = GTK_ORIENTATION_HORIZONTAL; + toolbar->style = GTK_TOOLBAR_ICONS; + toolbar->tooltips = gtk_tooltips_new (); + g_object_ref (toolbar->tooltips); + gtk_object_sink (GTK_OBJECT (toolbar->tooltips)); + + priv->button = gtk_toggle_button_new (); + g_signal_connect (priv->button, "button_press_event", + G_CALLBACK (egg_toolbar_button_press), toolbar); + gtk_button_set_relief (GTK_BUTTON (priv->button), + get_button_relief (toolbar)); + GTK_WIDGET_UNSET_FLAGS (priv->button, GTK_CAN_FOCUS); + + priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE); + gtk_widget_show (priv->arrow); + gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow); + + gtk_widget_set_parent (priv->button, GTK_WIDGET (toolbar)); +} + +static void +egg_toolbar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EggToolbar *toolbar = EGG_TOOLBAR (object); + + switch (prop_id) + { + case PROP_ORIENTATION: + egg_toolbar_set_orientation (toolbar, g_value_get_enum (value)); + break; + case PROP_TOOLBAR_STYLE: + egg_toolbar_set_style (toolbar, g_value_get_enum (value)); + break; + case PROP_SHOW_ARROW: + egg_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +egg_toolbar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EggToolbar *toolbar = EGG_TOOLBAR (object); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + switch (prop_id) + { + case PROP_ORIENTATION: + g_value_set_enum (value, toolbar->orientation); + break; + case PROP_TOOLBAR_STYLE: + g_value_set_enum (value, toolbar->style); + break; + case PROP_SHOW_ARROW: + g_value_set_boolean (value, priv->show_arrow); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +egg_toolbar_paint_space_line (GtkWidget *widget, + GdkRectangle *area, + EggToolItem *item) +{ + EggToolbar *toolbar; + GtkAllocation *allocation; + gint space_size; + + g_return_if_fail (GTK_BIN (item)->child == NULL); + + toolbar = EGG_TOOLBAR (widget); + + allocation = >K_WIDGET (item)->allocation; + space_size = get_space_size (toolbar); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_paint_vline (widget->style, widget->window, + GTK_WIDGET_STATE (widget), area, widget, + "toolbar", + allocation->y + allocation->height * + SPACE_LINE_START / SPACE_LINE_DIVISION, + allocation->y + allocation->height * + SPACE_LINE_END / SPACE_LINE_DIVISION, + allocation->x + (space_size-widget->style->xthickness)/2); + else if (toolbar->orientation == GTK_ORIENTATION_VERTICAL) + gtk_paint_hline (widget->style, widget->window, + GTK_WIDGET_STATE (widget), area, widget, + "toolbar", + allocation->x + allocation->width * + SPACE_LINE_START / SPACE_LINE_DIVISION, + allocation->x + allocation->width * + SPACE_LINE_END / SPACE_LINE_DIVISION, + allocation->y + (space_size-widget->style->ythickness)/2); +} + +static gint +egg_toolbar_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + EggToolbar *toolbar = EGG_TOOLBAR (widget); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + GList *items; + gint border_width; + + border_width = GTK_CONTAINER (widget)->border_width; + + if (GTK_WIDGET_DRAWABLE (widget)) + { + GtkShadowType shadow_type; + + gtk_widget_style_get (widget, "shadow_type", &shadow_type, NULL); + + gtk_paint_box (widget->style, + widget->window, + GTK_WIDGET_STATE (widget), + shadow_type, + &event->area, widget, "toolbar", + widget->allocation.x + border_width, + widget->allocation.y + border_width, + widget->allocation.width - border_width, + widget->allocation.height - border_width); + + } + + items = priv->items; + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (GTK_BIN (item)->child) + gtk_container_propagate_expose (GTK_CONTAINER (widget), + GTK_WIDGET (item), + event); + else if (GTK_WIDGET_MAPPED (item) && get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE) + egg_toolbar_paint_space_line (widget, &event->area, item); + + items = items->next; + } + + gtk_container_propagate_expose (GTK_CONTAINER (widget), + priv->button, + event); + + return FALSE; +} + +static void +egg_toolbar_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EggToolbar *toolbar = EGG_TOOLBAR (widget); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GList *items; + gint nbuttons, ipadding; + gint button_maxw, button_maxh; + gint total_button_maxw, total_button_maxh; + gint space_size; + GtkRequisition child_requisition; + + requisition->width = GTK_CONTAINER (toolbar)->border_width * 2; + requisition->height = GTK_CONTAINER (toolbar)->border_width * 2; + nbuttons = 0; + button_maxw = 0; + button_maxh = 0; + total_button_maxw = 0; + total_button_maxh = 0; + items = priv->items; + space_size = get_space_size (toolbar); + + if (priv->show_arrow) + { + /* When we enable the arrow we only want to be the + * size of the arrows plus the size of any items that + * are pack-end. + */ + + items = priv->items; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (TOOLBAR_ITEM_VISIBLE (item)) + { + gtk_widget_size_request (GTK_WIDGET (item), &child_requisition); + + total_button_maxw = MAX (total_button_maxw, child_requisition.width); + total_button_maxh = MAX (total_button_maxh, child_requisition.height); + + if (item->homogeneous) + { + if (item->pack_end) + nbuttons++; + button_maxw = MAX (button_maxw, child_requisition.width); + button_maxh = MAX (button_maxh, child_requisition.height); + } + else if (item->pack_end) + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + requisition->width += child_requisition.width; + else + requisition->height += child_requisition.height; + } + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + requisition->height = MAX (requisition->height, child_requisition.height); + else + requisition->width = MAX (requisition->width, child_requisition.width); + } + + items = items->next; + } + + /* Add the arrow */ + gtk_widget_size_request (priv->button, &child_requisition); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + requisition->width += child_requisition.width; + requisition->height = MAX (requisition->height, child_requisition.height); + } + else + { + requisition->height += child_requisition.height; + requisition->width = MAX (requisition->width, child_requisition.width); + } + } + else + { + items = priv->items; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (!TOOLBAR_ITEM_VISIBLE (item)) + { + items = items->next; + continue; + } + + if (!GTK_BIN (item)->child) + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + requisition->width += space_size; + else + requisition->height += space_size; + } + else + { + gtk_widget_size_request (GTK_WIDGET (item), &child_requisition); + + total_button_maxw = MAX (total_button_maxw, child_requisition.width); + total_button_maxh = MAX (total_button_maxh, child_requisition.height); + + if (item->homogeneous) + { + nbuttons++; + button_maxw = MAX (button_maxw, child_requisition.width); + button_maxh = MAX (button_maxh, child_requisition.height); + } + else + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + requisition->width += child_requisition.width; + requisition->height = MAX (requisition->height, child_requisition.height); + } + else + { + requisition->height += child_requisition.height; + requisition->width = MAX (requisition->width, child_requisition.width); + } + } + } + + items = items->next; + } + } + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + requisition->width += nbuttons * button_maxw; + requisition->height = MAX (requisition->height, button_maxh); + } + else + { + requisition->width = MAX (requisition->width, button_maxw); + requisition->height += nbuttons * button_maxh; + } + + /* Extra spacing */ + gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); + + requisition->width += 2 * ipadding; + requisition->height += 2 * ipadding; + + priv->total_button_maxw = total_button_maxw; + priv->total_button_maxh = total_button_maxh; + + toolbar->button_maxw = button_maxw; + toolbar->button_maxh = button_maxh; +} + +static void +egg_toolbar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EggToolbar *toolbar = EGG_TOOLBAR (widget); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GList *items; + GtkAllocation child_allocation; + gint ipadding, space_size; + gint border_width, edge_position; + gint available_width, available_height; + gint available_size, total_size; + GtkRequisition child_requisition; + gint remaining_size; + gint number_expandable, expandable_size; + gboolean first_expandable; + + widget->allocation = *allocation; + border_width = GTK_CONTAINER (widget)->border_width; + total_size = 0; + number_expandable = 0; + space_size = get_space_size (toolbar); + + gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); + border_width += ipadding; + + available_width = allocation->width - 2 * border_width; + available_height = allocation->height - 2 * border_width; + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + edge_position = allocation->x + allocation->width - border_width; + available_size = available_width; + } + else + { + edge_position = allocation->y + allocation->height - border_width; + available_size = available_height; + } + + items = g_list_last (priv->items); + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (!item->pack_end || !TOOLBAR_ITEM_VISIBLE (item)) + { + items = items->prev; + continue; + } + + if (!GTK_BIN (item)->child) + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + child_allocation.width = space_size; + child_allocation.height = available_height; + child_allocation.x = edge_position - child_allocation.width; + child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + + edge_position -= child_allocation.width; + available_size -= child_allocation.width; + } + else + { + child_allocation.width = available_width; + child_allocation.height = space_size; + child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; + child_allocation.y = edge_position - child_allocation.height; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + + edge_position -= child_allocation.height; + available_size -= child_allocation.height; + } + } + else + { + gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (item->homogeneous) + child_allocation.width = toolbar->button_maxw; + else + child_allocation.width = child_requisition.width; + child_allocation.height = available_height; + child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2; + child_allocation.x = edge_position - child_allocation.width; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + + edge_position -= child_allocation.width; + available_size -= child_allocation.width; + } + else + { + if (item->homogeneous) + child_allocation.height = toolbar->button_maxh; + else + child_allocation.height = child_requisition.height; + + child_allocation.width = available_width; + child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; + child_allocation.y = edge_position - child_allocation.height; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + + edge_position -= child_allocation.height; + available_size -= child_allocation.height; + } + } + + items = items->prev; + } + + /* Now go through the items and see if they fit */ + items = priv->items; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (item->pack_end || !TOOLBAR_ITEM_VISIBLE (item)) + { + items = items->next; + continue; + } + + if (item->expandable) + number_expandable += 1; + + if (!GTK_BIN (item)->child) + { + total_size += space_size; + } + else + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + + if (item->homogeneous) + total_size += toolbar->button_maxw; + else + total_size += child_requisition.width; + } + else + { + gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + + if (item->homogeneous) + total_size += toolbar->button_maxh; + else + total_size += child_requisition.height; + } + } + items = items->next; + } + + /* Check if we need to allocate and show the arrow */ + if (available_size < total_size) + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gtk_widget_get_child_requisition (priv->button, &child_requisition); + available_size -= child_requisition.width; + + child_allocation.width = child_requisition.width; + child_allocation.height = priv->total_button_maxh; + child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2; + child_allocation.x = edge_position - child_allocation.width; + } + else + { + gtk_widget_get_child_requisition (priv->button, &child_requisition); + available_size -= child_requisition.width; + + child_allocation.height = child_requisition.height; + child_allocation.width = priv->total_button_maxw; + child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; + child_allocation.y = edge_position - child_allocation.height; + } + + gtk_widget_size_allocate (priv->button, &child_allocation); + gtk_widget_show (priv->button); + } + else + gtk_widget_hide (priv->button); + + /* Finally allocate the remaining items */ + items = priv->items; + child_allocation.x = allocation->x + border_width; + child_allocation.y = allocation->y + border_width; + remaining_size = MAX (0, available_size - total_size); + total_size = 0; + first_expandable = TRUE; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (item->pack_end || !TOOLBAR_ITEM_VISIBLE (item)) + { + items = items->next; + continue; + } + + if (!GTK_BIN (item)->child) + { + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + child_allocation.width = space_size; + child_allocation.height = available_height; + child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2; + total_size += child_allocation.width; + + if (total_size > available_size) + break; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + gtk_widget_map (GTK_WIDGET (item)); + + child_allocation.x += child_allocation.width; + } + else + { + child_allocation.width = available_width; + child_allocation.height = space_size; + child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; + total_size += child_allocation.height; + + if (total_size > available_size) + break; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + gtk_widget_map (GTK_WIDGET (item)); + + child_allocation.y += child_allocation.height; + } + } + else + { + gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + + if (item->expandable) + { + expandable_size = remaining_size / number_expandable; + + if (first_expandable) + { + expandable_size += remaining_size % number_expandable; + first_expandable = FALSE; + } + } + else + expandable_size = 0; + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (item->homogeneous) + child_allocation.width = toolbar->button_maxw; + else + child_allocation.width = child_requisition.width; + + child_allocation.height = available_height; + child_allocation.width += expandable_size; + child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2; + total_size += child_allocation.width; + } + else + { + if (item->homogeneous) + child_allocation.height = toolbar->button_maxh; + else + child_allocation.height = child_requisition.height; + + child_allocation.width = available_width; + child_allocation.height += expandable_size; + child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; + total_size += child_allocation.height; + } + + if (total_size > available_size) + break; + + gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + gtk_widget_map (GTK_WIDGET (item)); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + child_allocation.x += child_allocation.width; + else + child_allocation.y += child_allocation.height; + + } + + items = items->next; + } + + /* Unmap the remaining items */ + priv->first_non_fitting_item = items; + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + gtk_widget_unmap (GTK_WIDGET (item)); + items = items->next; + } +} + +static void +egg_toolbar_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + if (prev_style) + egg_toolbar_update_button_relief (EGG_TOOLBAR (widget)); +} + +static gboolean +egg_toolbar_focus (GtkWidget *widget, + GtkDirectionType dir) +{ + /* Focus can't go in toolbars */ + + return FALSE; +} + +static void +style_change_notify (EggToolbar *toolbar) +{ + if (!toolbar->style_set) + { + /* pretend it was set, then unset, thus reverting to new default */ + toolbar->style_set = TRUE; + egg_toolbar_unset_style (toolbar); + } +} + +static void +icon_size_change_notify (EggToolbar *toolbar) +{ + if (!toolbar->icon_size_set) + { + /* pretend it was set, then unset, thus reverting to new default */ + toolbar->icon_size_set = TRUE; + egg_toolbar_unset_icon_size (toolbar); + } +} + +static GtkSettings * +toolbar_get_settings (EggToolbar *toolbar) +{ + return g_object_get_data (G_OBJECT (toolbar), "egg-toolbar-settings"); +} + +static void +egg_toolbar_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen) +{ + EggToolbar *toolbar = EGG_TOOLBAR (widget); + GtkSettings *old_settings = toolbar_get_settings (toolbar); + GtkSettings *settings; + + if (gtk_widget_has_screen (GTK_WIDGET (toolbar))) + settings = gtk_widget_get_settings (GTK_WIDGET (toolbar)); + else + settings = NULL; + + if (settings == old_settings) + return; + + if (old_settings) + { + g_signal_handler_disconnect (old_settings, toolbar->style_set_connection); + g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection); + + g_object_unref (old_settings); + } + + if (settings) + { + toolbar->style_set_connection = + g_signal_connect_swapped (settings, + "notify::gtk-toolbar-style", + G_CALLBACK (style_change_notify), + toolbar); + toolbar->icon_size_connection = + g_signal_connect_swapped (settings, + "notify::gtk-toolbar-icon-size", + G_CALLBACK (icon_size_change_notify), + toolbar); + + g_object_ref (settings); + g_object_set_data (G_OBJECT (toolbar), "egg-toolbar-settings", settings); + } + else + g_object_set_data (G_OBJECT (toolbar), "egg-toolbar-settings", NULL); + + style_change_notify (toolbar); + icon_size_change_notify (toolbar); +} + + +static void +egg_toolbar_add (GtkContainer *container, + GtkWidget *widget) +{ + g_return_if_fail (EGG_IS_TOOLBAR (container)); + g_return_if_fail (EGG_IS_TOOL_ITEM (widget)); + + egg_toolbar_append_tool_item (EGG_TOOLBAR (container), + EGG_TOOL_ITEM (widget)); +} + +static void +egg_toolbar_remove (GtkContainer *container, + GtkWidget *widget) +{ + g_return_if_fail (EGG_IS_TOOLBAR (container)); + g_return_if_fail (EGG_IS_TOOL_ITEM (widget)); + + egg_toolbar_remove_tool_item (EGG_TOOLBAR (container), + EGG_TOOL_ITEM (widget)); +} + +static void +egg_toolbar_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EggToolbar *toolbar = EGG_TOOLBAR (container); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GList *items; + + g_return_if_fail (callback != NULL); + + items = priv->items; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + items = items->next; + (*callback) (GTK_WIDGET (item), callback_data); + } + + if (include_internals) + (* callback) (priv->button, callback_data); +} + +static GType +egg_toolbar_child_type (GtkContainer *container) +{ + return EGG_TYPE_TOOL_ITEM; +} + +static void +egg_toolbar_real_orientation_changed (EggToolbar *toolbar, + GtkOrientation orientation) +{ + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + GList *items; + + if (toolbar->orientation != orientation) + { + toolbar->orientation = orientation; + + items = priv->items; + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + egg_tool_item_set_orientation (item, orientation); + + items = items->next; + } + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE); + else + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE); + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + g_object_notify (G_OBJECT (toolbar), "orientation"); + } +} + +static void +egg_toolbar_real_style_changed (EggToolbar *toolbar, + GtkToolbarStyle style) +{ + EggToolbarPrivate *priv; + GList *items; + + priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + if (toolbar->style != style) + { + toolbar->style = style; + + items = priv->items; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + egg_tool_item_set_toolbar_style (item, style); + + items = items->next; + } + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + g_object_notify (G_OBJECT (toolbar), "toolbar_style"); + } +} + +static void +menu_position_func (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + gpointer user_data) +{ + EggToolbar *toolbar = EGG_TOOLBAR (user_data); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GtkRequisition req; + + gdk_window_get_origin (GTK_BUTTON (priv->button)->event_window, x, y); + gtk_widget_size_request (priv->button, &req); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + *y += priv->button->allocation.height; + *x += priv->button->allocation.width - req.width; + } + else + { + *x += priv->button->allocation.width; + *y += priv->button->allocation.height - req.height; + } + + *push_in = TRUE; +} + +static void +menu_deactivated (GtkWidget *menu, GtkWidget *button) +{ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); +} + +static void +egg_toolbar_button_press (GtkWidget *button, + GdkEventButton *event, + EggToolbar *toolbar) +{ + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GtkWidget *menu; + GtkWidget *menu_item; + GList *items; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + + menu = gtk_menu_new (); + g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivated), button); + + items = priv->first_non_fitting_item; + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + if (TOOLBAR_ITEM_VISIBLE (item) && !item->pack_end) + { + menu_item = NULL; + g_signal_emit_by_name (item, "create_menu_proxy", &menu_item); + + if (menu_item) + { + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + } + } + items = items->next; + } + + gtk_widget_show_all (menu); + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + menu_position_func, toolbar, + event->button, event->time); +} + +static void +egg_toolbar_update_button_relief (EggToolbar *toolbar) +{ + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GtkReliefStyle relief; + GList *items; + + relief = get_button_relief (toolbar); + + items = priv->items; + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + egg_tool_item_set_relief_style (item, relief); + + items = items->next; + } + + gtk_button_set_relief (GTK_BUTTON (priv->button), relief); +} + +static GtkReliefStyle +get_button_relief (EggToolbar *toolbar) +{ + GtkReliefStyle button_relief = GTK_RELIEF_NORMAL; + + gtk_widget_ensure_style (GTK_WIDGET (toolbar)); + + gtk_widget_style_get (GTK_WIDGET (toolbar), + "button_relief", &button_relief, + NULL); + + return button_relief; +} + +static gint +get_space_size (EggToolbar *toolbar) +{ + gint space_size = DEFAULT_SPACE_SIZE; + + gtk_widget_style_get (GTK_WIDGET (toolbar), + "space_size", &space_size, + NULL); + + return space_size; +} + +static GtkToolbarSpaceStyle +get_space_style (EggToolbar *toolbar) +{ + GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE; + + gtk_widget_style_get (GTK_WIDGET (toolbar), + "space_style", &space_style, + NULL); + + + return space_style; +} + +GtkWidget * +egg_toolbar_new (void) +{ + EggToolbar *toolbar; + + toolbar = g_object_new (EGG_TYPE_TOOLBAR, NULL); + + return GTK_WIDGET (toolbar); +} + +void +egg_toolbar_append_tool_item (EggToolbar *toolbar, + EggToolItem *item) +{ + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + g_return_if_fail (EGG_IS_TOOL_ITEM (item)); + + egg_toolbar_insert_tool_item (toolbar, item, toolbar->num_children); +} + +void +egg_toolbar_prepend_tool_item (EggToolbar *toolbar, + EggToolItem *item) +{ + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + g_return_if_fail (EGG_IS_TOOL_ITEM (item)); + + egg_toolbar_insert_tool_item (toolbar, item, 0); +} + +void +egg_toolbar_remove_tool_item (EggToolbar *toolbar, + EggToolItem *item) +{ + EggToolbarPrivate *priv; + GList *tmp; + + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + g_return_if_fail (EGG_IS_TOOL_ITEM (item)); + + priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + for (tmp = priv->items; tmp != NULL; tmp = tmp->next) + { + GtkWidget *child = tmp->data; + + if (child == GTK_WIDGET (item)) + { + gboolean was_visible; + + was_visible = GTK_WIDGET_VISIBLE (item); + gtk_widget_unparent (GTK_WIDGET (item)); + + priv->items = g_list_remove_link (priv->items, tmp); + toolbar->num_children--; + + if (was_visible && GTK_WIDGET_VISIBLE (toolbar)) + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + + break; + } + } +} + +void +egg_toolbar_insert_tool_item (EggToolbar *toolbar, + EggToolItem *item, + gint pos) +{ + EggToolbarPrivate *priv; + + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + g_return_if_fail (EGG_IS_TOOL_ITEM (item)); + + priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + priv->items = g_list_insert (priv->items, item, pos); + toolbar->num_children++; + + egg_tool_item_set_orientation (item, toolbar->orientation); + egg_tool_item_set_toolbar_style (item, toolbar->style); + egg_tool_item_set_relief_style (item, get_button_relief (toolbar)); + + gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar)); + GTK_WIDGET_UNSET_FLAGS (item, GTK_CAN_FOCUS); +} + +void +egg_toolbar_set_orientation (EggToolbar *toolbar, + GtkOrientation orientation) +{ + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + + g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation); +} + +GtkOrientation +egg_toolbar_get_orientation (EggToolbar *toolbar) +{ + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL); + + return toolbar->orientation; +} + +void +egg_toolbar_set_style (EggToolbar *toolbar, + GtkToolbarStyle style) +{ + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + + toolbar->style_set = TRUE; + g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style); +} + +GtkToolbarStyle +egg_toolbar_get_style (EggToolbar *toolbar) +{ + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE); + + return toolbar->style; +} + +void +egg_toolbar_unset_style (EggToolbar *toolbar) +{ + GtkToolbarStyle style; + + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + + if (toolbar->style_set) + { + GtkSettings *settings = toolbar_get_settings (toolbar); + + if (settings) + g_object_get (settings, + "gtk-toolbar-style", &style, + NULL); + else + style = DEFAULT_TOOLBAR_STYLE; + + if (style != toolbar->style) + g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style); + + toolbar->style_set = FALSE; + } +} + +void +egg_toolbar_set_tooltips (EggToolbar *toolbar, + gboolean enable) +{ + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + + if (enable) + gtk_tooltips_enable (toolbar->tooltips); + else + gtk_tooltips_disable (toolbar->tooltips); +} + +gboolean +egg_toolbar_get_tooltips (EggToolbar *toolbar) +{ + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), FALSE); + + return toolbar->tooltips->enabled; +} + +GList* +egg_toolbar_get_tool_items (EggToolbar *toolbar) +{ + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), FALSE); + + return priv->items; +} + +void +egg_toolbar_set_icon_size (EggToolbar *toolbar, + GtkIconSize icon_size) +{ + GList *items; + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + + toolbar->icon_size_set = TRUE; + + if (toolbar->icon_size == icon_size) + return; + + toolbar->icon_size = icon_size; + + items = priv->items; + + while (items) + { + EggToolItem *item = EGG_TOOL_ITEM (items->data); + + egg_tool_item_set_icon_size (item, icon_size); + + items = items->next; + } + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); +} + +GtkIconSize +egg_toolbar_get_icon_size (EggToolbar *toolbar) +{ + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE); + + return toolbar->icon_size; +} + +void +egg_toolbar_unset_icon_size (EggToolbar *toolbar) +{ + GtkIconSize size; + + if (toolbar->icon_size_set) + { + GtkSettings *settings = toolbar_get_settings (toolbar); + + if (settings) + g_object_get (settings, + "gtk-toolbar-icon-size", &size, + NULL); + else + size = DEFAULT_ICON_SIZE; + + if (size != toolbar->icon_size) + egg_toolbar_set_icon_size (toolbar, size); + + toolbar->icon_size_set = FALSE; + } +} + + +void +egg_toolbar_set_show_arrow (EggToolbar *toolbar, + gboolean show_arrow) +{ + EggToolbarPrivate *priv; + + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + + priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + show_arrow = show_arrow != FALSE; + + if (priv->show_arrow != show_arrow) + { + priv->show_arrow = show_arrow; + + if (!priv->show_arrow) + gtk_widget_hide (priv->button); + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + g_object_notify (G_OBJECT (toolbar), "show_arrow"); + } +} + +gboolean +egg_toolbar_get_show_arrow (EggToolbar *toolbar) +{ + EggToolbarPrivate *priv; + + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), FALSE); + + priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + return priv->show_arrow; +} + +GtkWidget * +egg_toolbar_append_item (EggToolbar *toolbar, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data) +{ + return egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON, + NULL, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, + toolbar->num_children); +} + +GtkWidget * +egg_toolbar_prepend_item (EggToolbar *toolbar, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data) +{ + return egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON, + NULL, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, + 0); +} + +GtkWidget * +egg_toolbar_insert_item (EggToolbar *toolbar, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data, + gint position) +{ + return egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON, + NULL, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, + position); +} + +GtkWidget* +egg_toolbar_insert_stock (EggToolbar *toolbar, + const gchar *stock_id, + const char *tooltip_text, + const char *tooltip_private_text, + GtkSignalFunc callback, + gpointer user_data, + gint position) +{ + return egg_toolbar_internal_insert_element (toolbar, EGG_TOOLBAR_CHILD_BUTTON, + NULL, stock_id, + tooltip_text, tooltip_private_text, + NULL, callback, user_data, + position, TRUE); +} + +void +egg_toolbar_append_space (EggToolbar *toolbar) +{ + egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_SPACE, + NULL, NULL, + NULL, NULL, + NULL, NULL, NULL, + toolbar->num_children); +} + +void +egg_toolbar_prepend_space (EggToolbar *toolbar) +{ + egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_SPACE, + NULL, NULL, + NULL, NULL, + NULL, NULL, NULL, + 0); +} + +void +egg_toolbar_insert_space (EggToolbar *toolbar, + gint position) +{ + egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_SPACE, + NULL, NULL, + NULL, NULL, + NULL, NULL, NULL, + position); +} + +void +egg_toolbar_append_widget (EggToolbar *toolbar, + GtkWidget *widget, + const gchar *tooltip_text, + const gchar *tooltip_private_text) +{ + egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_WIDGET, + widget, NULL, + tooltip_text, tooltip_private_text, + NULL, NULL, NULL, + toolbar->num_children); +} + +void +egg_toolbar_prepend_widget (EggToolbar *toolbar, + GtkWidget *widget, + const gchar *tooltip_text, + const gchar *tooltip_private_text) +{ + egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_WIDGET, + widget, NULL, + tooltip_text, tooltip_private_text, + NULL, NULL, NULL, + 0); +} + +void +egg_toolbar_insert_widget (EggToolbar *toolbar, + GtkWidget *widget, + const char *tooltip_text, + const char *tooltip_private_text, + gint position) +{ + egg_toolbar_insert_element (toolbar, EGG_TOOLBAR_CHILD_WIDGET, + widget, NULL, + tooltip_text, tooltip_private_text, + NULL, NULL, NULL, + position); +} + +GtkWidget* +egg_toolbar_append_element (EggToolbar *toolbar, + GtkToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data) +{ + return egg_toolbar_insert_element (toolbar, type, widget, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, + toolbar->num_children); +} + +GtkWidget * +egg_toolbar_prepend_element (EggToolbar *toolbar, + GtkToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data) +{ + return egg_toolbar_insert_element (toolbar, type, widget, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, 0); +} + +GtkWidget * +egg_toolbar_insert_element (EggToolbar *toolbar, + EggToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data, + gint position) +{ + return egg_toolbar_internal_insert_element (toolbar, type, widget, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, position, FALSE); +} + +static GtkWidget * +egg_toolbar_internal_insert_element (EggToolbar *toolbar, + EggToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data, + gint position, + gboolean use_stock) +{ + EggToolbarChild *child; + EggToolItem *item = NULL; + + g_return_val_if_fail (EGG_IS_TOOLBAR (toolbar), NULL); + + if (type == EGG_TOOLBAR_CHILD_WIDGET) + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + else if (type != EGG_TOOLBAR_CHILD_RADIOBUTTON) + g_return_val_if_fail (widget == NULL, NULL); + + child = g_new (EggToolbarChild, 1); + + child->type = type; + child->icon = NULL; + child->label = NULL; + + switch (type) + { + case EGG_TOOLBAR_CHILD_SPACE: + item = egg_separator_tool_item_new (); + child->widget = NULL; + break; + + case EGG_TOOLBAR_CHILD_WIDGET: + item = egg_tool_item_new (); + child->widget = widget; + gtk_container_add (GTK_CONTAINER (item), child->widget); + + break; + + case EGG_TOOLBAR_CHILD_BUTTON: + item = egg_tool_button_new (); + child->widget = EGG_TOOL_BUTTON (item)->button; + break; + + case EGG_TOOLBAR_CHILD_TOGGLEBUTTON: + item = egg_toggle_tool_button_new (); + child->widget = EGG_TOOL_BUTTON (item)->button; + break; + + case EGG_TOOLBAR_CHILD_RADIOBUTTON: + item = egg_radio_tool_button_new (widget + ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget)) + : NULL); + child->widget = EGG_TOOL_BUTTON (item)->button; + break; + } + + /* + * We need to connect to the button's clicked callback because some + * programs may rely on that the widget in the callback is a GtkButton + */ + if (callback) + g_signal_connect (child->widget, "clicked", + callback, user_data); + + if (type == EGG_TOOLBAR_CHILD_BUTTON || + type == EGG_TOOLBAR_CHILD_RADIOBUTTON || + type == EGG_TOOLBAR_CHILD_TOGGLEBUTTON) + { + if (text) + { + child->label = EGG_TOOL_BUTTON (item)->label; + + if (use_stock) + g_object_set (G_OBJECT (item), "stock_id", text, NULL); + else + egg_tool_button_set_label (EGG_TOOL_BUTTON (item), text); + } + + if (icon) + { + child->icon = icon; + egg_tool_button_set_icon_widget (EGG_TOOL_BUTTON (item), icon); + } + + } + + if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text) + egg_tool_item_set_tooltip (item, toolbar->tooltips, + tooltip_text, tooltip_private_text); + + toolbar->children = g_list_insert (toolbar->children, child, position); + egg_toolbar_insert_tool_item (toolbar, item, position); + + return child->widget; +} |