aboutsummaryrefslogtreecommitdiffstats
path: root/lib/egg/eggtoolbutton.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/egg/eggtoolbutton.c')
-rw-r--r--lib/egg/eggtoolbutton.c670
1 files changed, 670 insertions, 0 deletions
diff --git a/lib/egg/eggtoolbutton.c b/lib/egg/eggtoolbutton.c
new file mode 100644
index 000000000..7c6e8e865
--- /dev/null
+++ b/lib/egg/eggtoolbutton.c
@@ -0,0 +1,670 @@
+/* eggtoolbutton.c
+ *
+ * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
+ * Copyright (C) 2002 James Henstridge <james@daa.com.au>
+ *
+ * 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.
+ */
+
+#include "eggtoolbutton.h"
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkiconfactory.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkimagemenuitem.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkvbox.h>
+
+#include <string.h>
+
+#ifndef _
+# define _(s) (s)
+#endif
+
+enum {
+ PROP_0,
+ PROP_LABEL,
+ PROP_USE_UNDERLINE,
+ PROP_STOCK_ID,
+ PROP_ICON_SET,
+ PROP_ICON_WIDGET,
+};
+
+static void egg_tool_button_init (EggToolButton *button,
+ EggToolButtonClass *klass);
+static void egg_tool_button_class_init (EggToolButtonClass *klass);
+
+
+static void egg_tool_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void egg_tool_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void egg_tool_button_finalize (GObject *object);
+
+static void egg_tool_button_show_all (GtkWidget *widget);
+
+static GtkWidget *egg_tool_button_create_menu_proxy (EggToolItem *item);
+static void egg_tool_button_set_orientation (EggToolItem *tool_item,
+ GtkOrientation orientation);
+static void egg_tool_button_set_icon_size (EggToolItem *tool_item,
+ GtkIconSize icon_size);
+static void egg_tool_button_set_toolbar_style (EggToolItem *tool_item,
+ GtkToolbarStyle style);
+static void egg_tool_button_set_relief_style (EggToolItem *tool_item,
+ GtkReliefStyle style);
+static void egg_tool_button_set_tooltip (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private);
+static void button_clicked (GtkWidget *widget,
+ EggToolButton *button);
+
+static GObjectClass *parent_class = NULL;
+
+GType
+egg_tool_button_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EggToolButtonClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tool_button_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EggToolButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tool_button_init,
+ };
+
+ type = g_type_register_static (EGG_TYPE_TOOL_ITEM,
+ "EggToolButton",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void
+egg_tool_button_class_init (EggToolButtonClass *klass)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ EggToolItemClass *tool_item_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class = (GObjectClass *)klass;
+ widget_class = (GtkWidgetClass *)klass;
+ tool_item_class = (EggToolItemClass *)klass;
+
+ object_class->set_property = egg_tool_button_set_property;
+ object_class->get_property = egg_tool_button_get_property;
+ object_class->finalize = egg_tool_button_finalize;
+
+ widget_class->show_all = egg_tool_button_show_all;
+
+ tool_item_class->create_menu_proxy = egg_tool_button_create_menu_proxy;
+ tool_item_class->set_orientation = egg_tool_button_set_orientation;
+ tool_item_class->set_icon_size = egg_tool_button_set_icon_size;
+ tool_item_class->set_toolbar_style = egg_tool_button_set_toolbar_style;
+ tool_item_class->set_relief_style = egg_tool_button_set_relief_style;
+ tool_item_class->set_tooltip = egg_tool_button_set_tooltip;
+
+ klass->button_type = GTK_TYPE_BUTTON;
+
+ g_object_class_install_property (object_class,
+ PROP_LABEL,
+ g_param_spec_string ("label",
+ _("Label"),
+ _("Text to show in the item."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_USE_UNDERLINE,
+ g_param_spec_boolean ("use_underline",
+ _("Use underline"),
+ _("Interpret underlines in the item label."),
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_STOCK_ID,
+ g_param_spec_string ("stock_id",
+ _("Stock Id"),
+ _("The stock icon displayed on the item."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ICON_SET,
+ g_param_spec_boxed ("icon_set",
+ _("Icon set"),
+ _("Icon set to use to draw the item's icon."),
+ GTK_TYPE_ICON_SET,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ICON_WIDGET,
+ g_param_spec_object ("icon_widget",
+ _("Icon widget"),
+ _("Icon widget to display in the item."),
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE));
+}
+
+static void
+egg_tool_button_init (EggToolButton *button, EggToolButtonClass *klass)
+{
+ EggToolItem *toolitem = EGG_TOOL_ITEM (button);
+
+ toolitem->homogeneous = TRUE;
+
+ /* create button */
+ button->button = g_object_new (klass->button_type, NULL);
+ GTK_WIDGET_UNSET_FLAGS (button->button, GTK_CAN_FOCUS);
+ g_signal_connect_object (button->button, "clicked",
+ G_CALLBACK (button_clicked), button, 0);
+
+ button->box = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (button->button), button->box);
+ gtk_widget_show (button->box);
+
+#if 0
+ button->icon = gtk_image_new();
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon, TRUE, TRUE, 0);
+ gtk_widget_show (button->icon);
+#endif
+
+ button->label = gtk_label_new (NULL);
+ gtk_label_set_use_underline (GTK_LABEL (button->label), TRUE);
+ gtk_box_pack_start (GTK_BOX (button->box), button->label, FALSE, TRUE, 0);
+ gtk_widget_show (button->label);
+
+ gtk_container_add (GTK_CONTAINER (button), button->button);
+ gtk_widget_show (button->button);
+}
+
+static gchar *
+elide_underscores (const gchar *original)
+{
+ gchar *q, *result;
+ const gchar *p;
+ gboolean last_underscore;
+
+ q = result = g_malloc (strlen (original) + 1);
+ last_underscore = FALSE;
+
+ for (p = original; *p; p++)
+ {
+ if (!last_underscore && *p == '_')
+ last_underscore = TRUE;
+ else
+ {
+ last_underscore = FALSE;
+ *q++ = *p;
+ }
+ }
+
+ *q = '\0';
+
+ return result;
+}
+
+static void
+egg_tool_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (object);
+ GtkStockItem stock_item;
+ GtkIconSet *icon_set;
+ gchar *label_no_mnemonic = NULL;
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ egg_tool_button_set_label (button, g_value_get_string (value));
+ break;
+ case PROP_USE_UNDERLINE:
+ gtk_label_set_use_underline (GTK_LABEL (button->label),
+ g_value_get_boolean (value));
+ break;
+ case PROP_STOCK_ID:
+ g_free (button->stock_id);
+ button->stock_id = g_value_dup_string (value);
+ if (!button->label_set)
+ {
+ if (gtk_stock_lookup (button->stock_id, &stock_item))
+ {
+ label_no_mnemonic = elide_underscores (stock_item.label);
+ gtk_label_set_label (GTK_LABEL (button->label), label_no_mnemonic);
+ g_free (label_no_mnemonic);
+ }
+ }
+ if (!button->icon_set)
+ {
+ if (button->icon && !GTK_IS_IMAGE (button->icon))
+ {
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ button->icon = NULL;
+ }
+ if (!button->icon)
+ {
+ button->icon = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (button->box), button->icon, 0);
+ }
+ gtk_image_set_from_stock (GTK_IMAGE (button->icon), button->stock_id,
+ EGG_TOOL_ITEM (button)->icon_size);
+ }
+ break;
+ case PROP_ICON_SET:
+ if (button->icon && !GTK_IS_IMAGE (button->icon))
+ {
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ button->icon = NULL;
+ }
+ if (!button->icon)
+ {
+ button->icon = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (button->box), button->icon, 0);
+ }
+ icon_set = g_value_get_boxed (value);
+ button->icon_set = (icon_set != NULL);
+ if (!button->icon_set && button->stock_id)
+ gtk_image_set_from_stock (GTK_IMAGE (button->icon), button->stock_id,
+ EGG_TOOL_ITEM (button)->icon_size);
+ else
+ gtk_image_set_from_icon_set (GTK_IMAGE (button->icon), icon_set,
+ EGG_TOOL_ITEM (button)->icon_size);
+ break;
+ case PROP_ICON_WIDGET:
+ egg_tool_button_set_icon_widget (button, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_tool_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ if (button->label_set)
+ g_value_set_string (value,
+ gtk_label_get_label (GTK_LABEL (button->label)));
+ break;
+ case PROP_USE_UNDERLINE:
+ g_value_set_boolean (value,
+ gtk_label_get_use_underline (GTK_LABEL (button->label)));
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value, button->stock_id);
+ break;
+ case PROP_ICON_SET:
+ if (GTK_IS_IMAGE (button->icon) &&
+ GTK_IMAGE (button->icon)->storage_type == GTK_IMAGE_ICON_SET)
+ {
+ GtkIconSet *icon_set;
+ gtk_image_get_icon_set (GTK_IMAGE (button->icon), &icon_set, NULL);
+ g_value_set_boxed (value, icon_set);
+ }
+ else
+ g_value_set_boxed (value, NULL);
+ break;
+ case PROP_ICON_WIDGET:
+ g_value_set_object (value, button->icon);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_tool_button_finalize (GObject *object)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (object);
+
+ g_free (button->stock_id);
+ button->stock_id = NULL;
+
+ parent_class->finalize (object);
+}
+
+static void
+egg_tool_button_show_all (GtkWidget *widget)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (widget);
+
+ switch (EGG_TOOL_ITEM (widget)->style)
+ {
+ case GTK_TOOLBAR_ICONS:
+ if (button->icon) gtk_widget_show_all (button->icon);
+ gtk_widget_hide (button->label);
+ gtk_widget_show (button->box);
+ gtk_widget_show (button->button);
+ break;
+ case GTK_TOOLBAR_TEXT:
+ if (button->icon) gtk_widget_hide (button->icon);
+ gtk_widget_show_all (button->label);
+ gtk_widget_show (button->box);
+ gtk_widget_show (button->button);
+ break;
+ case GTK_TOOLBAR_BOTH:
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ gtk_widget_show_all (button->button);
+ }
+
+ gtk_widget_show (GTK_WIDGET (button));
+}
+
+static GtkWidget *
+egg_tool_button_create_menu_proxy (EggToolItem *item)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (item);
+ GtkWidget *menu_item;
+ GtkWidget *image;
+ const char *label;
+
+ label = gtk_label_get_text (GTK_LABEL (button->label));
+
+ menu_item = gtk_image_menu_item_new_with_label (label);
+
+ if (GTK_IS_IMAGE (button->icon))
+ {
+ image = gtk_image_new ();
+
+ if (GTK_IMAGE (button->icon)->storage_type == GTK_IMAGE_STOCK)
+ {
+ gchar *stock_id;
+
+ gtk_image_get_stock (GTK_IMAGE (button->icon),
+ &stock_id, NULL);
+ gtk_image_set_from_stock (GTK_IMAGE (image), stock_id,
+ GTK_ICON_SIZE_MENU);
+ }
+ else if (GTK_IMAGE (button->icon)->storage_type == GTK_IMAGE_ICON_SET)
+ {
+ GtkIconSet *icon_set;
+
+ gtk_image_get_icon_set (GTK_IMAGE (button->icon), &icon_set, NULL);
+ gtk_image_set_from_icon_set (GTK_IMAGE (image), icon_set,
+ GTK_ICON_SIZE_MENU);
+ }
+ else
+ {
+ g_warning ("FIXME: Add more cases here");
+ }
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
+ }
+
+ g_signal_connect_object (menu_item, "activate",
+ G_CALLBACK (gtk_button_clicked),
+ EGG_TOOL_BUTTON (button)->button,
+ G_CONNECT_SWAPPED);
+
+ return menu_item;
+}
+
+static void
+egg_tool_button_set_orientation (EggToolItem *tool_item,
+ GtkOrientation orientation)
+{
+ if (tool_item->orientation != orientation)
+ {
+ tool_item->orientation = orientation;
+ }
+}
+
+static void
+egg_tool_button_set_icon_size (EggToolItem *tool_item,
+ GtkIconSize icon_size)
+{
+ if (tool_item->icon_size != icon_size)
+ {
+ EggToolButton *button = EGG_TOOL_BUTTON (tool_item);
+ char *stock_id;
+
+ if (button->icon && GTK_IS_IMAGE (button->icon) &&
+ gtk_image_get_storage_type (GTK_IMAGE (button->icon)) == GTK_IMAGE_STOCK)
+ {
+ gtk_image_get_stock (GTK_IMAGE (button->icon), &stock_id, NULL);
+ stock_id = g_strdup (stock_id);
+ gtk_image_set_from_stock (GTK_IMAGE (button->icon),
+ stock_id,
+ icon_size);
+ g_free (stock_id);
+ }
+ tool_item->icon_size = icon_size;
+ }
+}
+
+static void
+egg_tool_button_set_toolbar_style (EggToolItem *tool_item,
+ GtkToolbarStyle style)
+{
+ EggToolButton *button = EGG_TOOL_BUTTON (tool_item);
+
+ if (tool_item->style != style)
+ {
+ tool_item->style = style;
+
+ switch (tool_item->style)
+ {
+ case GTK_TOOLBAR_ICONS:
+ gtk_widget_hide (button->label);
+ if (button->icon) {
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->icon);
+ }
+ break;
+ case GTK_TOOLBAR_TEXT:
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->label,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->label);
+ if (button->icon)
+ gtk_widget_hide (button->icon);
+ break;
+ case GTK_TOOLBAR_BOTH:
+ if (GTK_IS_HBOX (button->box))
+ {
+ GtkWidget *vbox;
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox);
+
+ if (button->icon)
+ {
+ g_object_ref (button->icon);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ gtk_box_pack_start (GTK_BOX (vbox), button->icon,
+ TRUE, TRUE, 0);
+ g_object_unref (button->icon);
+ }
+
+ g_object_ref (button->label);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->label);
+ gtk_box_pack_start (GTK_BOX (vbox), button->label, FALSE, TRUE, 0);
+ g_object_unref (button->label);
+
+ gtk_container_remove (GTK_CONTAINER (button->button), button->box);
+ button->box = vbox;
+ gtk_container_add (GTK_CONTAINER (button->button), button->box);
+ }
+
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->label,
+ FALSE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->label);
+ if (button->icon) {
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->icon);
+ }
+ break;
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ if (GTK_IS_VBOX (button->box))
+ {
+ GtkWidget *hbox;
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox);
+
+ if (button->icon)
+ {
+ g_object_ref (button->icon);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ gtk_box_pack_start (GTK_BOX (hbox), button->icon,
+ TRUE, TRUE, 0);
+ g_object_unref (button->icon);
+ }
+
+ g_object_ref (button->label);
+ gtk_container_remove (GTK_CONTAINER (button->box), button->label);
+ gtk_box_pack_start (GTK_BOX (hbox), button->label, FALSE, TRUE, 0);
+ g_object_unref (button->label);
+
+ gtk_container_remove (GTK_CONTAINER (button->button), button->box);
+ button->box = hbox;
+ gtk_container_add (GTK_CONTAINER (button->button), button->box);
+ }
+
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->label,
+ TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->label);
+ if (button->icon) {
+ gtk_box_set_child_packing (GTK_BOX (button->box), button->icon,
+ FALSE, TRUE, 0, GTK_PACK_START);
+ gtk_widget_show (button->icon);
+ }
+ break;
+ }
+ }
+}
+
+static void
+egg_tool_button_set_relief_style (EggToolItem *tool_item,
+ GtkReliefStyle style)
+{
+ gtk_button_set_relief (GTK_BUTTON (EGG_TOOL_BUTTON (tool_item)->button), style);
+}
+
+static void
+egg_tool_button_set_tooltip (EggToolItem *tool_item,
+ GtkTooltips *tooltips,
+ const gchar *tip_text,
+ const gchar *tip_private)
+{
+ gtk_tooltips_set_tip (tooltips, EGG_TOOL_BUTTON (tool_item)->button,
+ tip_text, tip_private);
+}
+
+static void
+button_clicked (GtkWidget *widget, EggToolButton *button)
+{
+ g_signal_emit_by_name (button, "clicked");
+}
+
+EggToolItem *
+egg_tool_button_new_from_stock (const gchar *stock_id)
+{
+ EggToolButton *button;
+
+ button = g_object_new (EGG_TYPE_TOOL_BUTTON,
+ "stock_id", stock_id,
+ "use_underline", TRUE,
+ NULL);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+EggToolItem *
+egg_tool_button_new (void)
+{
+ EggToolButton *button;
+
+ button = g_object_new (EGG_TYPE_TOOL_BUTTON,
+ NULL);
+
+ return EGG_TOOL_ITEM (button);
+}
+
+void
+egg_tool_button_set_icon_widget (EggToolButton *button,
+ GtkWidget *icon)
+{
+ g_return_if_fail (EGG_IS_TOOL_BUTTON (button));
+ g_return_if_fail (GTK_IS_WIDGET (icon));
+
+ if (button->icon)
+ gtk_container_remove (GTK_CONTAINER (button->box), button->icon);
+ button->icon = NULL;
+
+ button->icon_set = (icon != NULL);
+ if (icon)
+ {
+ button->icon = icon;
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (button->box), button->icon, 0);
+ }
+ else if (button->stock_id)
+ {
+ button->icon = gtk_image_new_from_stock (button->stock_id,
+ EGG_TOOL_ITEM (button)->icon_size);
+ gtk_box_pack_start (GTK_BOX (button->box), button->icon,
+ TRUE, TRUE, 0);
+ }
+}
+
+void
+egg_tool_button_set_label (EggToolButton *button,
+ const gchar *label)
+{
+ gchar *label_no_mnemonic = NULL;
+ GtkStockItem stock_item;
+
+ g_return_if_fail (EGG_IS_TOOL_BUTTON (button));
+ g_return_if_fail (label != NULL);
+
+ button->label_set = (label != NULL);
+
+ if (label)
+ label_no_mnemonic = elide_underscores (label);
+ else if (button->stock_id && gtk_stock_lookup (button->stock_id, &stock_item))
+ label_no_mnemonic = elide_underscores (stock_item.label);
+
+ gtk_label_set_label (GTK_LABEL (button->label), label_no_mnemonic);
+ g_free (label_no_mnemonic);
+}
+