[gthumb] Completed the GthToggleMenuToolButton implementation



commit bac8e9a4977c90faee553a5818433094c79749cc
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Jul 15 20:27:58 2010 +0200

    Completed the GthToggleMenuToolButton implementation
    
    *) use a custom container to avoid a run-time warning.
    *) add the submenu to the menu item proxy.

 extensions/export_tools/callbacks.c  |    6 +-
 extensions/list_tools/callbacks.c    |   12 +-
 extensions/list_tools/gth-script.c   |   12 +-
 gthumb/gth-toggle-menu-tool-button.c |  702 ++++++++++++++++++++++++++++++++--
 gthumb/gth-toggle-menu-tool-button.h |   39 ++-
 5 files changed, 709 insertions(+), 62 deletions(-)
---
diff --git a/extensions/export_tools/callbacks.c b/extensions/export_tools/callbacks.c
index 191287a..aa95add 100644
--- a/extensions/export_tools/callbacks.c
+++ b/extensions/export_tools/callbacks.c
@@ -55,8 +55,10 @@ export_tools__gth_browser_construct_cb (GthBrowser *browser)
 
 	/* export tools menu button */
 
-	tool_item = g_object_new (GTH_TYPE_TOGGLE_MENU_TOOL_BUTTON, "icon-name", "share", NULL);
-	gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), _gtk_create_toggle_menu_tool_label (_("Share")));
+	tool_item = g_object_new (GTH_TYPE_TOGGLE_MENU_TOOL_BUTTON,
+				  "icon-name", "share",
+				  "label", _("Share"),
+				  NULL);
 	/*gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), _("Export files"));*/
 	gth_toggle_menu_tool_button_set_menu (GTH_TOGGLE_MENU_TOOL_BUTTON (tool_item),
 					      gtk_ui_manager_get_widget (gth_browser_get_ui_manager (browser), "/ExportPopup"));
diff --git a/extensions/list_tools/callbacks.c b/extensions/list_tools/callbacks.c
index 6e0e178..3ed2c84 100644
--- a/extensions/list_tools/callbacks.c
+++ b/extensions/list_tools/callbacks.c
@@ -233,8 +233,10 @@ list_tools__gth_browser_construct_cb (GthBrowser *browser)
 
 	/* tools menu button */
 
-	tool_item = gth_toggle_menu_tool_button_new_from_stock (GTK_STOCK_EXECUTE);
-	gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), _gtk_create_toggle_menu_tool_label (_("Tools")));
+	tool_item = g_object_new (GTH_TYPE_TOGGLE_MENU_TOOL_BUTTON,
+				  "stock-id", GTK_STOCK_EXECUTE,
+				  "label", _("Tools"),
+				  NULL);
 	gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), _("Batch tools for multiple files"));
 	gth_toggle_menu_tool_button_set_menu (GTH_TOGGLE_MENU_TOOL_BUTTON (tool_item),
 					      gtk_ui_manager_get_widget (gth_browser_get_ui_manager (browser), "/ListToolsPopup"));
@@ -242,8 +244,10 @@ list_tools__gth_browser_construct_cb (GthBrowser *browser)
 	gtk_widget_show (GTK_WIDGET (tool_item));
 	gtk_toolbar_insert (GTK_TOOLBAR (gth_browser_get_browser_toolbar (browser)), tool_item, -1);
 
-	tool_item = gth_toggle_menu_tool_button_new_from_stock (GTK_STOCK_EXECUTE);
-	gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), _gtk_create_toggle_menu_tool_label (_("Tools")));
+	tool_item = g_object_new (GTH_TYPE_TOGGLE_MENU_TOOL_BUTTON,
+				  "stock-id", GTK_STOCK_EXECUTE,
+				  "label", _("Tools"),
+				  NULL);
 	gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), _("Batch tools for multiple files"));
 	gth_toggle_menu_tool_button_set_menu (GTH_TOGGLE_MENU_TOOL_BUTTON (tool_item),
 					      gtk_ui_manager_get_widget (gth_browser_get_ui_manager (browser), "/ListToolsPopup"));
diff --git a/extensions/list_tools/gth-script.c b/extensions/list_tools/gth-script.c
index 21e14a0..15c0e22 100644
--- a/extensions/list_tools/gth-script.c
+++ b/extensions/list_tools/gth-script.c
@@ -80,6 +80,16 @@ gth_script_real_create_element (DomDomizable *base,
 }
 
 
+static guint
+_gdk_keyval_from_name (const gchar *keyval_name)
+{
+	if (keyval_name != NULL)
+		return gdk_keyval_from_name (keyval_name);
+	else
+		return GDK_VoidSymbol;
+}
+
+
 static void
 gth_script_real_load_from_element (DomDomizable *base,
 				   DomElement   *element)
@@ -97,7 +107,7 @@ gth_script_real_load_from_element (DomDomizable *base,
 		      "shell-script", (g_strcmp0 (dom_element_get_attribute (element, "shell-script"), "true") == 0),
 		      "for-each-file", (g_strcmp0 (dom_element_get_attribute (element, "for-each-file"), "true") == 0),
 		      "wait-command", (g_strcmp0 (dom_element_get_attribute (element, "wait-command"), "true") == 0),
-		      "shortcut", gdk_keyval_from_name (dom_element_get_attribute (element, "shortcut")),
+		      "shortcut", _gdk_keyval_from_name (dom_element_get_attribute (element, "shortcut")),
 		      NULL);
 }
 
diff --git a/gthumb/gth-toggle-menu-tool-button.c b/gthumb/gth-toggle-menu-tool-button.c
index 53af2c8..60129e5 100644
--- a/gthumb/gth-toggle-menu-tool-button.c
+++ b/gthumb/gth-toggle-menu-tool-button.c
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *  Copyright (C) 2009, 2010 Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -20,11 +20,22 @@
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
 
+#include <string.h>
+#include <gtk/gtk.h>
 #include "gth-toggle-menu-tool-button.h"
 
+#define MENU_ID "gth-toggle-menu-tool-button-menu-id"
+
 struct _GthToggleMenuToolButtonPrivate {
+	guint      active : 1;
+	guint      use_underline : 1;
+	char      *stock_id;
+	char      *icon_name;
+	char      *label_text;
 	GtkWidget *toggle_button;
 	GtkMenu   *menu;
+	GtkWidget *icon_widget;
+	GtkWidget *label_widget;
 };
 
 enum {
@@ -34,13 +45,289 @@ enum {
 
 enum {
 	PROP_0,
+	PROP_LABEL,
+	PROP_USE_UNDERLINE,
+	PROP_STOCK_ID,
+	PROP_ICON_NAME,
+	PROP_ACTIVE,
 	PROP_MENU
 };
 
 static gpointer parent_class = NULL;
+static GtkActivatableIface *parent_activatable_iface;
 static int signals[LAST_SIGNAL];
 
 
+gchar *
+_gtk_toolbar_elide_underscores (const gchar *original)
+{
+  gchar *q, *result;
+  const gchar *p, *end;
+  gsize len;
+  gboolean last_underscore;
+
+  if (!original)
+    return NULL;
+
+  len = strlen (original);
+  q = result = g_malloc (len + 1);
+  last_underscore = FALSE;
+
+  end = original + len;
+  for (p = original; p < end; p++)
+    {
+      if (!last_underscore && *p == '_')
+        last_underscore = TRUE;
+      else
+        {
+          last_underscore = FALSE;
+          if (original + 2 <= p && p + 1 <= end &&
+              p[-2] == '(' && p[-1] == '_' && p[0] != '_' && p[1] == ')')
+            {
+              q--;
+              *q = '\0';
+              p++;
+            }
+          else
+            *q++ = *p;
+        }
+    }
+
+  if (last_underscore)
+    *q++ = '_';
+
+  *q = '\0';
+
+  return result;
+}
+
+
+static void
+gth_toggle_menu_tool_button_construct_contents (GtkToolItem *tool_item)
+{
+	GthToggleMenuToolButton *button = GTH_TOGGLE_MENU_TOOL_BUTTON (tool_item);
+	GtkWidget               *label = NULL;
+	GtkWidget               *icon = NULL;
+	GtkToolbarStyle          style;
+	gboolean                 need_label = FALSE;
+	gboolean                 need_icon = FALSE;
+	GtkWidget               *arrow;
+	GtkWidget               *arrow_align;
+	GtkIconSize              icon_size;
+	GtkWidget               *box = NULL;
+	guint                    icon_spacing;
+	GtkOrientation           text_orientation = GTK_ORIENTATION_HORIZONTAL;
+	GtkSizeGroup            *size_group = NULL;
+
+	gtk_widget_style_get (GTK_WIDGET (tool_item),
+			      "icon-spacing", &icon_spacing,
+			      NULL);
+
+	if (button->priv->icon_widget && button->priv->icon_widget->parent)
+		gtk_container_remove (GTK_CONTAINER (button->priv->icon_widget->parent),
+				      button->priv->icon_widget);
+
+	if (button->priv->label_widget && button->priv->label_widget->parent)
+		gtk_container_remove (GTK_CONTAINER (button->priv->label_widget->parent),
+				      button->priv->label_widget);
+
+	if (GTK_BIN (button->priv->toggle_button)->child)
+		/* Note: we are not destroying the label_widget or icon_widget
+		 * here because they were removed from their containers above
+		 */
+		gtk_widget_destroy (GTK_BIN (button->priv->toggle_button)->child);
+
+	style = gtk_tool_item_get_toolbar_style (GTK_TOOL_ITEM (button));
+
+	if (style != GTK_TOOLBAR_TEXT)
+		need_icon = TRUE;
+
+	if ((style != GTK_TOOLBAR_ICONS) && (style != GTK_TOOLBAR_BOTH_HORIZ))
+		need_label = TRUE;
+
+	if ((style == GTK_TOOLBAR_BOTH_HORIZ) &&
+	    (gtk_tool_item_get_is_important (GTK_TOOL_ITEM (button))
+	     || (gtk_tool_item_get_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL)
+	     || (gtk_tool_item_get_text_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL)))
+	{
+		need_label = TRUE;
+	}
+
+	if ((style == GTK_TOOLBAR_ICONS)
+	    && (button->priv->icon_widget == NULL)
+	    && (button->priv->stock_id == NULL)
+	    && button->priv->icon_name == NULL)
+	{
+		need_label = TRUE;
+		need_icon = FALSE;
+		style = GTK_TOOLBAR_TEXT;
+	}
+
+	if ((style == GTK_TOOLBAR_TEXT)
+	    && (button->priv->label_widget == NULL)
+	    && (button->priv->stock_id == NULL)
+	    && (button->priv->label_text == NULL))
+	{
+		need_label = FALSE;
+		need_icon = TRUE;
+		style = GTK_TOOLBAR_ICONS;
+	}
+
+	if (need_label) {
+		if (button->priv->label_widget) {
+			label = button->priv->label_widget;
+		}
+		else {
+			GtkStockItem  stock_item;
+			gboolean      elide;
+			char         *label_text;
+
+			if (button->priv->label_text) {
+				label_text = button->priv->label_text;
+				elide = button->priv->use_underline;
+			}
+			else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item)) {
+				label_text = stock_item.label;
+				elide = TRUE;
+			}
+			else {
+				label_text = "";
+				elide = FALSE;
+			}
+
+			if (elide)
+				label_text = _gtk_toolbar_elide_underscores (label_text);
+			else
+				label_text = g_strdup (label_text);
+
+			label = gtk_label_new (label_text);
+
+			g_free (label_text);
+
+			gtk_widget_show (label);
+		}
+
+		gtk_label_set_ellipsize (GTK_LABEL (label),
+					 gtk_tool_item_get_ellipsize_mode (GTK_TOOL_ITEM (button)));
+		text_orientation = gtk_tool_item_get_text_orientation (GTK_TOOL_ITEM (button));
+		if (text_orientation == GTK_ORIENTATION_HORIZONTAL) {
+			gtk_label_set_angle (GTK_LABEL (label), 0);
+			gtk_misc_set_alignment (GTK_MISC (label),
+						gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)),
+						0.5);
+		}
+		else {
+			gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
+			if (gtk_widget_get_direction (GTK_WIDGET (tool_item)) == GTK_TEXT_DIR_RTL)
+				gtk_label_set_angle (GTK_LABEL (label), -90);
+			else
+				gtk_label_set_angle (GTK_LABEL (label), 90);
+			gtk_misc_set_alignment (GTK_MISC (label),
+						0.5,
+						1 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)));
+		}
+	}
+
+	icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
+	if (need_icon) {
+		if (button->priv->icon_widget) {
+			icon = button->priv->icon_widget;
+
+			if (GTK_IS_IMAGE (icon)) {
+				g_object_set (button->priv->icon_widget,
+					      "icon-size", icon_size,
+					      NULL);
+			}
+		}
+		else if (button->priv->stock_id
+			 && gtk_icon_factory_lookup_default (button->priv->stock_id))
+		{
+			icon = gtk_image_new_from_stock (button->priv->stock_id, icon_size);
+			gtk_widget_show (icon);
+		}
+		else if (button->priv->icon_name) {
+			icon = gtk_image_new_from_icon_name (button->priv->icon_name, icon_size);
+			gtk_widget_show (icon);
+		}
+
+		if (icon && text_orientation == GTK_ORIENTATION_HORIZONTAL)
+			gtk_misc_set_alignment (GTK_MISC (icon),
+						1.0 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)),
+						0.5);
+		else if (icon)
+			gtk_misc_set_alignment (GTK_MISC (icon),
+						0.5,
+						gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)));
+
+		if (icon) {
+			size_group = gtk_tool_item_get_text_size_group (GTK_TOOL_ITEM (button));
+			if (size_group != NULL)
+				gtk_size_group_add_widget (size_group, icon);
+		}
+	}
+
+	arrow = gtk_arrow_new ((text_orientation == GTK_ORIENTATION_HORIZONTAL) ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+	gtk_widget_show (arrow);
+
+	arrow_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (arrow_align), 0, 0, icon_spacing, 0);
+	gtk_widget_show (arrow_align);
+	gtk_container_add (GTK_CONTAINER (arrow_align), arrow);
+
+	size_group = gtk_tool_item_get_text_size_group (GTK_TOOL_ITEM (button));
+	if (size_group != NULL)
+		gtk_size_group_add_widget (size_group, arrow_align);
+
+	if (text_orientation == GTK_ORIENTATION_HORIZONTAL)
+		box = gtk_hbox_new (FALSE, icon_spacing);
+	else
+		box = gtk_vbox_new (FALSE, icon_spacing);
+	gtk_widget_show (box);
+	gtk_container_add (GTK_CONTAINER (button->priv->toggle_button), box);
+
+	gtk_box_pack_end (GTK_BOX (box), arrow_align, FALSE, FALSE, 0);
+
+	switch (style) {
+	case GTK_TOOLBAR_ICONS:
+		if (icon)
+			gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
+		break;
+
+	case GTK_TOOLBAR_BOTH:
+		if (icon)
+			gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
+		gtk_box_pack_end (GTK_BOX (box), label, FALSE, TRUE, 0);
+		break;
+
+	case GTK_TOOLBAR_BOTH_HORIZ:
+		if (text_orientation == GTK_ORIENTATION_HORIZONTAL) {
+			if (icon)
+				gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0);
+			if (label)
+				gtk_box_pack_end (GTK_BOX (box), label, TRUE, TRUE, 0);
+		}
+		else {
+			if (icon)
+				gtk_box_pack_end (GTK_BOX (box), icon, label ? FALSE : TRUE, TRUE, 0);
+			if (label)
+				gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
+		}
+		break;
+
+	case GTK_TOOLBAR_TEXT:
+		gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
+		break;
+	}
+
+	gtk_button_set_relief (GTK_BUTTON (button->priv->toggle_button),
+			       gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
+
+	gtk_tool_item_rebuild_menu (tool_item);
+
+	gtk_widget_queue_resize (GTK_WIDGET (button));
+}
+
+
 static void
 gth_toggle_menu_tool_button_state_changed (GtkWidget    *widget,
 					   GtkStateType  previous_state)
@@ -53,6 +340,30 @@ gth_toggle_menu_tool_button_state_changed (GtkWidget    *widget,
 
 
 static void
+gth_toggle_menu_tool_button_update_icon_spacing (GthToggleMenuToolButton *button)
+{
+	GtkWidget *box;
+	guint spacing;
+
+	box = GTK_BIN (button->priv->toggle_button)->child;
+	if (GTK_IS_BOX (box)) {
+		gtk_widget_style_get (GTK_WIDGET (button),
+				      "icon-spacing", &spacing,
+				      NULL);
+		gtk_box_set_spacing (GTK_BOX (box), spacing);
+	}
+}
+
+
+static void
+gth_toggle_menu_tool_button_style_set (GtkWidget *widget,
+				       GtkStyle  *prev_style)
+{
+	gth_toggle_menu_tool_button_update_icon_spacing (GTH_TOGGLE_MENU_TOOL_BUTTON (widget));
+}
+
+
+static void
 gth_toggle_menu_tool_button_set_property (GObject      *object,
 					  guint         prop_id,
 					  const GValue *value,
@@ -61,6 +372,21 @@ gth_toggle_menu_tool_button_set_property (GObject      *object,
 	GthToggleMenuToolButton *button = GTH_TOGGLE_MENU_TOOL_BUTTON (object);
 
 	switch (prop_id) {
+	case PROP_LABEL:
+		gth_toggle_menu_tool_button_set_label (button, g_value_get_string (value));
+		break;
+	case PROP_USE_UNDERLINE:
+		gth_toggle_menu_tool_button_set_use_underline (button, g_value_get_boolean (value));
+		break;
+	case PROP_STOCK_ID:
+		gth_toggle_menu_tool_button_set_stock_id (button, g_value_get_string (value));
+		break;
+	case PROP_ICON_NAME:
+		gth_toggle_menu_tool_button_set_icon_name (button, g_value_get_string (value));
+		break;
+	case PROP_ACTIVE:
+		gth_toggle_menu_tool_button_set_active (button, g_value_get_boolean (value));
+		break;
 	case PROP_MENU:
 		gth_toggle_menu_tool_button_set_menu (button, g_value_get_object (value));
 		break;
@@ -80,6 +406,21 @@ gth_toggle_menu_tool_button_get_property (GObject    *object,
 	GthToggleMenuToolButton *button = GTH_TOGGLE_MENU_TOOL_BUTTON (object);
 
 	switch (prop_id) {
+	case PROP_LABEL:
+		g_value_set_string (value, gth_toggle_menu_tool_button_get_label (button));
+		break;
+	case PROP_USE_UNDERLINE:
+		g_value_set_boolean (value, gth_toggle_menu_tool_button_get_use_underline (button));
+		break;
+	case PROP_STOCK_ID:
+		g_value_set_string (value, button->priv->stock_id);
+		break;
+	case PROP_ICON_NAME:
+		g_value_set_string (value, button->priv->icon_name);
+		break;
+	case PROP_ACTIVE:
+		g_value_set_boolean (value, gth_toggle_menu_tool_button_get_active (button));
+		break;
 	case PROP_MENU:
 		g_value_set_object (value, button->priv->menu);
 		break;
@@ -178,6 +519,8 @@ popup_menu_under_button (GthToggleMenuToolButton *button,
 	if (button->priv->menu == NULL)
 		return;
 
+	if (gtk_menu_get_attach_widget (button->priv->menu) != NULL)
+		gtk_menu_detach (button->priv->menu);
 	gtk_menu_popup (button->priv->menu, NULL, NULL,
 			(GtkMenuPositionFunc) menu_position_func,
 			button,
@@ -190,15 +533,21 @@ static gboolean
 real_button_toggled_cb (GtkToggleButton         *togglebutton,
                         GthToggleMenuToolButton *button)
 {
+	gboolean toggle_active = gtk_toggle_button_get_active (togglebutton);
 
 	if (button->priv->menu == NULL)
 		return FALSE;
 
-	if (gtk_toggle_button_get_active (togglebutton) && ! GTK_WIDGET_VISIBLE (button->priv->menu)) {
-		/* we get here only when the menu is activated by a key
-		 * press, so that we can select the first menu item */
-		popup_menu_under_button (button, NULL);
-		gtk_menu_shell_select_first (GTK_MENU_SHELL (button->priv->menu), FALSE);
+	if (button->priv->active != toggle_active) {
+		button->priv->active = toggle_active;
+		g_object_notify (G_OBJECT (button), "active");
+
+		if (button->priv->active && ! GTK_WIDGET_VISIBLE (button->priv->menu)) {
+			/* we get here only when the menu is activated by a key
+			 * press, so that we can select the first menu item */
+			popup_menu_under_button (button, NULL);
+			gtk_menu_shell_select_first (GTK_MENU_SHELL (button->priv->menu), FALSE);
+		}
 	}
 
 	return FALSE;
@@ -242,29 +591,83 @@ gth_toggle_menu_tool_button_destroy (GtkObject *object)
 }
 
 
+static gboolean
+gth_toggle_menu_tool_button_create_menu_proxy (GtkToolItem *item)
+{
+	GthToggleMenuToolButton *button;
+	GtkStockItem             stock_item;
+	gboolean                 use_mnemonic = TRUE;
+	const char              *label_text;
+	const char              *stock_id;
+	const char              *label;
+	GtkWidget               *menu_item;
+
+	button = GTH_TOGGLE_MENU_TOOL_BUTTON (item);
+
+	label_text = gth_toggle_menu_tool_button_get_label (button);
+	stock_id = gth_toggle_menu_tool_button_get_stock_id (button);
+
+	if (label_text) {
+		label = label_text;
+		use_mnemonic = gth_toggle_menu_tool_button_get_use_underline (button);
+	}
+	else if ((stock_id != NULL) && gtk_stock_lookup (stock_id, &stock_item)) {
+		label = stock_item.label;
+	}
+	else {
+		label = "";
+	}
+
+	if (use_mnemonic)
+		menu_item = gtk_menu_item_new_with_mnemonic (label);
+	else
+		menu_item = gtk_menu_item_new_with_label (label);
+
+	g_object_ref (button->priv->menu);
+	if (gtk_menu_get_attach_widget (button->priv->menu) != NULL)
+		gtk_menu_detach (button->priv->menu);
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), GTK_WIDGET (button->priv->menu));
+
+	gtk_tool_item_set_proxy_menu_item (item, MENU_ID, menu_item);
+
+	return TRUE;
+}
+
+
+static void
+gth_toggle_menu_tool_button_toolbar_reconfigured (GtkToolItem *tool_item)
+{
+	gth_toggle_menu_tool_button_construct_contents (tool_item);
+}
+
+
 static void
 gth_toggle_menu_tool_button_class_init (GthToggleMenuToolButtonClass *klass)
 {
 	GObjectClass     *object_class;
 	GtkObjectClass   *gtk_object_class;
 	GtkWidgetClass   *widget_class;
-	/*GtkToolItemClass *toolitem_class;*/
+	GtkToolItemClass *tool_item_class;
 
 	parent_class = g_type_class_peek_parent (klass);
 	g_type_class_add_private (klass, sizeof (GthToggleMenuToolButtonPrivate));
 
-	object_class = (GObjectClass *)klass;
+	object_class = (GObjectClass *) klass;
 	object_class->set_property = gth_toggle_menu_tool_button_set_property;
 	object_class->get_property = gth_toggle_menu_tool_button_get_property;
 
-	gtk_object_class = (GtkObjectClass *)klass;
+	gtk_object_class = (GtkObjectClass *) klass;
 	gtk_object_class->destroy = gth_toggle_menu_tool_button_destroy;
 
-	widget_class = (GtkWidgetClass *)klass;
+	widget_class = (GtkWidgetClass *) klass;
 	widget_class->state_changed = gth_toggle_menu_tool_button_state_changed;
+	widget_class->style_set = gth_toggle_menu_tool_button_style_set;
 
-	/*toolitem_class = (GtkToolItemClass *)klass;
-	toolitem_class->toolbar_reconfigured = gth_toggle_menu_tool_button_toolbar_reconfigured;*/
+	tool_item_class = (GtkToolItemClass *) klass;
+	tool_item_class->create_menu_proxy = gth_toggle_menu_tool_button_create_menu_proxy;
+	tool_item_class->toolbar_reconfigured = gth_toggle_menu_tool_button_toolbar_reconfigured;
+
+	/* signals */
 
 	/**
 	 * GthToggleMenuToolButton::show-menu:
@@ -274,7 +677,7 @@ gth_toggle_menu_tool_button_class_init (GthToggleMenuToolButtonClass *klass)
 	 *
 	 * It can be used to populate the menu on demand, using
 	 * gth_toggle_menu_tool_button_get_menu().
-
+	 *
 	 * Note that even if you populate the menu dynamically in this way,
 	 * you must set an empty menu on the #GthToggleMenuToolButton beforehand,
 	 * since the arrow is made insensitive if the menu is not set.
@@ -288,13 +691,59 @@ gth_toggle_menu_tool_button_class_init (GthToggleMenuToolButtonClass *klass)
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE, 0);
 
+	/* properties */
+
+	g_object_class_install_property (object_class,
+					 PROP_LABEL,
+					 g_param_spec_string ("label",
+							      "Label",
+							      "Text to show in the item.",
+							      NULL,
+							      G_PARAM_READABLE | G_PARAM_WRITABLE));
+	g_object_class_install_property (object_class,
+					 PROP_USE_UNDERLINE,
+					 g_param_spec_boolean ("use-underline",
+							       "Use underline",
+							       "If set, an underline in the label property indicates that the next character should be used for the mnemonic accelerator key in the overflow menu",
+							       FALSE,
+							       G_PARAM_READABLE | G_PARAM_WRITABLE));
+	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_READABLE | G_PARAM_WRITABLE));
 	g_object_class_install_property (object_class,
-                                        PROP_MENU,
-                                        g_param_spec_object ("menu",
-                                                             "Menu",
-                                                             "The dropdown menu",
-                                                             GTK_TYPE_MENU,
-                                                             G_PARAM_READABLE | G_PARAM_WRITABLE));
+					 PROP_ICON_NAME,
+					 g_param_spec_string ("icon-name",
+							      "Icon name",
+							      "The name of the themed icon displayed on the item",
+							      NULL,
+							      G_PARAM_READABLE | G_PARAM_WRITABLE));
+	g_object_class_install_property (object_class,
+					 PROP_ACTIVE,
+					 g_param_spec_boolean ("active",
+							       "Active",
+							       "If the toggle button should be pressed in or not",
+							       FALSE,
+							       G_PARAM_READABLE | G_PARAM_WRITABLE));
+	g_object_class_install_property (object_class,
+					 PROP_MENU,
+					 g_param_spec_object ("menu",
+							      "Menu",
+							      "The dropdown menu",
+							      GTK_TYPE_MENU,
+							      G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+	gtk_widget_class_install_style_property (widget_class,
+						 g_param_spec_int ("icon-spacing",
+								   "Icon spacing",
+								   "Spacing in pixels between the icon and label",
+								   0,
+								   G_MAXINT,
+								   3,
+								   G_PARAM_READABLE | G_PARAM_WRITABLE));
 }
 
 
@@ -304,7 +753,11 @@ gth_toggle_menu_tool_button_init (GthToggleMenuToolButton *button)
 	button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button, GTH_TYPE_TOGGLE_MENU_TOOL_BUTTON, GthToggleMenuToolButtonPrivate);
 	button->priv->menu = NULL;
 
-	button->priv->toggle_button = gtk_bin_get_child (GTK_BIN (button));
+	button->priv->toggle_button = gtk_toggle_button_new ();
+	gtk_button_set_focus_on_click (GTK_BUTTON (button->priv->toggle_button), FALSE);
+	gtk_container_add (GTK_CONTAINER (button), button->priv->toggle_button);
+	gtk_widget_show (button->priv->toggle_button);
+
 	g_signal_connect (button->priv->toggle_button,
 			  "toggled",
 			  G_CALLBACK (real_button_toggled_cb),
@@ -313,6 +766,58 @@ gth_toggle_menu_tool_button_init (GthToggleMenuToolButton *button)
 			  "button-press-event",
 		          G_CALLBACK (real_button_button_press_event_cb),
 		          button);
+
+	button->priv->active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button->priv->toggle_button));
+}
+
+
+static void
+gth_toggle_menu_tool_button_update (GtkActivatable *activatable,
+				    GtkAction      *action,
+				    const gchar    *property_name)
+{
+	GthToggleMenuToolButton *button;
+
+	parent_activatable_iface->update (activatable, action, property_name);
+
+	if (! GTK_IS_TOGGLE_ACTION (action))
+		return;
+
+	button = GTH_TOGGLE_MENU_TOOL_BUTTON (activatable);
+
+	if (strcmp (property_name, "active") == 0) {
+		gtk_action_block_activate (action);
+		gth_toggle_menu_tool_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+		gtk_action_unblock_activate (action);
+	}
+}
+
+
+static void
+gth_toggle_menu_tool_button_sync_action_properties (GtkActivatable *activatable,
+						    GtkAction      *action)
+{
+	GthToggleMenuToolButton *button;
+
+	parent_activatable_iface->sync_action_properties (activatable, action);
+
+	if (! GTK_IS_TOGGLE_ACTION (action))
+		return;
+
+	button = GTH_TOGGLE_MENU_TOOL_BUTTON (activatable);
+
+	gtk_action_block_activate (action);
+	gth_toggle_menu_tool_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+	gtk_action_unblock_activate (action);
+}
+
+
+static void
+gth_toggle_menu_tool_button_gtk_activable_interface_init (GtkActivatableIface *iface)
+{
+	parent_activatable_iface = g_type_interface_peek_parent (iface);
+	iface->update = gth_toggle_menu_tool_button_update;
+	iface->sync_action_properties = gth_toggle_menu_tool_button_sync_action_properties;
 }
 
 
@@ -333,10 +838,17 @@ gth_toggle_menu_tool_button_get_type (void)
 			0,
 			(GInstanceInitFunc) gth_toggle_menu_tool_button_init
 		};
-		type = g_type_register_static (GTK_TYPE_TOGGLE_TOOL_BUTTON,
+		static const GInterfaceInfo gtk_activable_info = {
+			(GInterfaceInitFunc) gth_toggle_menu_tool_button_gtk_activable_interface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+
+		type = g_type_register_static (GTK_TYPE_TOOL_ITEM,
 					       "GthToggleMenuToolButton",
 					       &type_info,
 					       0);
+		g_type_add_interface_static (type, GTK_TYPE_ACTIVATABLE, &gtk_activable_info);
 	}
 
         return type;
@@ -362,6 +874,133 @@ gth_toggle_menu_tool_button_new_from_stock (const gchar *stock_id)
 
 
 void
+gth_toggle_menu_tool_button_set_label (GthToggleMenuToolButton *button,
+				       const char              *label)
+{
+	char *old_label;
+
+	g_return_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button));
+
+	old_label = button->priv->label_text;
+	button->priv->label_text = g_strdup (label);
+
+	if (label != NULL) {
+		char      *elided_label;
+		AtkObject *accessible;
+
+		elided_label = _gtk_toolbar_elide_underscores (label);
+		accessible = gtk_widget_get_accessible (GTK_WIDGET (button->priv->toggle_button));
+		atk_object_set_name (accessible, elided_label);
+
+		g_free (elided_label);
+	}
+
+	g_free (old_label);
+
+	g_object_notify (G_OBJECT (button), "label");
+}
+
+
+G_CONST_RETURN char *
+gth_toggle_menu_tool_button_get_label (GthToggleMenuToolButton *button)
+{
+	g_return_val_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button), NULL);
+
+	return button->priv->label_text;
+}
+
+
+void
+gth_toggle_menu_tool_button_set_use_underline (GthToggleMenuToolButton *button,
+					       gboolean                 use_underline)
+{
+	g_return_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button));
+
+	use_underline = use_underline != FALSE;
+
+	if (use_underline != button->priv->use_underline) {
+		button->priv->use_underline = use_underline;
+		g_object_notify (G_OBJECT (button), "use-underline");
+	}
+}
+
+
+gboolean
+gth_toggle_menu_tool_button_get_use_underline (GthToggleMenuToolButton *button)
+{
+	g_return_val_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button), FALSE);
+
+	return button->priv->use_underline;
+}
+
+
+void
+gth_toggle_menu_tool_button_set_stock_id (GthToggleMenuToolButton *button,
+					  const char              *stock_id)
+{
+	g_return_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button));
+
+	g_free (button->priv->stock_id);
+	button->priv->stock_id = g_strdup (stock_id);
+
+	g_object_notify (G_OBJECT (button), "stock-id");
+}
+
+
+G_CONST_RETURN char *
+gth_toggle_menu_tool_button_get_stock_id (GthToggleMenuToolButton *button)
+{
+	g_return_val_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button), NULL);
+
+	return button->priv->stock_id;
+}
+
+
+void
+gth_toggle_menu_tool_button_set_icon_name (GthToggleMenuToolButton *button,
+					   const char              *icon_name)
+{
+	g_return_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button));
+
+	g_free (button->priv->icon_name);
+	button->priv->icon_name = g_strdup (icon_name);
+
+	g_object_notify (G_OBJECT (button), "icon-name");
+}
+
+
+G_CONST_RETURN char*
+gth_toggle_menu_tool_button_get_icon_name (GthToggleMenuToolButton *button)
+{
+	g_return_val_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button), NULL);
+
+	return button->priv->icon_name;
+}
+
+
+void
+gth_toggle_menu_tool_button_set_active (GthToggleMenuToolButton *button,
+					gboolean                 is_active)
+{
+	g_return_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button));
+
+	is_active = is_active != FALSE;
+
+	if (button->priv->active != is_active)
+		gtk_button_clicked (GTK_BUTTON (button->priv->toggle_button));
+}
+
+
+gboolean
+gth_toggle_menu_tool_button_get_active (GthToggleMenuToolButton *button)
+{
+	  g_return_val_if_fail (GTH_IS_TOGGLE_MENU_TOOL_BUTTON (button), FALSE);
+
+	  return button->priv->active;
+}
+
+
+void
 gth_toggle_menu_tool_button_set_menu (GthToggleMenuToolButton *button,
 				      GtkWidget               *menu)
 {
@@ -398,24 +1037,3 @@ gth_toggle_menu_tool_button_get_menu (GthToggleMenuToolButton *button)
 
 	return GTK_WIDGET (button->priv->menu);
 }
-
-
-GtkWidget *
-_gtk_create_toggle_menu_tool_label (const char *label)
-{
-	GtkWidget *box1;
-	GtkWidget *box2;
-	GtkWidget *child;
-
-	box2 = gtk_hbox_new (FALSE, 6);
-	child = gtk_label_new (label);
-	gtk_box_pack_start (GTK_BOX (box2), child, FALSE, FALSE, 0);
-	child = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
-	gtk_box_pack_start (GTK_BOX (box2), child, FALSE, FALSE, 0);
-
-	box1 = gtk_hbox_new (FALSE, 0);
-	gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, FALSE, 0);
-	gtk_widget_show_all (box1);
-
-	return box1;
-}
diff --git a/gthumb/gth-toggle-menu-tool-button.h b/gthumb/gth-toggle-menu-tool-button.h
index 3abf791..790a023 100644
--- a/gthumb/gth-toggle-menu-tool-button.h
+++ b/gthumb/gth-toggle-menu-tool-button.h
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *  Copyright (C) 2009, 2010 Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,27 +41,40 @@ typedef struct _GthToggleMenuToolButtonPrivate GthToggleMenuToolButtonPrivate;
 
 struct _GthToggleMenuToolButton
 {
-	GtkToggleToolButton parent;
+	GtkToolItem parent;
 	GthToggleMenuToolButtonPrivate *priv;
 };
 
 struct _GthToggleMenuToolButtonClass
 {
-	GtkToggleToolButtonClass parent_class;
+	GtkToolItemClass parent_class;
+
+	/*< signals >*/
 
 	void (*show_menu) (GthToggleMenuToolButton *button);
 };
 
-GType         gth_toggle_menu_tool_button_get_type       (void) G_GNUC_CONST;
-GtkToolItem * gth_toggle_menu_tool_button_new            (void);
-GtkToolItem * gth_toggle_menu_tool_button_new_from_stock (const char              *stock_id);
-void          gth_toggle_menu_tool_button_set_menu       (GthToggleMenuToolButton *button,
-							  GtkWidget               *menu);
-GtkWidget *   gth_toggle_menu_tool_button_get_menu       (GthToggleMenuToolButton *button);
-
-/* utility */
-
-GtkWidget *   _gtk_create_toggle_menu_tool_label         (const char *label);
+GType                   gth_toggle_menu_tool_button_get_type          (void) G_GNUC_CONST;
+GtkToolItem *           gth_toggle_menu_tool_button_new               (void);
+GtkToolItem *           gth_toggle_menu_tool_button_new_from_stock    (const char              *stock_id);
+void                    gth_toggle_menu_tool_button_set_label         (GthToggleMenuToolButton *button,
+								       const char              *label);
+G_CONST_RETURN char *   gth_toggle_menu_tool_button_get_label         (GthToggleMenuToolButton *button);
+void                    gth_toggle_menu_tool_button_set_use_underline (GthToggleMenuToolButton *button,
+								       gboolean                 use_underline);
+gboolean                gth_toggle_menu_tool_button_get_use_underline (GthToggleMenuToolButton *button);
+void                    gth_toggle_menu_tool_button_set_stock_id      (GthToggleMenuToolButton *button,
+								       const char              *stock_id);
+G_CONST_RETURN char *   gth_toggle_menu_tool_button_get_stock_id      (GthToggleMenuToolButton *button);
+void                    gth_toggle_menu_tool_button_set_icon_name     (GthToggleMenuToolButton *button,
+								       const char              *icon_name);
+G_CONST_RETURN char *   gth_toggle_menu_tool_button_get_icon_name     (GthToggleMenuToolButton *button);
+void                    gth_toggle_menu_tool_button_set_active        (GthToggleMenuToolButton *button,
+								       gboolean                 is_active);
+gboolean                gth_toggle_menu_tool_button_get_active        (GthToggleMenuToolButton *button);
+void                    gth_toggle_menu_tool_button_set_menu          (GthToggleMenuToolButton *button,
+								       GtkWidget               *menu);
+GtkWidget *             gth_toggle_menu_tool_button_get_menu          (GthToggleMenuToolButton *button);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]