summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog44
-rw-r--r--docs/reference/ChangeLog8
-rw-r--r--docs/reference/gtk/gtk-docs.sgml1
-rw-r--r--docs/reference/gtk/gtk-sections.txt15
-rw-r--r--docs/reference/gtk/gtk.types1
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtk.symbols56
-rw-r--r--gtk/gtkaction.c712
-rw-r--r--gtk/gtkaction.h25
-rw-r--r--gtk/gtkactiongroup.c7
-rw-r--r--gtk/gtkactivatable.c540
-rw-r--r--gtk/gtkactivatable.h88
-rw-r--r--gtk/gtkbutton.c228
-rw-r--r--gtk/gtkcheckmenuitem.c100
-rw-r--r--gtk/gtkimagemenuitem.c142
-rw-r--r--gtk/gtkmenuitem.c238
-rw-r--r--gtk/gtkradioaction.c3
-rw-r--r--gtk/gtkradiomenuitem.c10
-rw-r--r--gtk/gtkrecentaction.c84
-rw-r--r--gtk/gtkrecentchooser.c151
-rw-r--r--gtk/gtkrecentchooserdefault.c83
-rw-r--r--gtk/gtkrecentchoosermenu.c63
-rw-r--r--gtk/gtkrecentchooserprivate.h27
-rw-r--r--gtk/gtktoggleaction.c75
-rw-r--r--gtk/gtktogglebutton.c66
-rw-r--r--gtk/gtktoggletoolbutton.c65
-rw-r--r--gtk/gtktoolbutton.c170
-rw-r--r--gtk/gtktoolitem.c176
29 files changed, 2368 insertions, 813 deletions
diff --git a/ChangeLog b/ChangeLog
index 35b0a817e2..0deeda968b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,49 @@
2009-01-23 Matthias Clasen <mclasen@redhat.com>
+ Bug 560228 – Add "action-controller" property to GtkWidgetClass
+
+ Rework the way actions and proxies interact, to make the
+ interaction less ad hoc, more extensible, and better suited
+ for support in GUI builders like glade.
+
+ To be used as a proxy, a widget must now implement the
+ GtkActivatable interface, and GtkActivatable implementations
+ are responsible for syncing their appearance with the action
+ and for activating the action.
+
+ All the widgets that are commonly used as proxies implement
+ GtkActivatable now.
+
+ Patch by Tristan van Berkom.
+
+ * gtk/gtkactivatable.[hc]: The GtkActivatable interface.
+
+ * gtk/gtkbutton.c:
+ * gtk/gtktogglebutton.c:
+ * gtk/gtktoolitem.c:
+ * gtk/gtktoolbutton.c:
+ * gtk/gtktoggletoolbutton.c:
+ * gtk/gtkmenuitem.c:
+ * gtk/gtkcheckmenuitem.c:
+ * gtk/gtkimagemenuitem.c:
+ * gtk/gtkradiomenuitem.c:
+ * gtk/gtkrecentchooserprivate.h:
+ * gtk/gtkrecentchooser.c:
+ * gtk/gtkrecentchooserdefault.c:
+ * gtk/gtkrecentchoosermenu.c: Implement GtkActivatable.
+ * gtk/gtkaction.[hc]: Move appearance synchronization to
+ GtkActivatable implementations.
+
+ * gtk/gtkradioaction.c:
+ * gtk/gtkrecentaction.c:
+ * gtk/gtktoggleaction.c:
+ * gtk/gtkactiongroup.c: Adapt.
+
+ * gtk/gtk.h: Include gtkactivatable.h
+ * gtk/gtk.symbols: Add new functions
+
+2009-01-23 Matthias Clasen <mclasen@redhat.com>
+
Bug 567124 – proposal to delay doing something related to
immodule until widgets realized
diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog
index 4e9331027a..0df5972956 100644
--- a/docs/reference/ChangeLog
+++ b/docs/reference/ChangeLog
@@ -1,5 +1,13 @@
2009-01-23 Matthias Clasen <mclasen@redhat.com>
+ * gtk/gtk-sections.txt: Add new GtkActivatable API
+
+ * gtk/gtk-docs.sgml: Include GtkActivatable section
+
+ * gtk.types: Add gtk_activatable_get_type
+
+2009-01-23 Matthias Clasen <mclasen@redhat.com>
+
* gtk/gtk-sections.txt: Additions
2009-01-23 Matthias Clasen <mclasen@redhat.com>
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index 51afa822d3..dd203f6653 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -247,6 +247,7 @@ that is, GUI components such as #GtkButton or #GtkTextView.
<xi:include href="xml/gtktoggleaction.xml" />
<xi:include href="xml/gtkradioaction.xml" />
<xi:include href="xml/gtkrecentaction.xml" />
+ <xi:include href="xml/gtkactivatable.xml" />
</chapter>
<chapter id="SelectorWidgets">
diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt
index 10abe573a2..6f1191d07e 100644
--- a/docs/reference/gtk/gtk-sections.txt
+++ b/docs/reference/gtk/gtk-sections.txt
@@ -188,6 +188,8 @@ gtk_action_disconnect_proxy
gtk_action_get_proxies
gtk_action_connect_accelerator
gtk_action_disconnect_accelerator
+gtk_action_block_activate
+gtk_action_unblock_activate
gtk_action_block_activate_from
gtk_action_unblock_activate_from
gtk_action_get_accel_path
@@ -227,6 +229,19 @@ GtkActionPrivate
</SECTION>
<SECTION>
+<FILE>gtkactivatable</FILE>
+<TITLE>GtkActivatable</TITLE>
+gtk_activatable_do_set_related_action
+gtk_activatable_get_related_action
+gtk_activatable_get_use_action_appearance
+gtk_activatable_reset
+gtk_activatable_set_related_action
+gtk_activatable_set_use_action_appearance
+<SUBSECTION Private>
+gtk_activatable_get_type
+</SECTION>
+
+<SECTION>
<FILE>gtkactiongroup</FILE>
<TITLE>GtkActionGroup</TITLE>
GtkActionGroup
diff --git a/docs/reference/gtk/gtk.types b/docs/reference/gtk/gtk.types
index 6481be9895..68e2e52bfe 100644
--- a/docs/reference/gtk/gtk.types
+++ b/docs/reference/gtk/gtk.types
@@ -8,6 +8,7 @@ gtk_accel_map_get_type
gtk_accessible_get_type
gtk_action_get_type
gtk_action_group_get_type
+gtk_activatable_get_type
gtk_adjustment_get_type
gtk_alignment_get_type
gtk_arrow_get_type
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index a3e9eedc3a..2339a86543 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -148,6 +148,7 @@ gtk_public_h_sources = \
gtkaccessible.h \
gtkaction.h \
gtkactiongroup.h \
+ gtkactivatable.h \
gtkadjustment.h \
gtkalignment.h \
gtkarrow.h \
@@ -397,6 +398,7 @@ gtk_base_c_sources = \
gtkaccessible.c \
gtkaction.c \
gtkactiongroup.c \
+ gtkactivatable.c \
gtkadjustment.c \
gtkalignment.c \
gtkarrow.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 6bd28f41ad..7b9b765e08 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -37,6 +37,7 @@
#include <gtk/gtkaccessible.h>
#include <gtk/gtkaction.h>
#include <gtk/gtkactiongroup.h>
+#include <gtk/gtkactivatable.h>
#include <gtk/gtkadjustment.h>
#include <gtk/gtkalignment.h>
#include <gtk/gtkarrow.h>
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 777cb0aac7..2ca4a6a7d5 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -144,49 +144,61 @@ gtk_accessible_get_type G_GNUC_CONST
#if IN_HEADER(__GTK_ACTION_H__)
#if IN_FILE(__GTK_ACTION_C__)
gtk_action_activate
+gtk_action_block_activate
+#ifndef GTK_DISABLE_DEPRECATED
gtk_action_block_activate_from
+#endif
gtk_action_connect_accelerator
+#ifndef GTK_DISABLE_DEPRECATED
gtk_action_connect_proxy
+#endif
gtk_action_create_icon
gtk_action_create_menu_item
gtk_action_create_tool_item
gtk_action_create_menu
gtk_action_disconnect_accelerator
+#ifndef GTK_DISABLE_DEPRECATED
gtk_action_disconnect_proxy
+#endif
gtk_action_get_accel_closure
gtk_action_get_accel_path
+gtk_action_get_gicon
+gtk_action_get_label
gtk_action_get_name
gtk_action_get_proxies
+#ifndef GTK_DISABLE_DEPRECATED
gtk_widget_get_action
+#endif
+gtk_action_get_icon_name
+gtk_action_get_is_important
gtk_action_get_sensitive
+gtk_action_get_short_label
+gtk_action_get_stock_id
+gtk_action_get_tooltip
gtk_action_get_type G_GNUC_CONST
gtk_action_get_visible
+gtk_action_get_visible_horizontal
+gtk_action_get_visible_vertical
gtk_action_is_sensitive
gtk_action_is_visible
gtk_action_new
gtk_action_set_accel_group
gtk_action_set_accel_path
-gtk_action_set_sensitive
-gtk_action_set_visible
-gtk_action_unblock_activate_from
+gtk_action_set_gicon
+gtk_action_set_icon_name
+gtk_action_set_is_important
gtk_action_set_label
-gtk_action_get_label
+gtk_action_set_sensitive
gtk_action_set_short_label
-gtk_action_get_short_label
-gtk_action_set_tooltip
-gtk_action_get_tooltip
gtk_action_set_stock_id
-gtk_action_get_stock_id
-gtk_action_set_gicon
-gtk_action_get_gicon
-gtk_action_set_icon_name
-gtk_action_get_icon_name
+gtk_action_set_tooltip
+gtk_action_set_visible
gtk_action_set_visible_horizontal
-gtk_action_get_visible_horizontal
gtk_action_set_visible_vertical
-gtk_action_get_visible_vertical
-gtk_action_set_is_important
-gtk_action_get_is_important
+gtk_action_unblock_activate
+#ifndef GTK_DISABLE_DEPRECATED
+gtk_action_unblock_activate_from
+#endif
#endif
#endif
@@ -216,6 +228,18 @@ gtk_action_group_translate_string
#endif
#endif
+#if IN_HEADER(__GTK_ACTIVATABLE_H__)
+#if IN_FILE(__GTK_ACTIVATABLE_C__)
+gtk_activatable_do_set_related_action
+gtk_activatable_get_related_action
+gtk_activatable_get_type G_GNUC_CONST
+gtk_activatable_get_use_action_appearance
+gtk_activatable_reset
+gtk_activatable_set_related_action
+gtk_activatable_set_use_action_appearance
+#endif
+#endif
+
#if IN_HEADER(__GTK_ADJUSTMENT_H__)
#if IN_FILE(__GTK_ADJUSTMENT_C__)
gtk_adjustment_changed
diff --git a/gtk/gtkaction.c b/gtk/gtkaction.c
index 59c52d3552..6d29ca4e34 100644
--- a/gtk/gtkaction.c
+++ b/gtk/gtkaction.c
@@ -47,6 +47,7 @@
#include "gtktoolbar.h"
#include "gtkprivate.h"
#include "gtkbuildable.h"
+#include "gtkactivatable.h"
#include "gtkalias.h"
@@ -71,6 +72,8 @@ struct _GtkActionPrivate
guint is_important : 1;
guint hide_if_empty : 1;
guint visible_overflown : 1;
+ guint recursion_guard : 1;
+ guint activate_blocked : 1;
/* accelerator */
guint accel_count;
@@ -120,10 +123,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_action_buildable_init))
-
-static GQuark quark_gtk_action_proxy = 0;
-static const gchar gtk_action_proxy_key[] = "gtk-action";
-
static void gtk_action_finalize (GObject *object);
static void gtk_action_set_property (GObject *object,
guint prop_id,
@@ -135,8 +134,6 @@ static void gtk_action_get_property (GObject *object,
GParamSpec *pspec);
static void gtk_action_set_action_group (GtkAction *action,
GtkActionGroup *action_group);
-static void gtk_action_sync_tooltip (GtkAction *action,
- GtkWidget *proxy);
static GtkWidget *create_menu_item (GtkAction *action);
static GtkWidget *create_tool_item (GtkAction *action);
@@ -144,7 +141,7 @@ static void connect_proxy (GtkAction *action,
GtkWidget *proxy);
static void disconnect_proxy (GtkAction *action,
GtkWidget *proxy);
-
+
static void closure_accel_activate (GClosure *closure,
GValue *return_value,
guint n_param_values,
@@ -160,8 +157,6 @@ gtk_action_class_init (GtkActionClass *klass)
{
GObjectClass *gobject_class;
- quark_gtk_action_proxy = g_quark_from_static_string (gtk_action_proxy_key);
-
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gtk_action_finalize;
@@ -170,14 +165,13 @@ gtk_action_class_init (GtkActionClass *klass)
klass->activate = NULL;
- klass->create_menu_item = create_menu_item;
- klass->create_tool_item = create_tool_item;
- klass->create_menu = NULL;
- klass->connect_proxy = connect_proxy;
- klass->disconnect_proxy = disconnect_proxy;
-
- klass->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
+ klass->create_menu_item = create_menu_item;
+ klass->create_tool_item = create_tool_item;
+ klass->create_menu = NULL;
+ klass->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
klass->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
+ klass->connect_proxy = connect_proxy;
+ klass->disconnect_proxy = disconnect_proxy;
g_object_class_install_property (gobject_class,
PROP_NAME,
@@ -194,6 +188,9 @@ gtk_action_class_init (GtkActionClass *klass)
* The label used for menu items and buttons that activate
* this action. If the label is %NULL, GTK+ uses the stock
* label specified via the stock-id property.
+ *
+ * This is an appearance property and thus only applies if
+ * #GtkActivatable:use-action-appearance is %TRUE.
*/
g_object_class_install_property (gobject_class,
PROP_LABEL,
@@ -208,6 +205,9 @@ gtk_action_class_init (GtkActionClass *klass)
* GtkAction:short-label:
*
* A shorter label that may be used on toolbar buttons.
+ *
+ * This is an appearance property and thus only applies if
+ * #GtkActivatable:use-action-appearance is %TRUE.
*/
g_object_class_install_property (gobject_class,
PROP_SHORT_LABEL,
@@ -230,6 +230,9 @@ gtk_action_class_init (GtkActionClass *klass)
* GtkAction:stock-id:
*
* The stock icon displayed in widgets representing this action.
+ *
+ * This is an appearance property and thus only applies if
+ * #GtkActivatable:use-action-appearance is %TRUE.
*/
g_object_class_install_property (gobject_class,
PROP_STOCK_ID,
@@ -247,6 +250,9 @@ gtk_action_class_init (GtkActionClass *klass)
* Note that the stock icon is preferred, if the #GtkAction:stock-id
* property holds the id of an existing stock icon.
*
+ * This is an appearance property and thus only applies if
+ * #GtkActivatable:use-action-appearance is %TRUE.
+ *
* Since: 2.16
*/
g_object_class_install_property (gobject_class,
@@ -265,6 +271,9 @@ gtk_action_class_init (GtkActionClass *klass)
* property holds the id of an existing stock icon, and the #GIcon is
* preferred if the #GtkAction:gicon property is set.
*
+ * This is an appearance property and thus only applies if
+ * #GtkActivatable:use-action-appearance is %TRUE.
+ *
* Since: 2.10
*/
g_object_class_install_property (gobject_class,
@@ -381,6 +390,7 @@ gtk_action_init (GtkAction *action)
action->private_data->visible_overflown = TRUE;
action->private_data->is_important = FALSE;
action->private_data->hide_if_empty = TRUE;
+ action->private_data->activate_blocked = FALSE;
action->private_data->sensitive = TRUE;
action->private_data->visible = TRUE;
@@ -634,12 +644,30 @@ static void
remove_proxy (GtkAction *action,
GtkWidget *proxy)
{
- if (GTK_IS_MENU_ITEM (proxy))
- gtk_action_disconnect_accelerator (action);
-
action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
}
+static void
+connect_proxy (GtkAction *action,
+ GtkWidget *proxy)
+{
+ action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
+
+ if (action->private_data->action_group)
+ _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
+
+}
+
+static void
+disconnect_proxy (GtkAction *action,
+ GtkWidget *proxy)
+{
+ remove_proxy (action, proxy);
+
+ if (action->private_data->action_group)
+ _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
+}
+
/**
* _gtk_action_sync_menu_visible:
* @action: a #GtkAction, or %NULL to determine the action from @proxy
@@ -670,7 +698,7 @@ _gtk_action_sync_menu_visible (GtkAction *action,
g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
if (action == NULL)
- action = g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy);
+ action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
if (action)
{
@@ -685,257 +713,6 @@ _gtk_action_sync_menu_visible (GtkAction *action,
gtk_widget_hide (proxy);
}
-gboolean _gtk_menu_is_empty (GtkWidget *menu);
-
-static gboolean
-gtk_action_create_menu_proxy (GtkToolItem *tool_item,
- GtkAction *action)
-{
- GtkWidget *menu_item;
-
- if (action->private_data->visible_overflown)
- {
- menu_item = gtk_action_create_menu_item (action);
-
- g_object_ref_sink (menu_item);
-
- gtk_tool_item_set_proxy_menu_item (tool_item,
- "gtk-action-menu-item", menu_item);
- g_object_unref (menu_item);
- }
- else
- gtk_tool_item_set_proxy_menu_item (tool_item,
- "gtk-action-menu-item", NULL);
-
- return TRUE;
-}
-
-static void
-connect_proxy (GtkAction *action,
- GtkWidget *proxy)
-{
- g_object_ref (action);
- g_object_set_qdata_full (G_OBJECT (proxy), quark_gtk_action_proxy, action,
- g_object_unref);
-
- /* add this widget to the list of proxies */
- action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
- g_object_weak_ref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
-
- gtk_widget_set_sensitive (proxy, gtk_action_is_sensitive (action));
- if (gtk_action_is_visible (action))
- gtk_widget_show (proxy);
- else
- gtk_widget_hide (proxy);
- gtk_widget_set_no_show_all (proxy, TRUE);
-
- if (GTK_IS_MENU_ITEM (proxy))
- {
- GtkWidget *label;
- /* menu item specific synchronisers ... */
-
- if (action->private_data->accel_quark)
- {
- gtk_action_connect_accelerator (action);
- gtk_menu_item_set_accel_path (GTK_MENU_ITEM (proxy),
- g_quark_to_string (action->private_data->accel_quark));
- }
-
- label = GTK_BIN (proxy)->child;
-
- /* make sure label is a label */
- if (label && !GTK_IS_LABEL (label))
- {
- gtk_container_remove (GTK_CONTAINER (proxy), label);
- label = NULL;
- }
-
- if (!label)
- label = g_object_new (GTK_TYPE_ACCEL_LABEL,
- "use-underline", TRUE,
- "xalign", 0.0,
- "visible", TRUE,
- "parent", proxy,
- NULL);
-
- if (GTK_IS_ACCEL_LABEL (label) && action->private_data->accel_quark)
- g_object_set (label,
- "accel-closure", action->private_data->accel_closure,
- NULL);
-
- gtk_label_set_label (GTK_LABEL (label), action->private_data->label);
-
- if (GTK_IS_IMAGE_MENU_ITEM (proxy))
- {
- GtkWidget *image;
-
- image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
- if (image && !GTK_IS_IMAGE (image))
- {
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy), NULL);
- image = NULL;
- }
- if (!image)
- {
- image = gtk_image_new ();
- gtk_widget_show (image);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),
- image);
- }
-
- if (action->private_data->stock_id &&
- gtk_icon_factory_lookup_default (action->private_data->stock_id))
- gtk_image_set_from_stock (GTK_IMAGE (image),
- action->private_data->stock_id, GTK_ICON_SIZE_MENU);
- else if (action->private_data->gicon)
- gtk_image_set_from_gicon (GTK_IMAGE (image),
- action->private_data->gicon, GTK_ICON_SIZE_MENU);
- else if (action->private_data->icon_name)
- gtk_image_set_from_icon_name (GTK_IMAGE (image),
- action->private_data->icon_name, GTK_ICON_SIZE_MENU);
- else
- gtk_image_clear (GTK_IMAGE (image));
- }
-
- if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)) == NULL)
- g_signal_connect_object (proxy, "activate",
- G_CALLBACK (gtk_action_activate), action,
- G_CONNECT_SWAPPED);
-
- }
- else if (GTK_IS_TOOL_ITEM (proxy))
- {
- /* toolbar button specific synchronisers ... */
- if (GTK_IS_TOOL_BUTTON (proxy))
- {
- GtkWidget *image;
- GtkIconSize icon_size;
-
- g_object_set (proxy,
- "visible-horizontal", action->private_data->visible_horizontal,
- "visible-vertical", action->private_data->visible_vertical,
- "is-important", action->private_data->is_important,
- "label", action->private_data->short_label,
- "use-underline", TRUE,
- "stock-id", action->private_data->stock_id,
- "icon-name", action->private_data->icon_name,
- NULL);
-
- if (action->private_data->stock_id &&
- gtk_icon_factory_lookup_default (action->private_data->stock_id))
- {
- /* use the stock icon */
- gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), NULL);
- }
- else if (action->private_data->gicon)
- {
- icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (proxy));
- image = gtk_tool_button_get_icon_widget (GTK_TOOL_BUTTON (proxy));
- if (!image)
- {
- image = gtk_image_new ();
- gtk_widget_show (image);
- gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy),
- image);
- }
-
- gtk_image_set_from_gicon (GTK_IMAGE (image),
- action->private_data->gicon,
- icon_size);
- }
-
- g_signal_connect_object (proxy, "clicked",
- G_CALLBACK (gtk_action_activate), action,
- G_CONNECT_SWAPPED);
- }
- else
- {
- g_object_set (proxy,
- "visible-horizontal", action->private_data->visible_horizontal,
- "visible-vertical", action->private_data->visible_vertical,
- "is-important", action->private_data->is_important,
- NULL);
- }
-
- gtk_action_sync_tooltip (action, proxy);
-
- g_signal_connect_object (proxy, "create-menu-proxy",
- G_CALLBACK (gtk_action_create_menu_proxy),
- action, 0);
-
- gtk_tool_item_rebuild_menu (GTK_TOOL_ITEM (proxy));
- }
- else if (GTK_IS_BUTTON (proxy))
- {
- /* button specific synchronisers ... */
- if (gtk_button_get_use_stock (GTK_BUTTON (proxy)))
- {
- /* synchronise stock-id */
- g_object_set (proxy,
- "label", action->private_data->stock_id,
- NULL);
- }
- else
- {
- GtkWidget *image;
-
- image = gtk_button_get_image (GTK_BUTTON (proxy));
-
- if (GTK_IS_IMAGE (image) ||
- GTK_BIN (proxy)->child == NULL ||
- GTK_IS_LABEL (GTK_BIN (proxy)->child))
- {
- /* synchronise the label */
- g_object_set (proxy,
- "label", action->private_data->short_label,
- "use-underline", TRUE,
- NULL);
- }
-
- if (GTK_IS_IMAGE (image) &&
- (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
- gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
- gtk_image_set_from_gicon (GTK_IMAGE (image),
- action->private_data->gicon, GTK_ICON_SIZE_MENU);
- else if (GTK_IS_IMAGE (image) &&
- (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
- gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
- gtk_image_set_from_icon_name (GTK_IMAGE (image),
- action->private_data->icon_name, GTK_ICON_SIZE_MENU);
- }
- /* we leave the button alone if there is a custom child */
- g_signal_connect_object (proxy, "clicked",
- G_CALLBACK (gtk_action_activate), action,
- G_CONNECT_SWAPPED);
- }
-
- if (action->private_data->action_group)
- _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
-}
-
-static void
-disconnect_proxy (GtkAction *action,
- GtkWidget *proxy)
-{
- g_object_set_qdata (G_OBJECT (proxy), quark_gtk_action_proxy, NULL);
-
- g_object_weak_unref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
- remove_proxy (action, proxy);
-
- /* disconnect the activate handler */
- g_signal_handlers_disconnect_by_func (proxy,
- G_CALLBACK (gtk_action_activate),
- action);
-
- /* toolbar button specific synchronisers ... */
- g_signal_handlers_disconnect_by_func (proxy,
- G_CALLBACK (gtk_action_create_menu_proxy),
- action);
-
- if (action->private_data->action_group)
- _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
-}
-
void
_gtk_action_emit_activate (GtkAction *action)
{
@@ -973,11 +750,43 @@ gtk_action_activate (GtkAction *action)
{
g_return_if_fail (GTK_IS_ACTION (action));
- if (gtk_action_is_sensitive (action))
+ if (action->private_data->activate_blocked == FALSE &&
+ gtk_action_is_sensitive (action))
_gtk_action_emit_activate (action);
}
/**
+ * gtk_action_block_activate:
+ *
+ * Disable activation signals from the action
+ *
+ * This is needed when updating the state of your proxy
+ * #GtkActivatable widget could result in calling gtk_action_activate(),
+ * this is a convenience function to avoid recursing in those
+ * cases (updating toggle state for instance).
+ */
+void
+gtk_action_block_activate (GtkAction *action)
+{
+ g_return_if_fail (GTK_IS_ACTION (action));
+
+ action->private_data->activate_blocked = TRUE;
+}
+
+/**
+ * gtk_action_unblock_activate:
+ *
+ * Reenable activation signals from the action
+ */
+void
+gtk_action_unblock_activate (GtkAction *action)
+{
+ g_return_if_fail (GTK_IS_ACTION (action));
+
+ action->private_data->activate_blocked = FALSE;
+}
+
+/**
* gtk_action_create_icon:
* @action: the action object
* @icon_size: the size of the icon that should be created.
@@ -1024,7 +833,8 @@ gtk_action_create_menu_item (GtkAction *action)
menu_item = GTK_ACTION_GET_CLASS (action)->create_menu_item (action);
- GTK_ACTION_GET_CLASS (action)->connect_proxy (action, menu_item);
+ gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (menu_item), TRUE);
+ gtk_activatable_set_related_action (GTK_ACTIVATABLE (menu_item), action);
return menu_item;
}
@@ -1048,11 +858,32 @@ gtk_action_create_tool_item (GtkAction *action)
button = GTK_ACTION_GET_CLASS (action)->create_tool_item (action);
- GTK_ACTION_GET_CLASS (action)->connect_proxy (action, button);
+ gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (button), TRUE);
+ gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
return button;
}
+void
+_gtk_action_add_to_proxy_list (GtkAction *action,
+ GtkWidget *proxy)
+{
+ g_return_if_fail (GTK_IS_ACTION (action));
+ g_return_if_fail (GTK_IS_WIDGET (proxy));
+
+ GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
+}
+
+void
+_gtk_action_remove_from_proxy_list (GtkAction *action,
+ GtkWidget *proxy)
+{
+ g_return_if_fail (GTK_IS_ACTION (action));
+ g_return_if_fail (GTK_IS_WIDGET (proxy));
+
+ GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
+}
+
/**
* gtk_action_connect_proxy:
* @action: the action object
@@ -1067,22 +898,20 @@ gtk_action_create_tool_item (GtkAction *action)
* first.
*
* Since: 2.4
+ *
+ * Deprecated 2.16: Use gtk_activatable_set_related_action() instead.
*/
void
gtk_action_connect_proxy (GtkAction *action,
GtkWidget *proxy)
{
- GtkAction *prev_action;
-
g_return_if_fail (GTK_IS_ACTION (action));
g_return_if_fail (GTK_IS_WIDGET (proxy));
+ g_return_if_fail (GTK_IS_ACTIVATABLE (proxy));
- prev_action = g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy);
+ gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (proxy), TRUE);
- if (prev_action)
- GTK_ACTION_GET_CLASS (action)->disconnect_proxy (prev_action, proxy);
-
- GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
+ gtk_activatable_set_related_action (GTK_ACTIVATABLE (proxy), action);
}
/**
@@ -1094,6 +923,8 @@ gtk_action_connect_proxy (GtkAction *action,
* Does <emphasis>not</emphasis> destroy the widget, however.
*
* Since: 2.4
+ *
+ * Deprecated 2.16: Use gtk_activatable_set_related_action() instead.
*/
void
gtk_action_disconnect_proxy (GtkAction *action,
@@ -1102,9 +933,7 @@ gtk_action_disconnect_proxy (GtkAction *action,
g_return_if_fail (GTK_IS_ACTION (action));
g_return_if_fail (GTK_IS_WIDGET (proxy));
- g_return_if_fail (g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy) == action);
-
- GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
+ gtk_activatable_set_related_action (GTK_ACTIVATABLE (proxy), NULL);
}
/**
@@ -1139,15 +968,19 @@ gtk_action_get_proxies (GtkAction *action)
* %NULL, if it is not attached to an action.
*
* Since: 2.10
+ *
+ * Deprecated 2.16: Use gtk_activatable_get_related_action() instead.
*/
GtkAction*
gtk_widget_get_action (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
-
- return g_object_get_qdata (G_OBJECT (widget), quark_gtk_action_proxy);
-}
+ if (GTK_IS_ACTIVATABLE (widget))
+ return gtk_activatable_get_related_action (GTK_ACTIVATABLE (widget));
+
+ return NULL;
+}
/**
* gtk_action_get_name:
@@ -1211,22 +1044,6 @@ gtk_action_get_sensitive (GtkAction *action)
return action->private_data->sensitive;
}
-void
-_gtk_action_sync_sensitive (GtkAction *action)
-{
- GSList *p;
- GtkWidget *proxy;
- gboolean sensitive;
-
- sensitive = gtk_action_is_sensitive (action);
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
- gtk_widget_set_sensitive (proxy, sensitive);
- }
-}
-
/**
* gtk_action_set_sensitive:
* @action: the action object
@@ -1251,8 +1068,6 @@ gtk_action_set_sensitive (GtkAction *action,
{
action->private_data->sensitive = sensitive;
- _gtk_action_sync_sensitive (action);
-
g_object_notify (G_OBJECT (action), "sensitive");
}
}
@@ -1300,36 +1115,6 @@ gtk_action_get_visible (GtkAction *action)
return action->private_data->visible;
}
-void
-_gtk_action_sync_visible (GtkAction *action)
-{
- GSList *p;
- GtkWidget *proxy;
- GtkWidget *menu;
- gboolean visible;
-
- visible = gtk_action_is_visible (action);
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_MENU_ITEM (proxy))
- {
- menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
-
- _gtk_action_sync_menu_visible (action, proxy, _gtk_menu_is_empty (menu));
- }
- else
- {
- if (visible)
- gtk_widget_show (proxy);
- else
- gtk_widget_hide (proxy);
- }
- }
-}
-
/**
* gtk_action_set_visible:
* @action: the action object
@@ -1354,8 +1139,6 @@ gtk_action_set_visible (GtkAction *action,
{
action->private_data->visible = visible;
- _gtk_action_sync_visible (action);
-
g_object_notify (G_OBJECT (action), "visible");
}
}
@@ -1374,8 +1157,7 @@ void
gtk_action_set_is_important (GtkAction *action,
gboolean is_important)
{
- GSList *p;
- GtkWidget *proxy;
+ g_return_if_fail (GTK_IS_ACTION (action));
g_return_if_fail (GTK_IS_ACTION (action));
@@ -1384,15 +1166,6 @@ gtk_action_set_is_important (GtkAction *action,
if (action->private_data->is_important != is_important)
{
action->private_data->is_important = is_important;
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_TOOL_ITEM (proxy))
- gtk_tool_item_set_is_important (GTK_TOOL_ITEM (proxy),
- is_important);
- }
g_object_notify (G_OBJECT (action), "is-important");
}
@@ -1403,12 +1176,12 @@ gtk_action_set_is_important (GtkAction *action,
* @action: a #GtkAction
*
* Checks whether @action is important or not
- *
+ *
* Returns: whether @action is important
*
* Since: 2.16
*/
-gboolean
+gboolean
gtk_action_get_is_important (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
@@ -1429,8 +1202,6 @@ void
gtk_action_set_label (GtkAction *action,
const gchar *label)
{
- GSList *p;
- GtkWidget *proxy, *child;
gchar *tmp;
g_return_if_fail (GTK_IS_ACTION (action));
@@ -1447,21 +1218,7 @@ gtk_action_set_label (GtkAction *action,
if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
action->private_data->label = g_strdup (stock_item.label);
}
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_MENU_ITEM (proxy))
- {
- child = GTK_BIN (proxy)->child;
-
- if (GTK_IS_LABEL (child))
- gtk_label_set_label (GTK_LABEL (child),
- action->private_data->label);
- }
- }
-
+
g_object_notify (G_OBJECT (action), "label");
/* if short_label is unset, set short_label=label */
@@ -1482,7 +1239,7 @@ gtk_action_set_label (GtkAction *action,
*
* Since: 2.16
*/
-G_CONST_RETURN gchar *
+G_CONST_RETURN gchar *
gtk_action_get_label (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
@@ -1495,16 +1252,14 @@ gtk_action_get_label (GtkAction *action)
* @action: a #GtkAction
* @label: the label text to set
*
- * Sets a shorter label on @action.
+ * Sets a shorter label text on @action.
*
* Since: 2.16
*/
void
-gtk_action_set_short_label (GtkAction *action,
+gtk_action_set_short_label (GtkAction *action,
const gchar *label)
{
- GSList *p;
- GtkWidget *proxy, *child;
gchar *tmp;
g_return_if_fail (GTK_IS_ACTION (action));
@@ -1517,29 +1272,6 @@ gtk_action_set_short_label (GtkAction *action,
if (!action->private_data->short_label_set)
action->private_data->short_label = g_strdup (action->private_data->label);
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_TOOL_BUTTON (proxy))
- gtk_tool_button_set_label (GTK_TOOL_BUTTON (proxy),
- action->private_data->short_label);
- else if (GTK_IS_BUTTON (proxy) &&
- !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
- {
- GtkWidget *image;
-
- child = GTK_BIN (proxy)->child;
-
- image = gtk_button_get_image (GTK_BUTTON (proxy));
-
- if (GTK_IS_IMAGE (image) ||
- child == NULL || GTK_IS_LABEL (child))
- gtk_button_set_label (GTK_BUTTON (proxy),
- action->private_data->short_label);
- }
- }
-
g_object_notify (G_OBJECT (action), "short-label");
}
@@ -1548,16 +1280,17 @@ gtk_action_set_short_label (GtkAction *action,
* @action: a #GtkAction
* @label: the label text to set
*
- * Sets a shorter label on @action.
+ * Gets the short label text of @action.
+ *
+ * Returns: the short label text.
*
* Since: 2.16
*/
-G_CONST_RETURN gchar *
+G_CONST_RETURN gchar *
gtk_action_get_short_label (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
- g_object_notify (G_OBJECT (action), "short-label");
return action->private_data->short_label;
}
@@ -1574,8 +1307,7 @@ void
gtk_action_set_visible_horizontal (GtkAction *action,
gboolean visible_horizontal)
{
- GSList *p;
- GtkWidget *proxy;
+ g_return_if_fail (GTK_IS_ACTION (action));
g_return_if_fail (GTK_IS_ACTION (action));
@@ -1584,15 +1316,6 @@ gtk_action_set_visible_horizontal (GtkAction *action,
if (action->private_data->visible_horizontal != visible_horizontal)
{
action->private_data->visible_horizontal = visible_horizontal;
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_TOOL_ITEM (proxy))
- gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (proxy),
- visible_horizontal);
- }
g_object_notify (G_OBJECT (action), "visible-horizontal");
}
@@ -1603,12 +1326,12 @@ gtk_action_set_visible_horizontal (GtkAction *action,
* @action: a #GtkAction
*
* Checks whether @action is visible when horizontal
- *
+ *
* Returns: whether @action is visible when horizontal
*
* Since: 2.16
*/
-gboolean
+gboolean
gtk_action_get_visible_horizontal (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
@@ -1621,7 +1344,7 @@ gtk_action_get_visible_horizontal (GtkAction *action)
* @action: a #GtkAction
* @visible_vertical: whether the action is visible vertically
*
- * Sets whether @action is visible when vertical
+ * Sets whether @action is visible when vertical
*
* Since: 2.16
*/
@@ -1629,8 +1352,7 @@ void
gtk_action_set_visible_vertical (GtkAction *action,
gboolean visible_vertical)
{
- GSList *p;
- GtkWidget *proxy;
+ g_return_if_fail (GTK_IS_ACTION (action));
g_return_if_fail (GTK_IS_ACTION (action));
@@ -1639,15 +1361,6 @@ gtk_action_set_visible_vertical (GtkAction *action,
if (action->private_data->visible_vertical != visible_vertical)
{
action->private_data->visible_vertical = visible_vertical;
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_TOOL_ITEM (proxy))
- gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (proxy),
- visible_vertical);
- }
g_object_notify (G_OBJECT (action), "visible-vertical");
}
@@ -1658,12 +1371,12 @@ gtk_action_set_visible_vertical (GtkAction *action,
* @action: a #GtkAction
*
* Checks whether @action is visible when horizontal
- *
+ *
* Returns: whether @action is visible when horizontal
*
* Since: 2.16
*/
-gboolean
+gboolean
gtk_action_get_visible_vertical (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
@@ -1671,14 +1384,6 @@ gtk_action_get_visible_vertical (GtkAction *action)
return action->private_data->visible_vertical;
}
-static void
-gtk_action_sync_tooltip (GtkAction *action,
- GtkWidget *proxy)
-{
- gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (proxy),
- action->private_data->tooltip);
-}
-
/**
* gtk_action_set_tooltip:
* @action: a #GtkAction
@@ -1692,8 +1397,6 @@ void
gtk_action_set_tooltip (GtkAction *action,
const gchar *tooltip)
{
- GSList *p;
- GtkWidget *proxy;
gchar *tmp;
g_return_if_fail (GTK_IS_ACTION (action));
@@ -1702,14 +1405,6 @@ gtk_action_set_tooltip (GtkAction *action,
action->private_data->tooltip = g_strdup (tooltip);
g_free (tmp);
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_TOOL_ITEM (proxy))
- gtk_action_sync_tooltip (action, proxy);
- }
-
g_object_notify (G_OBJECT (action), "tooltip");
}
@@ -1719,11 +1414,11 @@ gtk_action_set_tooltip (GtkAction *action,
*
* Gets the tooltip text of @action.
*
-* Returns: the tooltip text
+ * Returns: the tooltip text
*
* Since: 2.16
*/
-G_CONST_RETURN gchar *
+G_CONST_RETURN gchar *
gtk_action_get_tooltip (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
@@ -1744,42 +1439,16 @@ void
gtk_action_set_stock_id (GtkAction *action,
const gchar *stock_id)
{
- GSList *p;
- GtkWidget *proxy, *image;
gchar *tmp;
-
+
+ g_return_if_fail (GTK_IS_ACTION (action));
+
g_return_if_fail (GTK_IS_ACTION (action));
tmp = action->private_data->stock_id;
action->private_data->stock_id = g_strdup (stock_id);
g_free (tmp);
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_IMAGE_MENU_ITEM (proxy))
- {
- image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
-
- if (GTK_IS_IMAGE (image))
- gtk_image_set_from_stock (GTK_IMAGE (image),
- action->private_data->stock_id, GTK_ICON_SIZE_MENU);
- }
- else if (GTK_IS_TOOL_BUTTON (proxy))
- {
- gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), NULL);
- gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (proxy),
- action->private_data->stock_id);
- }
- else if (GTK_IS_BUTTON (proxy) &&
- gtk_button_get_use_stock (GTK_BUTTON (proxy)))
- {
- gtk_button_set_label (GTK_BUTTON (proxy),
- action->private_data->stock_id);
- }
- }
-
g_object_notify (G_OBJECT (action), "stock-id");
/* update label and short_label if appropriate */
@@ -1807,7 +1476,7 @@ gtk_action_set_stock_id (GtkAction *action,
*
* Since: 2.16
*/
-G_CONST_RETURN gchar *
+G_CONST_RETURN gchar *
gtk_action_get_stock_id (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
@@ -1828,48 +1497,16 @@ void
gtk_action_set_icon_name (GtkAction *action,
const gchar *icon_name)
{
- GSList *p;
- GtkWidget *proxy, *image;
gchar *tmp;
-
+
+ g_return_if_fail (GTK_IS_ACTION (action));
+
g_return_if_fail (GTK_IS_ACTION (action));
tmp = action->private_data->icon_name;
action->private_data->icon_name = g_strdup (icon_name);
g_free (tmp);
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_IMAGE_MENU_ITEM (proxy))
- {
- image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
-
- if (GTK_IS_IMAGE (image) &&
- (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
- gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
- gtk_image_set_from_icon_name (GTK_IMAGE (image),
- action->private_data->icon_name, GTK_ICON_SIZE_MENU);
- }
- else if (GTK_IS_TOOL_BUTTON (proxy))
- {
- gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (proxy),
- action->private_data->icon_name);
- }
- else if (GTK_IS_BUTTON (proxy) &&
- !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
- {
- image = gtk_button_get_image (GTK_BUTTON (proxy));
-
- if (GTK_IS_IMAGE (image) &&
- (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
- gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
- gtk_image_set_from_icon_name (GTK_IMAGE (image),
- action->private_data->icon_name, GTK_ICON_SIZE_MENU);
- }
- }
-
g_object_notify (G_OBJECT (action), "icon-name");
}
@@ -1883,7 +1520,7 @@ gtk_action_set_icon_name (GtkAction *action,
*
* Since: 2.16
*/
-G_CONST_RETURN gchar *
+G_CONST_RETURN gchar *
gtk_action_get_icon_name (GtkAction *action)
{
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
@@ -1904,11 +1541,6 @@ void
gtk_action_set_gicon (GtkAction *action,
GIcon *icon)
{
- GSList *p;
- GtkWidget *proxy, *image;
- GtkIconSize icon_size;
- gboolean has_stock_icon;
-
g_return_if_fail (GTK_IS_ACTION (action));
if (action->private_data->gicon)
@@ -1919,48 +1551,6 @@ gtk_action_set_gicon (GtkAction *action,
if (action->private_data->gicon)
g_object_ref (action->private_data->gicon);
- if (action->private_data->stock_id &&
- gtk_icon_factory_lookup_default (action->private_data->stock_id))
- has_stock_icon = TRUE;
- else
- has_stock_icon = FALSE;
-
- for (p = action->private_data->proxies; p; p = p->next)
- {
- proxy = (GtkWidget *)p->data;
-
- if (GTK_IS_IMAGE_MENU_ITEM (proxy) && !has_stock_icon)
- {
- image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
- gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU);
- }
- else if (GTK_IS_TOOL_BUTTON (proxy))
- {
- if (has_stock_icon || !icon)
- image = NULL;
- else
- {
- image = gtk_tool_button_get_icon_widget (GTK_TOOL_BUTTON (proxy));
- icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (proxy));
-
- if (!image)
- image = gtk_image_new ();
- }
-
- gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), image);
- gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
- }
- else if (GTK_IS_BUTTON (proxy) &&
- !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
- {
- image = gtk_button_get_image (GTK_BUTTON (proxy));
- if (GTK_IS_IMAGE (image) &&
- (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
- gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
- gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_BUTTON);
- }
- }
-
g_object_notify (G_OBJECT (action), "gicon");
}
@@ -1994,6 +1584,9 @@ gtk_action_get_gicon (GtkAction *action)
* This function is intended for use by action implementations.
*
* Since: 2.4
+ *
+ * Deprecated 2.16: activatables are now responsible for activating the
+ * action directly so this doesnt apply anymore.
*/
void
gtk_action_block_activate_from (GtkAction *action,
@@ -2017,6 +1610,9 @@ gtk_action_block_activate_from (GtkAction *action,
* This function is intended for use by action implementations.
*
* Since: 2.4
+ *
+ * Deprecated 2.16: activatables are now responsible for activating the
+ * action directly so this doesnt apply anymore.
*/
void
gtk_action_unblock_activate_from (GtkAction *action,
diff --git a/gtk/gtkaction.h b/gtk/gtkaction.h
index ff20c7dd66..a3636b478a 100644
--- a/gtk/gtkaction.h
+++ b/gtk/gtkaction.h
@@ -105,22 +105,33 @@ GtkWidget * gtk_action_create_icon (GtkAction *action,
GtkWidget * gtk_action_create_menu_item (GtkAction *action);
GtkWidget * gtk_action_create_tool_item (GtkAction *action);
GtkWidget * gtk_action_create_menu (GtkAction *action);
-void gtk_action_connect_proxy (GtkAction *action,
- GtkWidget *proxy);
-void gtk_action_disconnect_proxy (GtkAction *action,
- GtkWidget *proxy);
GSList * gtk_action_get_proxies (GtkAction *action);
-GtkAction * gtk_widget_get_action (GtkWidget *widget);
void gtk_action_connect_accelerator (GtkAction *action);
void gtk_action_disconnect_accelerator (GtkAction *action);
G_CONST_RETURN gchar *gtk_action_get_accel_path (GtkAction *action);
GClosure *gtk_action_get_accel_closure (GtkAction *action);
-/* protected ... for use by child actions */
+#ifndef GTK_DISABLE_DEPRECATED
+GtkAction *gtk_widget_get_action (GtkWidget *widget);
+void gtk_action_connect_proxy (GtkAction *action,
+ GtkWidget *proxy);
+void gtk_action_disconnect_proxy (GtkAction *action,
+ GtkWidget *proxy);
void gtk_action_block_activate_from (GtkAction *action,
GtkWidget *proxy);
void gtk_action_unblock_activate_from (GtkAction *action,
GtkWidget *proxy);
+#endif /* GTK_DISABLE_DEPRECATED */
+void gtk_action_block_activate (GtkAction *action);
+void gtk_action_unblock_activate (GtkAction *action);
+
+
+void _gtk_action_add_to_proxy_list (GtkAction *action,
+ GtkWidget *proxy);
+void _gtk_action_remove_from_proxy_list(GtkAction *action,
+ GtkWidget *proxy);
+
+/* protected ... for use by child actions */
void _gtk_action_emit_activate (GtkAction *action);
/* protected ... for use by action groups */
@@ -128,8 +139,6 @@ void gtk_action_set_accel_path (GtkAction *action,
const gchar *accel_path);
void gtk_action_set_accel_group (GtkAction *action,
GtkAccelGroup *accel_group);
-void _gtk_action_sync_sensitive (GtkAction *action);
-void _gtk_action_sync_visible (GtkAction *action);
void _gtk_action_sync_menu_visible (GtkAction *action,
GtkWidget *proxy,
gboolean empty);
diff --git a/gtk/gtkactiongroup.c b/gtk/gtkactiongroup.c
index a4c5feb624..2794c58008 100644
--- a/gtk/gtkactiongroup.c
+++ b/gtk/gtkactiongroup.c
@@ -626,8 +626,8 @@ cb_set_action_sensitivity (const gchar *name,
{
/* Minor optimization, the action_groups state only affects actions
* that are themselves sensitive */
- if (gtk_action_get_sensitive (action))
- _gtk_action_sync_sensitive (action);
+ g_object_notify (G_OBJECT (action), "sensitive");
+
}
/**
@@ -691,8 +691,7 @@ cb_set_action_visiblity (const gchar *name,
{
/* Minor optimization, the action_groups state only affects actions
* that are themselves visible */
- if (gtk_action_get_visible (action))
- _gtk_action_sync_visible (action);
+ g_object_notify (G_OBJECT (action), "visible");
}
/**
diff --git a/gtk/gtkactivatable.c b/gtk/gtkactivatable.c
new file mode 100644
index 0000000000..5f7252d2b5
--- /dev/null
+++ b/gtk/gtkactivatable.c
@@ -0,0 +1,540 @@
+/* gtkactivatable.c
+ * Copyright (C) 2008 Tristan Van Berkom <tristan.van.berkom@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+/**
+ * SECTION:gtk-activatable
+ * @Short_Description: An interface for activatable widgets.
+ *
+ * Activatable widgets can be connected to a #GtkAction and reflects
+ * the state of its action - a #GtkActivatable can also provide feedback
+ * through its action, as they are responsible for activating their
+ * related actions.
+ *
+ * <refsect2>
+ * <title>Implementing GtkActivatable</title>
+ * <para>
+ * When extending a class that is already #GtkActivatable; it is only
+ * necessary to implement the #GtkActivatable->reset() and #GtkActivatable->update()
+ * methods and chain up to the parent implementation, however when introducing
+ * a new #GtkActivatable class; the #GtkActivatable:related-action and
+ * #GtkActivatable:use-action-appearance properties need to be handled by
+ * the implementor. Handling these properties is mostly a matter of installing
+ * the action pointer and boolean flag on your instance, and calling
+ * gtk_activatable_do_set_related_action() and gtk_activatable_reset() at the
+ * appropriate times.
+ * </para>
+ * <example>
+ * <title>A class fragment implementing #GtkActivatable</title>
+ * <programlisting><![CDATA[
+ *
+ * enum {
+ * ...
+ *
+ * PROP_ACTIVATABLE_RELATED_ACTION,
+ * PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
+ * }
+ *
+ * struct _FooBarPrivate
+ * {
+ *
+ * ...
+ *
+ * GtkAction *action;
+ * gboolean use_action_appearance;
+ * };
+ *
+ * ...
+ *
+ * static void foo_bar_activatable_interface_init (GtkActivatableIface *iface);
+ * static void foo_bar_activatable_update (GtkActivatable *activatable,
+ * GtkAction *action,
+ * const gchar *property_name);
+ * static void foo_bar_activatable_reset (GtkActivatable *activatable,
+ * GtkAction *action);
+ * ...
+ *
+ *
+ * static void
+ * foo_bar_class_init (FooBarClass *klass)
+ * {
+ *
+ * ...
+ *
+ * g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ * g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+ *
+ * ...
+ * }
+ *
+ *
+ * static void
+ * foo_bar_activatable_interface_init (GtkActivatableIface *iface)
+ * {
+ * iface->update = foo_bar_activatable_update;
+ * iface->reset = foo_bar_activatable_reset;
+ * }
+ *
+ * ... Break the reference using gtk_activatable_do_set_related_action()...
+ *
+ * static void
+ * foo_bar_dispose (GObject *object)
+ * {
+ * FooBar *bar = FOO_BAR (object);
+ * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
+ *
+ * ...
+ *
+ * if (priv->action)
+ * {
+ * gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (bar), NULL);
+ * priv->action = NULL;
+ * }
+ * G_OBJECT_CLASS (foo_bar_parent_class)->dispose (object);
+ * }
+ *
+ * ... Handle the "related-action" and "use-action-appearance" properties ...
+ *
+ * static void
+ * foo_bar_set_property (GObject *object,
+ * guint prop_id,
+ * const GValue *value,
+ * GParamSpec *pspec)
+ * {
+ * FooBar *bar = FOO_BAR (object);
+ * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
+ *
+ * switch (prop_id)
+ * {
+ *
+ * ...
+ *
+ * case PROP_ACTIVATABLE_RELATED_ACTION:
+ * foo_bar_set_related_action (bar, g_value_get_object (value));
+ * break;
+ * case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ * foo_bar_set_use_action_appearance (bar, g_value_get_boolean (value));
+ * break;
+ * default:
+ * G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ * break;
+ * }
+ * }
+ *
+ * static void
+ * foo_bar_get_property (GObject *object,
+ * guint prop_id,
+ * GValue *value,
+ * GParamSpec *pspec)
+ * {
+ * FooBar *bar = FOO_BAR (object);
+ * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
+ *
+ * switch (prop_id)
+ * {
+ *
+ * ...
+ *
+ * case PROP_ACTIVATABLE_RELATED_ACTION:
+ * g_value_set_object (value, priv->action);
+ * break;
+ * case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ * g_value_set_boolean (value, priv->use_action_appearance);
+ * break;
+ * default:
+ * G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ * break;
+ * }
+ * }
+ *
+ *
+ * static void
+ * foo_bar_set_use_action_appearance (FooBar *bar,
+ * gboolean use_appearance)
+ * {
+ * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
+ *
+ * if (priv->use_action_appearance != use_appearance)
+ * {
+ * priv->use_action_appearance = use_appearance;
+ *
+ * gtk_activatable_reset (GTK_ACTIVATABLE (bar), priv->action);
+ * }
+ * }
+ *
+ * ... call gtk_activatable_do_set_related_action() and then assign the action pointer,
+ * no need to reference the action here since gtk_activatable_do_set_related_action() already
+ * holds a reference here for you...
+ * static void
+ * foo_bar_set_related_action (FooBar *bar,
+ * GtkAction *action)
+ * {
+ * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (bar);
+ *
+ * if (priv->action == action)
+ * return;
+ *
+ * gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (bar), action);
+ *
+ * priv->action = action;
+ * }
+ *
+ * ... Selectively reset and update activatable depending on the use-action-appearance property ...
+ * static void
+ * gtk_button_activatable_reset (GtkActivatable *activatable,
+ * GtkAction *action)
+ * {
+ * GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (activatable);
+ *
+ * if (!action)
+ * return;
+ *
+ * if (gtk_action_is_visible (action))
+ * gtk_widget_show (GTK_WIDGET (activatable));
+ * else
+ * gtk_widget_hide (GTK_WIDGET (activatable));
+ *
+ * gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+ *
+ * ...
+ *
+ * if (priv->use_action_appearance)
+ * {
+ * if (gtk_action_get_stock_id (action))
+ * foo_bar_set_stock (button, gtk_action_get_stock_id (action));
+ * else if (gtk_action_get_label (action))
+ * foo_bar_set_label (button, gtk_action_get_label (action));
+ *
+ * ...
+ *
+ * }
+ * }
+ *
+ * static void
+ * foo_bar_activatable_update (GtkActivatable *activatable,
+ * GtkAction *action,
+ * const gchar *property_name)
+ * {
+ * FooBarPrivate *priv = FOO_BAR_GET_PRIVATE (activatable);
+ *
+ * if (strcmp (property_name, "visible") == 0)
+ * {
+ * if (gtk_action_is_visible (action))
+ * gtk_widget_show (GTK_WIDGET (activatable));
+ * else
+ * gtk_widget_hide (GTK_WIDGET (activatable));
+ * }
+ * else if (strcmp (property_name, "sensitive") == 0)
+ * gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+ *
+ * ...
+ *
+ * if (!priv->use_action_appearance)
+ * return;
+ *
+ * if (strcmp (property_name, "stock-id") == 0)
+ * foo_bar_set_stock (button, gtk_action_get_stock_id (action));
+ * else if (strcmp (property_name, "label") == 0)
+ * foo_bar_set_label (button, gtk_action_get_label (action));
+ *
+ * ...
+ * }]]></programlisting>
+ * </example>
+ *
+ */
+
+#include "config.h"
+#include "gtkactivatable.h"
+#include "gtkactiongroup.h"
+#include "gtktypeutils.h"
+#include "gtkprivate.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+
+static void gtk_activatable_class_init (gpointer g_iface);
+
+GType
+gtk_activatable_get_type (void)
+{
+ static GType activatable_type = 0;
+
+ if (!activatable_type)
+ activatable_type =
+ g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkActivatable"),
+ sizeof (GtkActivatableIface),
+ (GClassInitFunc) gtk_activatable_class_init,
+ 0, NULL, 0);
+
+ return activatable_type;
+}
+
+static void
+gtk_activatable_class_init (gpointer g_iface)
+{
+ /**
+ * GtkActivatable:related-action:
+ *
+ * The action that this activatable will activate and receive
+ * updates from for various states and possibly appearance.
+ *
+ * <note><para>#GtkActivatable implementors need to handle the this property and
+ * call gtk_activatable_do_set_related_action() when it changes.</para></note>
+ *
+ * Since: 2.16
+ */
+ g_object_interface_install_property (g_iface,
+ g_param_spec_object ("related-action",
+ P_("Related Action"),
+ P_("The action this activatable will activate and receive updates from"),
+ GTK_TYPE_ACTION,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkActivatable:use-action-appearance:
+ *
+ * Whether this activatable should reset its layout
+ * and appearance when setting the related action or when
+ * the action changes appearance.
+ *
+ * See the #GtkAction documentation directly to find which properties
+ * should be ignored by the #GtkActivatable when this property is %FALSE.
+ *
+ * <note><para>#GtkActivatable implementors need to handle this property
+ * and call gtk_activatable_reset() on the activatable widget when it changes.</para></note>
+ *
+ * Since: 2.16
+ */
+ g_object_interface_install_property (g_iface,
+ g_param_spec_boolean ("use-action-appearance",
+ P_("Use Action Appearance"),
+ P_("Whether to use the related actions appearance properties"),
+ TRUE,
+ GTK_PARAM_READWRITE));
+
+
+}
+
+static void
+gtk_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkActivatableIface *iface;
+
+ g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
+
+ iface = GTK_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->update)
+ iface->update (activatable, action, property_name);
+ else
+ g_critical ("GtkActivatable->update() unimplemented for type %s",
+ g_type_name (G_OBJECT_TYPE (activatable)));
+}
+
+/**
+ * gtk_activatable_reset:
+ * @activatable: a #GtkActivatable
+ * @action: the related #GtkAction or %NULL
+ *
+ * This is called to update the activatable completely, this is called internally when
+ * the #GtkActivatable::related-action property is set or unset and by the implementing
+ * class when #GtkActivatable::use-action-appearance changes.
+ *
+ * Since: 2.16
+ **/
+void
+gtk_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkActivatableIface *iface;
+
+ g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
+
+ iface = GTK_ACTIVATABLE_GET_IFACE (activatable);
+ if (iface->reset)
+ iface->reset (activatable, action);
+ else
+ g_critical ("GtkActivatable->reset() unimplemented for type %s",
+ g_type_name (G_OBJECT_TYPE (activatable)));
+}
+
+
+/**
+ * gtk_activatable_set_related_action:
+ * @activatable: a #GtkActivatable
+ * @action: the #GtkAction to set
+ *
+ * Sets the related action on the @activatable object.
+ *
+ * <note><para>#GtkActivatable implementors need to handle the #GtkActivatable:related-action
+ * property and call gtk_activatable_do_set_related_action() when it changes.</para></note>
+ *
+ * Since: 2.16
+ **/
+void
+gtk_activatable_set_related_action (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
+ g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
+
+ g_object_set (activatable, "related-action", action, NULL);
+}
+
+static void
+gtk_activatable_action_notify (GtkAction *action,
+ GParamSpec *pspec,
+ GtkActivatable *activatable)
+{
+ gtk_activatable_update (activatable, action, pspec->name);
+}
+
+/**
+ * gtk_activatable_do_set_related_action:
+ * @activatable: a #GtkActivatable
+ * @action: the #GtkAction to set
+ *
+ * This is a utility function for #GtkActivatable implementors.
+ *
+ * When implementing #GtkActivatable you must call this when
+ * handling changes of the #GtkActivatable:related-action, and
+ * you must also use this to break references in #GObject->dispose().
+ *
+ * This function adds a reference to the currently set related
+ * action for you, it also makes sure the #GtkActivatable->update()
+ * method is called when the related #GtkAction properties change
+ * and registers to the action's proxy list.
+ *
+ * <note><para>Be careful to call this before setting the local
+ * copy of the #GtkAction property, since this function uses
+ * gtk_activatable_get_action() to retrieve the previous action</para></note>
+ */
+void
+gtk_activatable_do_set_related_action (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkAction *prev_action;
+
+ prev_action = gtk_activatable_get_related_action (activatable);
+
+ if (prev_action != action)
+ {
+ if (prev_action)
+ {
+ g_signal_handlers_disconnect_by_func (prev_action, gtk_activatable_action_notify, activatable);
+
+ _gtk_action_remove_from_proxy_list (prev_action, GTK_WIDGET (activatable));
+
+ g_object_unref (prev_action);
+
+ /* Some apps are using the object data directly...
+ * so continue to set it for a bit longer
+ */
+ g_object_set_data (activatable, "gtk-action", NULL);
+ }
+
+ /* Some applications rely on their proxy UI to be set up
+ * before they receive the ::connect-proxy signal, so we
+ * need to call reset() before add_to_proxy_list().
+ */
+ gtk_activatable_reset (activatable, action);
+
+ if (action)
+ {
+ g_object_ref (action);
+
+ g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_activatable_action_notify), activatable);
+
+ _gtk_action_add_to_proxy_list (action, GTK_WIDGET (activatable));
+
+ g_object_set_data (activatable, "gtk-action", action);
+ }
+ }
+}
+
+/**
+ * gtk_activatable_get_related_action:
+ * @activatable: a #GtkActivatable
+ *
+ * Gets the related #GtkAction for @activatable.
+ *
+ * Returns: the related #GtkAction if one is set.
+ *
+ * Since: 2.16
+ **/
+GtkAction *
+gtk_activatable_get_related_action (GtkActivatable *activatable)
+{
+ GtkAction *action;
+
+ g_return_val_if_fail (GTK_IS_ACTIVATABLE (activatable), NULL);
+
+ g_object_get (activatable, "related-action", &action, NULL);
+
+ /* g_object_get() gives us a ref... */
+ if (action)
+ g_object_unref (action);
+
+ return action;
+}
+
+/**
+ * gtk_activatable_set_use_action_appearance:
+ * @activatable: a #GtkActivatable
+ * @use_appearance: whether to use the actions appearance
+ *
+ * Sets whether this activatable should reset its layout and appearance
+ * when setting the related action or when the action changes appearance
+ *
+ * <note><para>#GtkActivatable implementors need to handle the #GtkActivatable:use-action-appearance
+ * property and call gtk_activatable_reset() to update @activatable if needed.</para></note>
+ *
+ * Since: 2.16
+ **/
+void
+gtk_activatable_set_use_action_appearance (GtkActivatable *activatable,
+ gboolean use_appearance)
+{
+ g_object_set (activatable, "use-action-appearance", use_appearance, NULL);
+}
+
+/**
+ * gtk_activatable_get_use_action_appearance:
+ * @activatable: a #GtkActivatable
+ *
+ * Gets whether this activatable should reset its layout
+ * and appearance when setting the related action or when
+ * the action changes appearance.
+ *
+ * Returns: whether @activatable uses its actions appearance.
+ *
+ * Since: 2.16
+ **/
+gboolean
+gtk_activatable_get_use_action_appearance (GtkActivatable *activatable)
+{
+ gboolean use_appearance;
+
+ g_object_get (activatable, "use-action-appearance", &use_appearance, NULL);
+
+ return use_appearance;
+}
+
+#define __GTK_ACTIVATABLE_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkactivatable.h b/gtk/gtkactivatable.h
new file mode 100644
index 0000000000..75478899ed
--- /dev/null
+++ b/gtk/gtkactivatable.h
@@ -0,0 +1,88 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2008 Tristan Van Berkom <tristan.van.berkom@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_ACTIVATABLE_H__
+#define __GTK_ACTIVATABLE_H__
+
+#include <gtk/gtkaction.h>
+#include <gtk/gtktypeutils.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_ACTIVATABLE (gtk_activatable_get_type ())
+#define GTK_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatable))
+#define GTK_ACTIVATABLE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatableIface))
+#define GTK_IS_ACTIVATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ACTIVATABLE))
+#define GTK_ACTIVATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatableIface))
+
+
+typedef struct _GtkActivatable GtkActivatable; /* Dummy typedef */
+typedef struct _GtkActivatableIface GtkActivatableIface;
+
+
+/**
+ * GtkActivatableIface:
+ * @update: Called to update the activatable when its related action's properties change.
+ * You must check the #GtkActivatable:use-action-appearance property only apply action
+ * properties that are meant to effect the appearance accordingly.
+ * @reset: Called to update the activatable completely, this is called internally when
+ * #GtkActivatable::related-action property is set or unset and by the implementor when
+ * #GtkActivatable::use-action-appearance changes.<note><para>This method can be called
+ * with a %NULL action at times</para></note>
+ *
+ * Since: 2.16
+ */
+
+struct _GtkActivatableIface
+{
+ GTypeInterface g_iface;
+
+ /* virtual table */
+ void (* update) (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+ void (* reset) (GtkActivatable *activatable,
+ GtkAction *action);
+};
+
+
+GType gtk_activatable_get_type (void) G_GNUC_CONST;
+
+void gtk_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+
+void gtk_activatable_set_related_action (GtkActivatable *activatable,
+ GtkAction *action);
+GtkAction *gtk_activatable_get_related_action (GtkActivatable *activatable);
+
+void gtk_activatable_set_use_action_appearance (GtkActivatable *activatable,
+ gboolean use_appearance);
+gboolean gtk_activatable_get_use_action_appearance (GtkActivatable *activatable);
+
+/* For use in activatable implementations */
+void gtk_activatable_do_set_related_action (GtkActivatable *activatable,
+ GtkAction *action);
+
+G_END_DECLS
+
+#endif /* __GTK_ACTIVATABLE_H__ */
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
index 234f0367ec..d882ca130b 100644
--- a/gtk/gtkbutton.c
+++ b/gtk/gtkbutton.c
@@ -36,6 +36,7 @@
#include "gtkvbox.h"
#include "gtkstock.h"
#include "gtkiconfactory.h"
+#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
@@ -69,7 +70,11 @@ enum {
PROP_FOCUS_ON_CLICK,
PROP_XALIGN,
PROP_YALIGN,
- PROP_IMAGE_POSITION
+ PROP_IMAGE_POSITION,
+
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
};
#define GTK_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_BUTTON, GtkButtonPrivate))
@@ -80,14 +85,17 @@ struct _GtkButtonPrivate
gfloat xalign;
gfloat yalign;
GtkWidget *image;
- guint align_set : 1;
- guint image_is_stock : 1;
- guint has_grab : 1;
+ guint align_set : 1;
+ guint image_is_stock : 1;
+ guint has_grab : 1;
+ guint use_action_appearance : 1;
guint32 grab_time;
GtkPositionType image_position;
+ GtkAction *action;
};
static void gtk_button_destroy (GtkObject *object);
+static void gtk_button_dispose (GObject *object);
static void gtk_button_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -124,6 +132,7 @@ static gint gtk_button_leave_notify (GtkWidget *widget,
GdkEventCrossing *event);
static void gtk_real_button_pressed (GtkButton *button);
static void gtk_real_button_released (GtkButton *button);
+static void gtk_real_button_clicked (GtkButton *button);
static void gtk_real_button_activate (GtkButton *button);
static void gtk_button_update_state (GtkButton *button);
static void gtk_button_add (GtkContainer *container,
@@ -142,9 +151,22 @@ static void gtk_button_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
+static void gtk_button_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+static void gtk_button_set_related_action (GtkButton *button,
+ GtkAction *action);
+static void gtk_button_set_use_action_appearance (GtkButton *button,
+ gboolean use_appearance);
+
static guint button_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkButton, gtk_button, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_button_activatable_interface_init))
static void
gtk_button_class_init (GtkButtonClass *klass)
@@ -159,7 +181,8 @@ gtk_button_class_init (GtkButtonClass *klass)
widget_class = (GtkWidgetClass*) klass;
container_class = (GtkContainerClass*) klass;
- gobject_class->constructor = gtk_button_constructor;
+ gobject_class->constructor = gtk_button_constructor;
+ gobject_class->dispose = gtk_button_dispose;
gobject_class->set_property = gtk_button_set_property;
gobject_class->get_property = gtk_button_get_property;
@@ -188,7 +211,7 @@ gtk_button_class_init (GtkButtonClass *klass)
klass->pressed = gtk_real_button_pressed;
klass->released = gtk_real_button_released;
- klass->clicked = NULL;
+ klass->clicked = gtk_real_button_clicked;
klass->enter = gtk_button_update_state;
klass->leave = gtk_button_update_state;
klass->activate = gtk_real_button_activate;
@@ -303,6 +326,9 @@ gtk_button_class_init (GtkButtonClass *klass)
GTK_POS_LEFT,
GTK_PARAM_READWRITE));
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+
/**
* GtkButton::pressed:
* @button: the object that received the signal
@@ -521,6 +547,7 @@ gtk_button_init (GtkButton *button)
priv->align_set = 0;
priv->image_is_stock = TRUE;
priv->image_position = GTK_POS_LEFT;
+ priv->use_action_appearance = TRUE;
}
static void
@@ -600,6 +627,20 @@ gtk_button_add (GtkContainer *container,
GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, widget);
}
+static void
+gtk_button_dispose (GObject *object)
+{
+ GtkButton *button = GTK_BUTTON (object);
+ GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+ if (priv->action)
+ {
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), NULL);
+ priv->action = NULL;
+ }
+ G_OBJECT_CLASS (gtk_button_parent_class)->dispose (object);
+}
+
static void
gtk_button_set_property (GObject *object,
guint prop_id,
@@ -638,6 +679,12 @@ gtk_button_set_property (GObject *object,
case PROP_IMAGE_POSITION:
gtk_button_set_image_position (button, g_value_get_enum (value));
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ gtk_button_set_related_action (button, g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ gtk_button_set_use_action_appearance (button, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -682,12 +729,170 @@ gtk_button_get_property (GObject *object,
case PROP_IMAGE_POSITION:
g_value_set_enum (value, priv->image_position);
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, priv->action);
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, priv->use_action_appearance);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+static void
+gtk_button_activatable_interface_init (GtkActivatableIface *iface)
+{
+ iface->update = gtk_button_activatable_update;
+ iface->reset = gtk_button_activatable_reset;
+}
+
+static void
+activatable_update_stock_id (GtkButton *button,
+ GtkAction *action)
+{
+ if (!gtk_button_get_use_stock (button))
+ return;
+
+ gtk_button_set_label (button, gtk_action_get_stock_id (action));
+}
+
+static void
+activatable_update_short_label (GtkButton *button,
+ GtkAction *action)
+{
+ GtkWidget *image;
+
+ if (gtk_button_get_use_stock (button))
+ return;
+
+ image = gtk_button_get_image (button);
+
+ /* Dont touch custom child... */
+ if (GTK_IS_IMAGE (image) ||
+ GTK_BIN (button)->child == NULL ||
+ GTK_IS_LABEL (GTK_BIN (button)->child))
+ {
+ gtk_button_set_label (button, gtk_action_get_short_label (action));
+ gtk_button_set_use_underline (button, TRUE);
+ }
+}
+
+static void
+activatable_update_icon_name (GtkButton *button,
+ GtkAction *action)
+{
+ GtkWidget *image;
+
+ if (gtk_button_get_use_stock (button))
+ return;
+
+ image = gtk_button_get_image (button);
+
+ if (GTK_IS_IMAGE (image) &&
+ (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+ gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
+ gtk_image_set_from_icon_name (GTK_IMAGE (image),
+ gtk_action_get_icon_name (action), GTK_ICON_SIZE_MENU);
+}
+
+static void
+activatable_update_gicon (GtkButton *button,
+ GtkAction *action)
+{
+ GtkWidget *image = gtk_button_get_image (button);
+ GIcon *icon = gtk_action_get_gicon (action);
+
+ if (GTK_IS_IMAGE (image) &&
+ (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+ gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
+ gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_BUTTON);
+}
+
+static void
+gtk_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (activatable);
+
+ if (strcmp (property_name, "visible") == 0)
+ {
+ if (gtk_action_is_visible (action))
+ gtk_widget_show (GTK_WIDGET (activatable));
+ else
+ gtk_widget_hide (GTK_WIDGET (activatable));
+ }
+ else if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ if (!priv->use_action_appearance)
+ return;
+
+ if (strcmp (property_name, "stock-id") == 0)
+ activatable_update_stock_id (GTK_BUTTON (activatable), action);
+ else if (strcmp (property_name, "gicon") == 0)
+ activatable_update_gicon (GTK_BUTTON (activatable), action);
+ else if (strcmp (property_name, "short-label") == 0)
+ activatable_update_short_label (GTK_BUTTON (activatable), action);
+ else if (strcmp (property_name, "icon-name") == 0)
+ activatable_update_icon_name (GTK_BUTTON (activatable), action);
+}
+
+static void
+gtk_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (activatable);
+
+ if (!action)
+ return;
+
+ if (gtk_action_is_visible (action))
+ gtk_widget_show (GTK_WIDGET (activatable));
+ else
+ gtk_widget_hide (GTK_WIDGET (activatable));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ if (priv->use_action_appearance)
+ {
+ activatable_update_stock_id (GTK_BUTTON (activatable), action);
+ activatable_update_short_label (GTK_BUTTON (activatable), action);
+ activatable_update_gicon (GTK_BUTTON (activatable), action);
+ activatable_update_icon_name (GTK_BUTTON (activatable), action);
+ }
+}
+
+static void
+gtk_button_set_related_action (GtkButton *button,
+ GtkAction *action)
+{
+ GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+ if (priv->action == action)
+ return;
+
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), action);
+
+ priv->action = action;
+}
+
+static void
+gtk_button_set_use_action_appearance (GtkButton *button,
+ gboolean use_appearance)
+{
+ GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+ if (priv->use_action_appearance != use_appearance)
+ {
+ priv->use_action_appearance = use_appearance;
+
+ gtk_activatable_reset (GTK_ACTIVATABLE (button), priv->action);
+ }
+}
+
GtkWidget*
gtk_button_new (void)
{
@@ -1494,6 +1699,15 @@ gtk_real_button_released (GtkButton *button)
}
}
+static void
+gtk_real_button_clicked (GtkButton *button)
+{
+ GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+ if (priv->action)
+ gtk_action_activate (priv->action);
+}
+
static gboolean
button_activate_timeout (gpointer data)
{
diff --git a/gtk/gtkcheckmenuitem.c b/gtk/gtkcheckmenuitem.c
index a179ab24e0..e65370b0f1 100644
--- a/gtk/gtkcheckmenuitem.c
+++ b/gtk/gtkcheckmenuitem.c
@@ -27,6 +27,8 @@
#include "config.h"
#include "gtkcheckmenuitem.h"
#include "gtkaccellabel.h"
+#include "gtkactivatable.h"
+#include "gtktoggleaction.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
#include "gtkintl.h"
@@ -53,19 +55,28 @@ static void gtk_check_menu_item_draw_indicator (GtkCheckMenuItem *che
GdkRectangle *area);
static void gtk_real_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
GdkRectangle *area);
-static void gtk_check_menu_item_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_check_menu_item_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-
-static guint check_menu_item_signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (GtkCheckMenuItem, gtk_check_menu_item, GTK_TYPE_MENU_ITEM)
+static void gtk_check_menu_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_check_menu_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void gtk_check_menu_item_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_check_menu_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_check_menu_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+
+static GtkActivatableIface *parent_activatable_iface;
+static guint check_menu_item_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_CODE (GtkCheckMenuItem, gtk_check_menu_item, GTK_TYPE_MENU_ITEM,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_check_menu_item_activatable_interface_init))
static void
gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
@@ -107,8 +118,7 @@ gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("indicator-size",
- P_("Indicator Size")
-,
+ P_("Indicator Size"),
P_("Size of check or radio indicator"),
0,
G_MAXINT,
@@ -134,6 +144,64 @@ gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
G_TYPE_NONE, 0);
}
+static void
+gtk_check_menu_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+ parent_activatable_iface = g_type_interface_peek_parent (iface);
+ iface->update = gtk_check_menu_item_activatable_update;
+ iface->reset = gtk_check_menu_item_activatable_reset;
+}
+
+static void
+gtk_check_menu_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkCheckMenuItem *check_menu_item;
+
+ check_menu_item = GTK_CHECK_MENU_ITEM (activatable);
+
+ parent_activatable_iface->update (activatable, action, property_name);
+
+ if (strcmp (property_name, "active") == 0)
+ {
+ gtk_action_block_activate (action);
+ gtk_check_menu_item_set_active (check_menu_item, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ gtk_action_unblock_activate (action);
+ }
+
+ if (!gtk_activatable_get_use_action_appearance (activatable))
+ return;
+
+ if (strcmp (property_name, "draw-as-radio") == 0)
+ gtk_check_menu_item_set_draw_as_radio (check_menu_item,
+ gtk_toggle_action_get_draw_as_radio (GTK_TOGGLE_ACTION (action)));
+}
+
+static void
+gtk_check_menu_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkCheckMenuItem *check_menu_item;
+
+ check_menu_item = GTK_CHECK_MENU_ITEM (activatable);
+
+ parent_activatable_iface->reset (activatable, action);
+
+ if (!action)
+ return;
+
+ gtk_action_block_activate (action);
+ gtk_check_menu_item_set_active (check_menu_item, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ gtk_action_unblock_activate (action);
+
+ if (!gtk_activatable_get_use_action_appearance (activatable))
+ return;
+
+ gtk_check_menu_item_set_draw_as_radio (check_menu_item,
+ gtk_toggle_action_get_draw_as_radio (GTK_TOGGLE_ACTION (action)));
+}
+
GtkWidget*
gtk_check_menu_item_new (void)
{
@@ -351,6 +419,8 @@ gtk_check_menu_item_activate (GtkMenuItem *menu_item)
gtk_check_menu_item_toggled (check_menu_item);
gtk_widget_queue_draw (GTK_WIDGET (check_menu_item));
+ GTK_MENU_ITEM_CLASS (gtk_check_menu_item_parent_class)->activate (menu_item);
+
g_object_notify (G_OBJECT (check_menu_item), "active");
}
diff --git a/gtk/gtkimagemenuitem.c b/gtk/gtkimagemenuitem.c
index c4a1c8facb..27b641f60d 100644
--- a/gtk/gtkimagemenuitem.c
+++ b/gtk/gtkimagemenuitem.c
@@ -34,6 +34,7 @@
#include "gtkmenubar.h"
#include "gtkcontainer.h"
#include "gtkwindow.h"
+#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkalias.h"
@@ -70,6 +71,12 @@ static void gtk_image_menu_item_screen_changed (GtkWidget *widget,
static void gtk_image_menu_item_recalculate (GtkImageMenuItem *image_menu_item);
+static void gtk_image_menu_item_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_image_menu_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_image_menu_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
typedef struct {
gchar *label;
@@ -83,7 +90,12 @@ enum {
PROP_ACCEL_GROUP
};
-G_DEFINE_TYPE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM)
+static GtkActivatableIface *parent_activatable_iface;
+
+
+G_DEFINE_TYPE_WITH_CODE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_image_menu_item_activatable_interface_init))
#define GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_IMAGE_MENU_ITEM, GtkImageMenuItemPrivate))
@@ -504,6 +516,134 @@ gtk_image_menu_item_forall (GtkContainer *container,
(* callback) (image_menu_item->image, callback_data);
}
+
+static void
+gtk_image_menu_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+ parent_activatable_iface = g_type_interface_peek_parent (iface);
+ iface->update = gtk_image_menu_item_activatable_update;
+ iface->reset = gtk_image_menu_item_activatable_reset;
+}
+
+static gboolean
+activatable_update_stock_id (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+ GtkWidget *image;
+ const gchar *stock_id = gtk_action_get_stock_id (action);
+
+ image = gtk_image_menu_item_get_image (image_menu_item);
+
+ if (GTK_IS_IMAGE (image) &&
+ stock_id && gtk_icon_factory_lookup_default (stock_id))
+ {
+ gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+activatable_update_gicon (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+ GtkWidget *image;
+ GIcon *icon = gtk_action_get_gicon (action);
+ const gchar *stock_id = gtk_action_get_stock_id (action);
+
+ image = gtk_image_menu_item_get_image (image_menu_item);
+
+ if (icon && GTK_IS_IMAGE (image) &&
+ !(stock_id && gtk_icon_factory_lookup_default (stock_id)))
+ {
+ gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+activatable_update_icon_name (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+ GtkWidget *image;
+ const gchar *icon_name = gtk_action_get_icon_name (action);
+
+ image = gtk_image_menu_item_get_image (image_menu_item);
+
+ if (GTK_IS_IMAGE (image) && icon_name &&
+ (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+ gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
+ {
+ gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
+ }
+}
+
+static void
+gtk_image_menu_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkImageMenuItem *image_menu_item;
+ GtkWidget *image;
+ gboolean use_appearance;
+
+ image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
+
+ parent_activatable_iface->update (activatable, action, property_name);
+
+ use_appearance = gtk_activatable_get_use_action_appearance (activatable);
+ if (!use_appearance)
+ return;
+
+ if (strcmp (property_name, "stock-id") == 0)
+ activatable_update_stock_id (image_menu_item, action);
+ else if (strcmp (property_name, "gicon") == 0)
+ activatable_update_gicon (image_menu_item, action);
+ else if (strcmp (property_name, "icon-name") == 0)
+ activatable_update_icon_name (image_menu_item, action);
+}
+
+static void
+gtk_image_menu_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkImageMenuItem *image_menu_item;
+ GtkWidget *image;
+ gboolean use_appearance;
+
+ image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
+
+ parent_activatable_iface->reset (activatable, action);
+
+ if (!action)
+ return;
+
+ use_appearance = gtk_activatable_get_use_action_appearance (activatable);
+ if (!use_appearance)
+ return;
+
+ image = gtk_image_menu_item_get_image (image_menu_item);
+ if (image && !GTK_IS_IMAGE (image))
+ {
+ gtk_image_menu_item_set_image (image_menu_item, NULL);
+ image = NULL;
+ }
+
+ if (!image)
+ {
+ image = gtk_image_new ();
+ gtk_widget_show (image);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable),
+ image);
+ }
+
+ if (!activatable_update_stock_id (image_menu_item, action) &&
+ !activatable_update_gicon (image_menu_item, action))
+ activatable_update_icon_name (image_menu_item, action);
+
+}
+
+
/**
* gtk_image_menu_item_new:
* @returns: a new #GtkImageMenuItem.
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index 9d8b33523f..03eca0bf59 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -37,9 +37,16 @@
#include "gtkseparatormenuitem.h"
#include "gtkprivate.h"
#include "gtkbuildable.h"
+#include "gtkactivatable.h"
#include "gtkintl.h"
#include "gtkalias.h"
+
+typedef struct {
+ GtkAction *action;
+ gboolean use_action_appearance;
+} GtkMenuItemPrivate;
+
enum {
ACTIVATE,
ACTIVATE_ITEM,
@@ -54,10 +61,15 @@ enum {
PROP_SUBMENU,
PROP_ACCEL_PATH,
PROP_LABEL,
- PROP_USE_UNDERLINE
+ PROP_USE_UNDERLINE,
+
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
};
+static void gtk_menu_item_dispose (GObject *object);
static void gtk_menu_item_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -85,6 +97,7 @@ static void gtk_menu_item_parent_set (GtkWidget *widget,
static void gtk_real_menu_item_select (GtkItem *item);
static void gtk_real_menu_item_deselect (GtkItem *item);
+static void gtk_real_menu_item_activate (GtkMenuItem *item);
static void gtk_real_menu_item_activate_item (GtkMenuItem *item);
static void gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
gint *requisition);
@@ -120,13 +133,30 @@ static void gtk_menu_item_buildable_add_child (GtkBuildable *buildab
GObject *child,
const gchar *type);
+static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_menu_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_menu_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+static void gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
+ GtkAction *action);
+static void gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
+ gboolean use_appearance);
+
+
static guint menu_item_signals[LAST_SIGNAL] = { 0 };
static GtkBuildableIface *parent_buildable_iface;
G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
- gtk_menu_item_buildable_interface_init))
+ gtk_menu_item_buildable_interface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_menu_item_activatable_interface_init))
+
+#define GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
static void
gtk_menu_item_class_init (GtkMenuItemClass *klass)
@@ -137,6 +167,7 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
+ gobject_class->dispose = gtk_menu_item_dispose;
gobject_class->set_property = gtk_menu_item_set_property;
gobject_class->get_property = gtk_menu_item_get_property;
@@ -157,15 +188,15 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
container_class->forall = gtk_menu_item_forall;
- item_class->select = gtk_real_menu_item_select;
- item_class->deselect = gtk_real_menu_item_deselect;
+ item_class->select = gtk_real_menu_item_select;
+ item_class->deselect = gtk_real_menu_item_deselect;
- klass->activate = NULL;
- klass->activate_item = gtk_real_menu_item_activate_item;
- klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
+ klass->activate = gtk_real_menu_item_activate;
+ klass->activate_item = gtk_real_menu_item_activate_item;
+ klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
- klass->set_label = gtk_real_menu_item_set_label;
- klass->get_label = gtk_real_menu_item_get_label;
+ klass->set_label = gtk_real_menu_item_set_label;
+ klass->get_label = gtk_real_menu_item_get_label;
klass->hide_on_activate = TRUE;
@@ -288,6 +319,9 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
FALSE,
GTK_PARAM_READWRITE));
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+
gtk_widget_class_install_style_property_parser (widget_class,
g_param_spec_enum ("selected-shadow-type",
"Selected Shadow Type",
@@ -344,12 +378,19 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
P_("The minimum desired width of the menu item in characters"),
0, G_MAXINT, 12,
GTK_PARAM_READABLE));
+
+ g_type_class_add_private (object_class, sizeof (GtkMenuItemPrivate));
}
static void
gtk_menu_item_init (GtkMenuItem *menu_item)
{
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
GTK_WIDGET_SET_FLAGS (menu_item, GTK_NO_WINDOW);
+
+ priv->action = NULL;
+ priv->use_action_appearance = TRUE;
menu_item->submenu = NULL;
menu_item->toggle_size = 0;
@@ -399,6 +440,22 @@ gtk_menu_item_new_with_mnemonic (const gchar *label)
NULL);
}
+static void
+gtk_menu_item_dispose (GObject *object)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (priv->action)
+ {
+ gtk_action_disconnect_accelerator (priv->action);
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
+
+ priv->action = NULL;
+ }
+ G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
+}
+
static void
gtk_menu_item_set_property (GObject *object,
guint prop_id,
@@ -424,7 +481,12 @@ gtk_menu_item_set_property (GObject *object,
case PROP_USE_UNDERLINE:
gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
break;
-
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -438,6 +500,7 @@ gtk_menu_item_get_property (GObject *object,
GParamSpec *pspec)
{
GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
switch (prop_id)
{
@@ -456,7 +519,12 @@ gtk_menu_item_get_property (GObject *object,
case PROP_USE_UNDERLINE:
g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
break;
-
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, priv->action);
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, priv->use_action_appearance);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -505,6 +573,138 @@ gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
parent_buildable_iface->add_child (buildable, builder, child, type);
}
+static void
+gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+ iface->update = gtk_menu_item_activatable_update;
+ iface->reset = gtk_menu_item_activatable_reset;
+}
+
+static void
+activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
+{
+ GtkWidget *child = GTK_BIN (menu_item)->child;
+
+ if (GTK_IS_LABEL (child))
+ {
+ const gchar *label;
+
+ label = gtk_action_get_label (action);
+ gtk_label_set_label (GTK_LABEL (child), label ? label : "");
+ }
+}
+
+gboolean _gtk_menu_is_empty (GtkWidget *menu);
+
+static void
+gtk_menu_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (strcmp (property_name, "visible") == 0)
+ _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
+ _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
+ else if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
+ else if (priv->use_action_appearance)
+ {
+ if (strcmp (property_name, "label") == 0)
+ activatable_update_label (menu_item, action);
+ }
+}
+
+static void
+gtk_menu_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (!action)
+ return;
+
+ _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
+ _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
+
+ if (priv->use_action_appearance)
+ {
+ GtkWidget *label = GTK_BIN (menu_item)->child;
+
+ /* make sure label is a label */
+ if (label && !GTK_IS_LABEL (label))
+ {
+ gtk_container_remove (GTK_CONTAINER (menu_item), label);
+ label = NULL;
+ }
+
+ if (!label)
+ label = g_object_new (GTK_TYPE_ACCEL_LABEL,
+ "use-underline", TRUE,
+ "xalign", 0.0,
+ "visible", TRUE,
+ "parent", menu_item,
+ NULL);
+
+ if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
+ g_object_set (label,
+ "accel-closure", gtk_action_get_accel_closure (action),
+ NULL);
+
+ activatable_update_label (menu_item, action);
+ }
+}
+
+static void
+gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
+ GtkAction *action)
+{
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (priv->action == action)
+ return;
+
+ if (priv->action)
+ {
+ gtk_action_disconnect_accelerator (priv->action);
+ }
+
+ if (action)
+ {
+ const gchar *accel_path;
+
+ accel_path = gtk_action_get_accel_path (action);
+ if (accel_path)
+ {
+ gtk_action_connect_accelerator (action);
+ gtk_menu_item_set_accel_path (menu_item, accel_path);
+ }
+ }
+
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
+
+ priv->action = action;
+}
+
+static void
+gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
+ gboolean use_appearance)
+{
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (priv->use_action_appearance != use_appearance)
+ {
+ priv->use_action_appearance = use_appearance;
+
+ gtk_activatable_reset (GTK_ACTIVATABLE (menu_item), priv->action);
+ }
+}
+
+
/**
* gtk_menu_item_set_submenu:
* @menu_item: a #GtkMenuItem
@@ -629,7 +829,7 @@ void
gtk_menu_item_activate (GtkMenuItem *menu_item)
{
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-
+
g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
}
@@ -1142,13 +1342,27 @@ gtk_menu_item_mnemonic_activate (GtkWidget *widget,
return TRUE;
}
+static void
+gtk_real_menu_item_activate (GtkMenuItem *menu_item)
+{
+ GtkMenuItemPrivate *priv;
+
+ priv = GET_PRIVATE (menu_item);
+
+ if (priv->action)
+ gtk_action_activate (priv->action);
+}
+
+
static void
gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
{
+ GtkMenuItemPrivate *priv;
GtkWidget *widget;
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+ priv = GET_PRIVATE (menu_item);
widget = GTK_WIDGET (menu_item);
if (widget->parent &&
diff --git a/gtk/gtkradioaction.c b/gtk/gtkradioaction.c
index 2b113e17cd..1be634d7f8 100644
--- a/gtk/gtkradioaction.c
+++ b/gtk/gtkradioaction.c
@@ -324,6 +324,8 @@ gtk_radio_action_activate (GtkAction *action)
if (tmp_action->private_data->active && (tmp_action != toggle_action))
{
toggle_action->private_data->active = !toggle_action->private_data->active;
+
+ g_object_notify (G_OBJECT (action), "active");
break;
}
}
@@ -331,6 +333,7 @@ gtk_radio_action_activate (GtkAction *action)
else
{
toggle_action->private_data->active = !toggle_action->private_data->active;
+ g_object_notify (G_OBJECT (action), "active");
tmp_list = radio_action->private_data->group;
while (tmp_list)
diff --git a/gtk/gtkradiomenuitem.c b/gtk/gtkradiomenuitem.c
index 0b33dc6c93..f17b5ed2b7 100644
--- a/gtk/gtkradiomenuitem.c
+++ b/gtk/gtkradiomenuitem.c
@@ -28,6 +28,7 @@
#include "gtkaccellabel.h"
#include "gtkmarshalers.h"
#include "gtkradiomenuitem.h"
+#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
@@ -420,9 +421,14 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item);
GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
GtkCheckMenuItem *tmp_menu_item;
+ GtkAction *action;
GSList *tmp_list;
gint toggled;
+ action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (menu_item));
+ if (action && gtk_menu_item_get_submenu (menu_item) == NULL)
+ gtk_action_activate (action);
+
toggled = FALSE;
if (check_menu_item->active)
@@ -467,7 +473,9 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
}
if (toggled)
- gtk_check_menu_item_toggled (check_menu_item);
+ {
+ gtk_check_menu_item_toggled (check_menu_item);
+ }
gtk_widget_queue_draw (GTK_WIDGET (radio_menu_item));
}
diff --git a/gtk/gtkrecentaction.c b/gtk/gtkrecentaction.c
index 449eaad3c7..bf5c6d081e 100644
--- a/gtk/gtkrecentaction.c
+++ b/gtk/gtkrecentaction.c
@@ -42,7 +42,6 @@
struct _GtkRecentActionPrivate
{
GtkRecentManager *manager;
- guint manager_changed_id;
guint show_numbers : 1;
@@ -57,8 +56,8 @@ struct _GtkRecentActionPrivate
GtkRecentSortType sort_type;
GtkRecentSortFunc sort_func;
- gpointer sort_data;
- GDestroyNotify data_destroy;
+ gpointer sort_data;
+ GDestroyNotify data_destroy;
GtkRecentFilter *current_filter;
@@ -213,7 +212,7 @@ gtk_recent_action_set_sort_func (GtkRecentChooser *chooser,
for (l = priv->choosers; l; l = l->next)
{
GtkRecentChooser *chooser_menu = l->data;
-
+
gtk_recent_chooser_set_sort_func (chooser_menu, priv->sort_func,
priv->sort_data,
priv->data_destroy);
@@ -225,7 +224,6 @@ set_current_filter (GtkRecentAction *action,
GtkRecentFilter *filter)
{
GtkRecentActionPrivate *priv = action->priv;
- GSList *l;
g_object_ref (action);
@@ -237,13 +235,6 @@ set_current_filter (GtkRecentAction *action,
if (priv->current_filter)
g_object_ref_sink (priv->current_filter);
- for (l = priv->choosers; l; l = l->next)
- {
- GtkRecentChooser *chooser = l->data;
-
- gtk_recent_chooser_set_filter (chooser, priv->current_filter);
- }
-
g_object_notify (G_OBJECT (action), "filter");
g_object_unref (action);
@@ -338,21 +329,10 @@ gtk_recent_action_connect_proxy (GtkAction *action,
GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
GtkRecentActionPrivate *priv = recent_action->priv;
+ /* it can only be a recent chooser implementor anyway... */
if (GTK_IS_RECENT_CHOOSER (widget) &&
!g_slist_find (priv->choosers, widget))
{
- g_object_set (G_OBJECT (widget),
- "show-private", priv->show_private,
- "show-not-found", priv->show_not_found,
- "show-tips", priv->show_tips,
- "show-icons", priv->show_icons,
- "show-numbers", priv->show_numbers,
- "limit", priv->limit,
- "sort-type", priv->sort_type,
- "filter", priv->current_filter,
- "local-only", priv->local_only,
- NULL);
-
if (priv->sort_func)
{
gtk_recent_chooser_set_sort_func (GTK_RECENT_CHOOSER (widget),
@@ -369,7 +349,8 @@ gtk_recent_action_connect_proxy (GtkAction *action,
action);
}
- GTK_ACTION_CLASS (gtk_recent_action_parent_class)->connect_proxy (action, widget);
+ if (GTK_ACTION_CLASS (gtk_recent_action_parent_class)->connect_proxy)
+ GTK_ACTION_CLASS (gtk_recent_action_parent_class)->connect_proxy (action, widget);
}
static void
@@ -385,7 +366,8 @@ gtk_recent_action_disconnect_proxy (GtkAction *action,
if (g_slist_find (priv->choosers, widget))
priv->choosers = g_slist_remove (priv->choosers, widget);
- GTK_ACTION_CLASS (gtk_recent_action_parent_class)->disconnect_proxy (action, widget);
+ if (GTK_ACTION_CLASS (gtk_recent_action_parent_class)->disconnect_proxy)
+ GTK_ACTION_CLASS (gtk_recent_action_parent_class)->disconnect_proxy (action, widget);
}
static GtkWidget *
@@ -458,38 +440,15 @@ gtk_recent_action_create_tool_item (GtkAction *action)
}
static void
-manager_changed_cb (GtkRecentManager *manager,
- gpointer user_data)
-{
- /* do we need to propagate the signal to all the proxies? guess not */
-}
-
-static void
set_recent_manager (GtkRecentAction *action,
GtkRecentManager *manager)
{
GtkRecentActionPrivate *priv = action->priv;
- if (priv->manager)
- {
- if (priv->manager_changed_id)
- {
- g_signal_handler_disconnect (priv->manager, priv->manager_changed_id);
- priv->manager_changed_id = 0;
- }
-
- priv->manager = NULL;
- }
-
if (manager)
priv->manager = NULL;
else
priv->manager = gtk_recent_manager_get_default ();
-
- if (priv->manager)
- priv->manager_changed_id = g_signal_connect (priv->manager, "changed",
- G_CALLBACK (manager_changed_cb),
- action);
}
static void
@@ -520,14 +479,6 @@ gtk_recent_action_dispose (GObject *gobject)
GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
GtkRecentActionPrivate *priv = action->priv;
- if (priv->manager_changed_id)
- {
- if (priv->manager)
- g_signal_handler_disconnect (priv->manager, priv->manager_changed_id);
-
- priv->manager_changed_id = 0;
- }
-
if (priv->current_filter)
{
g_object_unref (priv->current_filter);
@@ -545,7 +496,6 @@ gtk_recent_action_set_property (GObject *gobject,
{
GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
GtkRecentActionPrivate *priv = action->priv;
- GSList *l;
switch (prop_id)
{
@@ -574,33 +524,20 @@ gtk_recent_action_set_property (GObject *gobject,
priv->sort_type = g_value_get_enum (value);
break;
case GTK_RECENT_CHOOSER_PROP_FILTER:
- /* this already iterates over the choosers list */
set_current_filter (action, g_value_get_object (value));
- return;
+ break;
case GTK_RECENT_CHOOSER_PROP_SELECT_MULTIPLE:
g_warning ("%s: Choosers of type `%s' do not support selecting multiple items.",
G_STRFUNC,
G_OBJECT_TYPE_NAME (gobject));
return;
case GTK_RECENT_CHOOSER_PROP_RECENT_MANAGER:
- /* this is a construct-only property; we set the recent-manager
- * of the choosers with this value when we create them, so there's
- * no need to iterate later.
- */
set_recent_manager (action, g_value_get_object (value));
- return;
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
return;
}
-
- /* propagate the properties to the proxies we have created */
- for (l = priv->choosers; l != NULL; l = l->next)
- {
- GObject *proxy = l->data;
-
- g_object_set_property (proxy, pspec->name, value);
- }
}
static void
@@ -707,7 +644,6 @@ gtk_recent_action_init (GtkRecentAction *action)
priv->current_filter = NULL;
priv->manager = NULL;
- priv->manager_changed_id = 0;
}
/**
diff --git a/gtk/gtkrecentchooser.c b/gtk/gtkrecentchooser.c
index 31157b98d7..298a125300 100644
--- a/gtk/gtkrecentchooser.c
+++ b/gtk/gtkrecentchooser.c
@@ -24,6 +24,8 @@
#include "gtkrecentchooser.h"
#include "gtkrecentchooserprivate.h"
#include "gtkrecentmanager.h"
+#include "gtkrecentaction.h"
+#include "gtkactivatable.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
@@ -39,7 +41,14 @@ enum
LAST_SIGNAL
};
-static void gtk_recent_chooser_class_init (gpointer g_iface);
+static void gtk_recent_chooser_class_init (gpointer g_iface);
+static gboolean recent_chooser_has_show_numbers (GtkRecentChooser *chooser);
+
+static GQuark quark_gtk_related_action = 0;
+static GQuark quark_gtk_use_action_appearance = 0;
+static const gchar gtk_related_action_key[] = "gtk-related-action";
+static const gchar gtk_use_action_appearance_key[] = "gtk-use-action-appearance";
+
static guint chooser_signals[LAST_SIGNAL] = { 0, };
@@ -66,6 +75,9 @@ static void
gtk_recent_chooser_class_init (gpointer g_iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+
+ quark_gtk_related_action = g_quark_from_static_string (gtk_related_action_key);
+ quark_gtk_use_action_appearance = g_quark_from_static_string (gtk_use_action_appearance_key);
/**
* GtkRecentChooser::selection-changed
@@ -575,6 +587,25 @@ gtk_recent_chooser_get_show_tips (GtkRecentChooser *chooser)
return show_tips;
}
+static gboolean
+recent_chooser_has_show_numbers (GtkRecentChooser *chooser)
+{
+ GParamSpec *pspec;
+
+ /* This is the result of a minor screw up: the "show-numbers" property
+ * was removed from the GtkRecentChooser interface, but the accessors
+ * remained in the interface API; now we need to check whether the
+ * implementation of the RecentChooser interface has a "show-numbers"
+ * boolean property installed before accessing it, and avoid an
+ * assertion failure using a more graceful warning. This should really
+ * go away as soon as we can break API and remove these accessors.
+ */
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (chooser),
+ "show-numbers");
+
+ return (pspec && pspec->value_type == G_TYPE_BOOLEAN);
+}
+
/**
* gtk_recent_chooser_set_show_numbers:
* @chooser: a #GtkRecentChooser
@@ -590,25 +621,13 @@ void
gtk_recent_chooser_set_show_numbers (GtkRecentChooser *chooser,
gboolean show_numbers)
{
- GParamSpec *pspec;
-
g_return_if_fail (GTK_IS_RECENT_CHOOSER (chooser));
- /* This is the result of a minor screw up: the "show-numbers" property
- * was removed from the GtkRecentChooser interface, but the accessors
- * remained in the interface API; now we need to check whether the
- * implementation of the RecentChooser interface has a "show-numbers"
- * boolean property installed before accessing it, and avoid an
- * assertion failure using a more graceful warning. This should really
- * go away as soon as we can break API and remove these accessors.
- */
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (chooser),
- "show-numbers");
- if (!pspec || pspec->value_type != G_TYPE_BOOLEAN)
+ if (!recent_chooser_has_show_numbers (chooser))
{
g_warning ("Choosers of type `%s' do not support showing numbers",
G_OBJECT_TYPE_NAME (chooser));
-
+
return;
}
@@ -1074,5 +1093,107 @@ _gtk_recent_chooser_selection_changed (GtkRecentChooser *chooser)
g_signal_emit (chooser, chooser_signals[SELECTION_CHANGED], 0);
}
+void
+_gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkRecentChooser *recent_chooser = GTK_RECENT_CHOOSER (activatable);
+ GtkRecentChooser *action_chooser = GTK_RECENT_CHOOSER (action);
+ GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
+
+ if (strcmp (property_name, "show-numbers") == 0 && recent_chooser_has_show_numbers (recent_chooser))
+ gtk_recent_chooser_set_show_numbers (recent_chooser,
+ gtk_recent_action_get_show_numbers (recent_action));
+ else if (strcmp (property_name, "show-private") == 0)
+ gtk_recent_chooser_set_show_private (recent_chooser, gtk_recent_chooser_get_show_private (action_chooser));
+ else if (strcmp (property_name, "show-not-found") == 0)
+ gtk_recent_chooser_set_show_not_found (recent_chooser, gtk_recent_chooser_get_show_not_found (action_chooser));
+ else if (strcmp (property_name, "show-tips") == 0)
+ gtk_recent_chooser_set_show_tips (recent_chooser, gtk_recent_chooser_get_show_tips (action_chooser));
+ else if (strcmp (property_name, "show-icons") == 0)
+ gtk_recent_chooser_set_show_icons (recent_chooser, gtk_recent_chooser_get_show_icons (action_chooser));
+ else if (strcmp (property_name, "limit") == 0)
+ gtk_recent_chooser_set_limit (recent_chooser, gtk_recent_chooser_get_limit (action_chooser));
+ else if (strcmp (property_name, "local-only") == 0)
+ gtk_recent_chooser_set_local_only (recent_chooser, gtk_recent_chooser_get_local_only (action_chooser));
+ else if (strcmp (property_name, "sort-type") == 0)
+ gtk_recent_chooser_set_sort_type (recent_chooser, gtk_recent_chooser_get_sort_type (action_chooser));
+ else if (strcmp (property_name, "filter") == 0)
+ gtk_recent_chooser_set_filter (recent_chooser, gtk_recent_chooser_get_filter (action_chooser));
+}
+
+void
+_gtk_recent_chooser_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkRecentChooser *recent_chooser = GTK_RECENT_CHOOSER (activatable);
+ GtkRecentChooser *action_chooser = GTK_RECENT_CHOOSER (action);
+
+ if (!action)
+ return;
+
+ if (recent_chooser_has_show_numbers (recent_chooser))
+ gtk_recent_chooser_set_show_numbers (recent_chooser,
+ gtk_recent_action_get_show_numbers (GTK_RECENT_ACTION (action)));
+ gtk_recent_chooser_set_show_private (recent_chooser, gtk_recent_chooser_get_show_private (action_chooser));
+ gtk_recent_chooser_set_show_not_found (recent_chooser, gtk_recent_chooser_get_show_not_found (action_chooser));
+ gtk_recent_chooser_set_show_tips (recent_chooser, gtk_recent_chooser_get_show_tips (action_chooser));
+ gtk_recent_chooser_set_show_icons (recent_chooser, gtk_recent_chooser_get_show_icons (action_chooser));
+ gtk_recent_chooser_set_limit (recent_chooser, gtk_recent_chooser_get_limit (action_chooser));
+ gtk_recent_chooser_set_local_only (recent_chooser, gtk_recent_chooser_get_local_only (action_chooser));
+ gtk_recent_chooser_set_sort_type (recent_chooser, gtk_recent_chooser_get_sort_type (action_chooser));
+ gtk_recent_chooser_set_filter (recent_chooser, gtk_recent_chooser_get_filter (action_chooser));
+}
+
+void
+_gtk_recent_chooser_set_related_action (GtkRecentChooser *recent_chooser,
+ GtkAction *action)
+{
+ GtkAction *prev_action;
+
+ prev_action = g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action);
+
+ if (prev_action == action)
+ return;
+
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (recent_chooser), action);
+ g_object_set_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action, action);
+}
+
+GtkAction *
+_gtk_recent_chooser_get_related_action (GtkRecentChooser *recent_chooser)
+{
+ return g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action);
+}
+
+/* The default for use-action-appearance is TRUE, so we try to set the
+ * qdata backwards for this case.
+ */
+void
+_gtk_recent_chooser_set_use_action_appearance (GtkRecentChooser *recent_chooser,
+ gboolean use_appearance)
+{
+ GtkAction *action;
+ gboolean use_action_appearance;
+
+ action = g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action);
+ use_action_appearance = !GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_use_action_appearance));
+
+ if (use_action_appearance != use_appearance)
+ {
+
+ g_object_set_qdata (G_OBJECT (recent_chooser), quark_gtk_use_action_appearance, !GINT_TO_POINTER (use_appearance));
+
+ gtk_activatable_reset (GTK_ACTIVATABLE (recent_chooser), action);
+ }
+}
+
+gboolean
+_gtk_recent_chooser_get_use_action_appearance (GtkRecentChooser *recent_chooser)
+{
+ return !GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_use_action_appearance));
+}
+
#define __GTK_RECENT_CHOOSER_C__
#include "gtkaliasdef.c"
diff --git a/gtk/gtkrecentchooserdefault.c b/gtk/gtkrecentchooserdefault.c
index 7e1b35ffd7..d8fecb2fbc 100644
--- a/gtk/gtkrecentchooserdefault.c
+++ b/gtk/gtkrecentchooserdefault.c
@@ -65,6 +65,7 @@
#include "gtktooltip.h"
#include "gtktypebuiltins.h"
#include "gtkvbox.h"
+#include "gtkactivatable.h"
#include "gtkrecentmanager.h"
#include "gtkrecentfilter.h"
@@ -76,7 +77,15 @@
#include "gtkprivate.h"
#include "gtkalias.h"
-
+enum
+{
+ PROP_0,
+
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
+};
+
struct _GtkRecentChooserDefault
{
@@ -274,13 +283,20 @@ static gboolean recent_view_query_tooltip_cb (GtkWidget *widget,
GtkTooltip *tooltip,
gpointer user_data);
-
+static void gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface);
+static void gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_recent_chooser_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
G_DEFINE_TYPE_WITH_CODE (GtkRecentChooserDefault,
_gtk_recent_chooser_default,
GTK_TYPE_VBOX,
G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER,
- gtk_recent_chooser_iface_init))
+ gtk_recent_chooser_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_recent_chooser_activatable_iface_init))
@@ -302,6 +318,14 @@ gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface)
iface->list_filters = gtk_recent_chooser_default_list_filters;
}
+static void
+gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface)
+
+{
+ iface->update = gtk_recent_chooser_activatable_update;
+ iface->reset = gtk_recent_chooser_activatable_reset;
+}
+
static void
_gtk_recent_chooser_default_class_init (GtkRecentChooserDefaultClass *klass)
{
@@ -318,6 +342,9 @@ _gtk_recent_chooser_default_class_init (GtkRecentChooserDefaultClass *klass)
widget_class->show_all = gtk_recent_chooser_default_show_all;
_gtk_recent_chooser_install_properties (gobject_class);
+
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
}
static void
@@ -528,6 +555,12 @@ gtk_recent_chooser_default_set_property (GObject *object,
case GTK_RECENT_CHOOSER_PROP_FILTER:
set_current_filter (impl, g_value_get_object (value));
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ _gtk_recent_chooser_set_related_action (GTK_RECENT_CHOOSER (impl), g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ _gtk_recent_chooser_set_use_action_appearance (GTK_RECENT_CHOOSER (impl), g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -571,6 +604,12 @@ gtk_recent_chooser_default_get_property (GObject *object,
case GTK_RECENT_CHOOSER_PROP_FILTER:
g_value_set_object (value, impl->current_filter);
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, _gtk_recent_chooser_get_related_action (GTK_RECENT_CHOOSER (impl)));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, _gtk_recent_chooser_get_use_action_appearance (GTK_RECENT_CHOOSER (impl)));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1909,6 +1948,44 @@ set_recent_manager (GtkRecentChooserDefault *impl,
}
}
+static void
+gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ if (strcmp (property_name, "visible") == 0)
+ {
+ if (gtk_action_is_visible (action))
+ gtk_widget_show (GTK_WIDGET (activatable));
+ else
+ gtk_widget_hide (GTK_WIDGET (activatable));
+ }
+
+ if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ _gtk_recent_chooser_activatable_update (activatable, action, property_name);
+}
+
+
+static void
+gtk_recent_chooser_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ if (action)
+ {
+ if (gtk_action_is_visible (action))
+ gtk_widget_show (GTK_WIDGET (activatable));
+ else
+ gtk_widget_hide (GTK_WIDGET (activatable));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+ }
+
+ _gtk_recent_chooser_activatable_reset (activatable, action);
+}
+
+
GtkWidget *
_gtk_recent_chooser_default_new (GtkRecentManager *manager)
{
diff --git a/gtk/gtkrecentchoosermenu.c b/gtk/gtkrecentchoosermenu.c
index 54ea3c7897..bc02aa6dfd 100644
--- a/gtk/gtkrecentchoosermenu.c
+++ b/gtk/gtkrecentchoosermenu.c
@@ -42,6 +42,7 @@
#include "gtkimage.h"
#include "gtklabel.h"
#include "gtktooltip.h"
+#include "gtkactivatable.h"
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
#include "gtkalias.h"
@@ -86,10 +87,14 @@ struct _GtkRecentChooserMenuPrivate
enum {
PROP_0,
+ PROP_SHOW_NUMBERS,
- PROP_SHOW_NUMBERS
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
};
+
#define FALLBACK_ICON_SIZE 32
#define FALLBACK_ITEM_LIMIT 10
#define DEFAULT_LABEL_WIDTH 30
@@ -155,11 +160,20 @@ static void item_activate_cb (GtkWidget *widget,
static void manager_changed_cb (GtkRecentManager *manager,
gpointer user_data);
+static void gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface);
+static void gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_recent_chooser_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+
G_DEFINE_TYPE_WITH_CODE (GtkRecentChooserMenu,
gtk_recent_chooser_menu,
GTK_TYPE_MENU,
G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER,
- gtk_recent_chooser_iface_init))
+ gtk_recent_chooser_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_recent_chooser_activatable_iface_init))
static void
@@ -179,6 +193,14 @@ gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface)
iface->list_filters = gtk_recent_chooser_menu_list_filters;
}
+static void
+gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface)
+
+{
+ iface->update = gtk_recent_chooser_activatable_update;
+ iface->reset = gtk_recent_chooser_activatable_reset;
+}
+
static void
gtk_recent_chooser_menu_class_init (GtkRecentChooserMenuClass *klass)
{
@@ -208,6 +230,10 @@ gtk_recent_chooser_menu_class_init (GtkRecentChooserMenuClass *klass)
FALSE,
GTK_PARAM_READWRITE));
+
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+
g_type_class_add_private (klass, sizeof (GtkRecentChooserMenuPrivate));
}
@@ -376,6 +402,12 @@ gtk_recent_chooser_menu_set_property (GObject *object,
case GTK_RECENT_CHOOSER_PROP_FILTER:
gtk_recent_chooser_menu_set_current_filter (menu, g_value_get_object (value));
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ _gtk_recent_chooser_set_related_action (GTK_RECENT_CHOOSER (menu), g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ _gtk_recent_chooser_set_use_action_appearance (GTK_RECENT_CHOOSER (menu), g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -423,6 +455,12 @@ gtk_recent_chooser_menu_get_property (GObject *object,
case GTK_RECENT_CHOOSER_PROP_FILTER:
g_value_set_object (value, priv->current_filter);
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, _gtk_recent_chooser_get_related_action (GTK_RECENT_CHOOSER (menu)));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, _gtk_recent_chooser_get_use_action_appearance (GTK_RECENT_CHOOSER (menu)));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1131,6 +1169,27 @@ gtk_recent_chooser_menu_set_show_tips (GtkRecentChooserMenu *menu,
gtk_container_foreach (GTK_CONTAINER (menu), foreach_set_shot_tips, menu);
}
+static void
+gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ _gtk_recent_chooser_activatable_update (activatable, action, property_name);
+}
+
+static void
+gtk_recent_chooser_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ _gtk_recent_chooser_activatable_reset (activatable, action);
+}
+
+
/*
* Public API
*/
diff --git a/gtk/gtkrecentchooserprivate.h b/gtk/gtkrecentchooserprivate.h
index 1057d05190..23ea2b497c 100644
--- a/gtk/gtkrecentchooserprivate.h
+++ b/gtk/gtkrecentchooserprivate.h
@@ -25,17 +25,30 @@
#include "gtkrecentmanager.h"
#include "gtkrecentchooser.h"
+#include "gtkactivatable.h"
G_BEGIN_DECLS
-GtkRecentManager *_gtk_recent_chooser_get_recent_manager (GtkRecentChooser *chooser);
-GList * _gtk_recent_chooser_get_items (GtkRecentChooser *chooser,
- GtkRecentFilter *filter,
- GtkRecentSortFunc func,
- gpointer data);
+GtkRecentManager *_gtk_recent_chooser_get_recent_manager (GtkRecentChooser *chooser);
+GList * _gtk_recent_chooser_get_items (GtkRecentChooser *chooser,
+ GtkRecentFilter *filter,
+ GtkRecentSortFunc func,
+ gpointer data);
-void _gtk_recent_chooser_item_activated (GtkRecentChooser *chooser);
-void _gtk_recent_chooser_selection_changed (GtkRecentChooser *chooser);
+void _gtk_recent_chooser_item_activated (GtkRecentChooser *chooser);
+void _gtk_recent_chooser_selection_changed (GtkRecentChooser *chooser);
+
+void _gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+void _gtk_recent_chooser_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+void _gtk_recent_chooser_set_related_action (GtkRecentChooser *recent_chooser,
+ GtkAction *action);
+GtkAction *_gtk_recent_chooser_get_related_action (GtkRecentChooser *recent_chooser);
+void _gtk_recent_chooser_set_use_action_appearance (GtkRecentChooser *recent_chooser,
+ gboolean use_appearance);
+gboolean _gtk_recent_chooser_get_use_action_appearance (GtkRecentChooser *recent_chooser);
G_END_DECLS
diff --git a/gtk/gtktoggleaction.c b/gtk/gtktoggleaction.c
index 33f045a0c4..19930ecefd 100644
--- a/gtk/gtktoggleaction.c
+++ b/gtk/gtktoggleaction.c
@@ -54,11 +54,6 @@ enum {
G_DEFINE_TYPE (GtkToggleAction, gtk_toggle_action, GTK_TYPE_ACTION)
static void gtk_toggle_action_activate (GtkAction *action);
-static void gtk_toggle_action_real_toggled (GtkToggleAction *action);
-static void connect_proxy (GtkAction *action,
- GtkWidget *proxy);
-static void disconnect_proxy (GtkAction *action,
- GtkWidget *proxy);
static void set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -87,16 +82,22 @@ gtk_toggle_action_class_init (GtkToggleActionClass *klass)
gobject_class->get_property = get_property;
action_class->activate = gtk_toggle_action_activate;
- action_class->connect_proxy = connect_proxy;
- action_class->disconnect_proxy = disconnect_proxy;
action_class->menu_item_type = GTK_TYPE_CHECK_MENU_ITEM;
action_class->toolbar_item_type = GTK_TYPE_TOGGLE_TOOL_BUTTON;
action_class->create_menu_item = create_menu_item;
- klass->toggled = gtk_toggle_action_real_toggled;
+ klass->toggled = NULL;
+ /**
+ * GtkToggleAction:draw-as-radio:
+ *
+ * Whether the proxies for this action look like radio action proxies.
+ *
+ * This is an appearance property and thus only applies if
+ * #GtkActivatable:use-action-appearance is %TRUE.
+ */
g_object_class_install_property (gobject_class,
PROP_DRAW_AS_RADIO,
g_param_spec_boolean ("draw-as-radio",
@@ -232,64 +233,6 @@ gtk_toggle_action_activate (GtkAction *action)
gtk_toggle_action_toggled (toggle_action);
}
-static void
-gtk_toggle_action_real_toggled (GtkToggleAction *action)
-{
- GSList *slist;
-
- g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
-
- for (slist = gtk_action_get_proxies (GTK_ACTION (action)); slist; slist = slist->next)
- {
- GtkWidget *proxy = slist->data;
-
- gtk_action_block_activate_from (GTK_ACTION (action), proxy);
- if (GTK_IS_CHECK_MENU_ITEM (proxy))
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
- action->private_data->active);
- else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
- gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
- action->private_data->active);
- else if (GTK_IS_TOGGLE_BUTTON (proxy))
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
- action->private_data->active);
- else {
- g_warning ("Don't know how to toggle `%s' widgets",
- G_OBJECT_TYPE_NAME (proxy));
- }
- gtk_action_unblock_activate_from (GTK_ACTION (action), proxy);
- }
-}
-
-static void
-connect_proxy (GtkAction *action,
- GtkWidget *proxy)
-{
- GtkToggleAction *toggle_action;
-
- toggle_action = GTK_TOGGLE_ACTION (action);
-
- /* do this before hand, so that we don't call the "activate" handler */
- if (GTK_IS_CHECK_MENU_ITEM (proxy))
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
- toggle_action->private_data->active);
- else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
- gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
- toggle_action->private_data->active);
- else if (GTK_IS_TOGGLE_BUTTON (proxy))
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
- toggle_action->private_data->active);
-
- GTK_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);
-}
-
-static void
-disconnect_proxy (GtkAction *action,
- GtkWidget *proxy)
-{
- GTK_ACTION_CLASS (parent_class)->disconnect_proxy (action, proxy);
-}
-
/**
* gtk_toggle_action_toggled:
* @action: the action object
diff --git a/gtk/gtktogglebutton.c b/gtk/gtktogglebutton.c
index 33505a9254..88f22fbf0c 100644
--- a/gtk/gtktogglebutton.c
+++ b/gtk/gtktogglebutton.c
@@ -29,6 +29,8 @@
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtktogglebutton.h"
+#include "gtktoggleaction.h"
+#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
@@ -67,9 +69,20 @@ static void gtk_toggle_button_get_property (GObject *object,
GParamSpec *pspec);
static void gtk_toggle_button_update_state (GtkButton *button);
-static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON)
+static void gtk_toggle_button_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_toggle_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_toggle_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+
+static GtkActivatableIface *parent_activatable_iface;
+static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_CODE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_toggle_button_activatable_interface_init))
static void
gtk_toggle_button_class_init (GtkToggleButtonClass *class)
@@ -139,6 +152,53 @@ gtk_toggle_button_init (GtkToggleButton *toggle_button)
}
+static void
+gtk_toggle_button_activatable_interface_init (GtkActivatableIface *iface)
+{
+ parent_activatable_iface = g_type_interface_peek_parent (iface);
+ iface->update = gtk_toggle_button_activatable_update;
+ iface->reset = gtk_toggle_button_activatable_reset;
+}
+
+static void
+gtk_toggle_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkToggleButton *button;
+
+ parent_activatable_iface->update (activatable, action, property_name);
+
+ button = GTK_TOGGLE_BUTTON (activatable);
+
+ if (strcmp (property_name, "active") == 0)
+ {
+ gtk_action_block_activate (action);
+ gtk_toggle_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ gtk_action_unblock_activate (action);
+ }
+
+}
+
+static void
+gtk_toggle_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkToggleButton *button;
+
+ parent_activatable_iface->reset (activatable, action);
+
+ if (!action)
+ return;
+
+ button = GTK_TOGGLE_BUTTON (activatable);
+
+ gtk_action_block_activate (action);
+ gtk_toggle_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ gtk_action_unblock_activate (action);
+}
+
+
GtkWidget*
gtk_toggle_button_new (void)
{
@@ -441,6 +501,8 @@ gtk_toggle_button_clicked (GtkButton *button)
gtk_toggle_button_update_state (button);
g_object_notify (G_OBJECT (toggle_button), "active");
+
+ GTK_BUTTON_CLASS (gtk_toggle_button_parent_class)->clicked (button);
}
static void
diff --git a/gtk/gtktoggletoolbutton.c b/gtk/gtktoggletoolbutton.c
index 1076458aae..c527c136b2 100644
--- a/gtk/gtktoggletoolbutton.c
+++ b/gtk/gtktoggletoolbutton.c
@@ -1,4 +1,4 @@
-/* gtktoggletoolbutton.c
+ /* gtktoggletoolbutton.c
*
* Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
* Copyright (C) 2002 James Henstridge <james@daa.com.au>
@@ -27,6 +27,8 @@
#include "gtkstock.h"
#include "gtkintl.h"
#include "gtkradiotoolbutton.h"
+#include "gtktoggleaction.h"
+#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkalias.h"
@@ -67,9 +69,20 @@ static void button_toggled (GtkWidget *widget,
static void menu_item_activated (GtkWidget *widget,
GtkToggleToolButton *button);
-static guint toggle_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkToggleToolButton, gtk_toggle_tool_button, GTK_TYPE_TOOL_BUTTON)
+static void gtk_toggle_tool_button_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_toggle_tool_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_toggle_tool_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+
+static GtkActivatableIface *parent_activatable_iface;
+static guint toggle_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_CODE (GtkToggleToolButton, gtk_toggle_tool_button, GTK_TYPE_TOOL_BUTTON,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_toggle_tool_button_activatable_interface_init))
static void
gtk_toggle_tool_button_class_init (GtkToggleToolButtonClass *klass)
@@ -292,6 +305,52 @@ button_toggled (GtkWidget *widget,
}
}
+static void
+gtk_toggle_tool_button_activatable_interface_init (GtkActivatableIface *iface)
+{
+ parent_activatable_iface = g_type_interface_peek_parent (iface);
+ iface->update = gtk_toggle_tool_button_activatable_update;
+ iface->reset = gtk_toggle_tool_button_activatable_reset;
+}
+
+static void
+gtk_toggle_tool_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkToggleToolButton *button;
+
+ parent_activatable_iface->update (activatable, action, property_name);
+
+ button = GTK_TOGGLE_TOOL_BUTTON (activatable);
+
+ if (strcmp (property_name, "active") == 0)
+ {
+ gtk_action_block_activate (action);
+ gtk_toggle_tool_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ gtk_action_unblock_activate (action);
+ }
+}
+
+static void
+gtk_toggle_tool_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkToggleToolButton *button;
+
+ parent_activatable_iface->reset (activatable, action);
+
+ if (!action)
+ return;
+
+ button = GTK_TOGGLE_TOOL_BUTTON (activatable);
+
+ gtk_action_block_activate (action);
+ gtk_toggle_tool_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ gtk_action_unblock_activate (action);
+}
+
+
/**
* gtk_toggle_tool_button_new:
*
diff --git a/gtk/gtktoolbutton.c b/gtk/gtktoolbutton.c
index 65b3c1aaa9..be2bf5af48 100644
--- a/gtk/gtktoolbutton.c
+++ b/gtk/gtktoolbutton.c
@@ -32,6 +32,7 @@
#include "gtkvbox.h"
#include "gtkintl.h"
#include "gtktoolbar.h"
+#include "gtkactivatable.h"
#include "gtkprivate.h"
#include "gtkalias.h"
@@ -77,11 +78,14 @@ static void gtk_tool_button_style_set (GtkWidget *widget,
GtkStyle *prev_style);
static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
-
-static GObjectClass *parent_class = NULL;
-static guint toolbutton_signals[LAST_SIGNAL] = { 0 };
-#define GTK_TOOL_BUTTON_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TOOL_BUTTON, GtkToolButtonPrivate))
+static void gtk_tool_button_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_tool_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_tool_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+
struct _GtkToolButtonPrivate
{
@@ -97,19 +101,37 @@ struct _GtkToolButtonPrivate
guint contents_invalid : 1;
};
+static GObjectClass *parent_class = NULL;
+static GtkActivatableIface *parent_activatable_iface;
+static guint toolbutton_signals[LAST_SIGNAL] = { 0 };
+
+#define GTK_TOOL_BUTTON_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TOOL_BUTTON, GtkToolButtonPrivate))
+
GType
gtk_tool_button_get_type (void)
{
static GType type = 0;
-
+
if (!type)
- type = g_type_register_static_simple (GTK_TYPE_TOOL_ITEM,
- I_("GtkToolButton"),
- sizeof (GtkToolButtonClass),
- (GClassInitFunc) gtk_tool_button_class_init,
- sizeof (GtkToolButton),
- (GInstanceInitFunc) gtk_tool_button_init,
- 0);
+ {
+ static const GInterfaceInfo activatable_info =
+ {
+ (GInterfaceInitFunc) gtk_tool_button_activatable_interface_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL
+ };
+
+ type = g_type_register_static_simple (GTK_TYPE_TOOL_ITEM,
+ I_("GtkToolButton"),
+ sizeof (GtkToolButtonClass),
+ (GClassInitFunc) gtk_tool_button_class_init,
+ sizeof (GtkToolButton),
+ (GInstanceInitFunc) gtk_tool_button_init,
+ 0);
+
+ g_type_add_interface_static (type, GTK_TYPE_ACTIVATABLE,
+ &activatable_info);
+ }
return type;
}
@@ -672,6 +694,13 @@ static void
button_clicked (GtkWidget *widget,
GtkToolButton *button)
{
+ GtkAction *action;
+
+ action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (button));
+
+ if (action)
+ gtk_action_activate (action);
+
g_signal_emit_by_name (button, "clicked");
}
@@ -704,6 +733,123 @@ gtk_tool_button_style_set (GtkWidget *widget,
gtk_tool_button_update_icon_spacing (GTK_TOOL_BUTTON (widget));
}
+static void
+gtk_tool_button_activatable_interface_init (GtkActivatableIface *iface)
+{
+ parent_activatable_iface = g_type_interface_peek_parent (iface);
+ iface->update = gtk_tool_button_activatable_update;
+ iface->reset = gtk_tool_button_activatable_reset;
+}
+
+static void
+gtk_tool_button_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkToolButton *button;
+ GtkWidget *image;
+
+ parent_activatable_iface->update (activatable, action, property_name);
+
+ if (!gtk_activatable_get_use_action_appearance (activatable))
+ return;
+
+ button = GTK_TOOL_BUTTON (activatable);
+
+ if (strcmp (property_name, "short-label") == 0)
+ {
+ if (!gtk_action_get_stock_id (action) &&
+ !gtk_action_get_icon_name (action))
+ {
+ gtk_tool_button_set_use_underline (button, TRUE);
+ gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
+ }
+ }
+ else if (strcmp (property_name, "stock-id") == 0)
+ {
+ if (gtk_action_get_stock_id (action))
+ {
+ gtk_tool_button_set_label (button, NULL);
+ gtk_tool_button_set_icon_name (button, NULL);
+ }
+ gtk_tool_button_set_stock_id (button, gtk_action_get_stock_id (action));
+ }
+ else if (strcmp (property_name, "gicon") == 0)
+ {
+ const gchar *stock_id = gtk_action_get_stock_id (action);
+ GIcon *icon = gtk_action_get_gicon (action);
+ GtkIconSize icon_size = GTK_ICON_SIZE_BUTTON;
+
+ if ((stock_id && gtk_icon_factory_lookup_default (stock_id)) || !icon)
+ image = NULL;
+ else
+ {
+ image = gtk_tool_button_get_icon_widget (button);
+ icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
+
+ if (!image)
+ image = gtk_image_new ();
+ }
+
+ gtk_tool_button_set_icon_widget (button, image);
+ gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
+
+ }
+ else if (strcmp (property_name, "icon-name") == 0)
+ {
+ if (gtk_action_get_icon_name (action))
+ {
+ gtk_tool_button_set_label (button, NULL);
+ gtk_tool_button_set_stock_id (button, NULL);
+ }
+ gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
+ }
+}
+
+static void
+gtk_tool_button_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkToolButton *button;
+ GIcon *icon;
+
+ parent_activatable_iface->reset (activatable, action);
+
+ if (!action)
+ return;
+
+ if (!gtk_activatable_get_use_action_appearance (activatable))
+ return;
+
+ button = GTK_TOOL_BUTTON (activatable);
+
+ gtk_tool_button_set_label (button, NULL);
+ gtk_tool_button_set_stock_id (button, NULL);
+ gtk_tool_button_set_icon_name (button, NULL);
+ gtk_tool_button_set_use_underline (button, TRUE);
+
+ if (gtk_action_get_stock_id (action))
+ gtk_tool_button_set_stock_id (button, gtk_action_get_stock_id (action));
+ else if ((icon = gtk_action_get_gicon (action)) != NULL)
+ {
+ GtkIconSize icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
+ GtkWidget *image = gtk_tool_button_get_icon_widget (button);
+
+ if (!image)
+ {
+ image = gtk_image_new ();
+ gtk_widget_show (image);
+ gtk_tool_button_set_icon_widget (button, image);
+ }
+
+ gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
+ }
+ else if (gtk_action_get_icon_name (action))
+ gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
+ else
+ gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
+}
+
/**
* gtk_tool_button_new_from_stock:
* @stock_id: the name of the stock item
diff --git a/gtk/gtktoolitem.c b/gtk/gtktoolitem.c
index 40a8d0cd0f..54b60e792f 100644
--- a/gtk/gtktoolitem.c
+++ b/gtk/gtktoolitem.c
@@ -30,6 +30,7 @@
#include "gtkmarshalers.h"
#include "gtktoolshell.h"
#include "gtkseparatormenuitem.h"
+#include "gtkactivatable.h"
#include "gtkintl.h"
#include "gtkmain.h"
#include "gtkprivate.h"
@@ -69,7 +70,11 @@ enum {
PROP_0,
PROP_VISIBLE_HORIZONTAL,
PROP_VISIBLE_VERTICAL,
- PROP_IS_IMPORTANT
+ PROP_IS_IMPORTANT,
+
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
};
#define GTK_TOOL_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOL_ITEM, GtkToolItemPrivate))
@@ -90,11 +95,15 @@ struct _GtkToolItemPrivate
gchar *menu_item_id;
GtkWidget *menu_item;
+
+ GtkAction *action;
+ gboolean use_action_appearance;
};
-static void gtk_tool_item_finalize (GObject *object);
-static void gtk_tool_item_parent_set (GtkWidget *toolitem,
- GtkWidget *parent);
+static void gtk_tool_item_finalize (GObject *object);
+static void gtk_tool_item_dispose (GObject *object);
+static void gtk_tool_item_parent_set (GtkWidget *toolitem,
+ GtkWidget *parent);
static void gtk_tool_item_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -120,10 +129,22 @@ static gboolean gtk_tool_item_real_set_tooltip (GtkToolItem *tool_item,
static gboolean gtk_tool_item_create_menu_proxy (GtkToolItem *item);
+static void gtk_tool_item_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_tool_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_tool_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action);
+static void gtk_tool_item_set_related_action (GtkToolItem *item,
+ GtkAction *action);
+static void gtk_tool_item_set_use_action_appearance (GtkToolItem *item,
+ gboolean use_appearance);
static guint toolitem_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkToolItem, gtk_tool_item, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_CODE (GtkToolItem, gtk_tool_item, GTK_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_tool_item_activatable_interface_init))
static void
gtk_tool_item_class_init (GtkToolItemClass *klass)
@@ -136,8 +157,9 @@ gtk_tool_item_class_init (GtkToolItemClass *klass)
object_class->set_property = gtk_tool_item_set_property;
object_class->get_property = gtk_tool_item_get_property;
- object_class->finalize = gtk_tool_item_finalize;
- object_class->notify = gtk_tool_item_property_notify;
+ object_class->finalize = gtk_tool_item_finalize;
+ object_class->dispose = gtk_tool_item_dispose;
+ object_class->notify = gtk_tool_item_property_notify;
widget_class->realize = gtk_tool_item_realize;
widget_class->unrealize = gtk_tool_item_unrealize;
@@ -172,6 +194,10 @@ gtk_tool_item_class_init (GtkToolItemClass *klass)
FALSE,
GTK_PARAM_READWRITE));
+ g_object_class_override_property (object_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (object_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+
+
/**
* GtkToolItem::create-menu-proxy:
* @tool_item: the object the signal was emitted on
@@ -276,6 +302,8 @@ gtk_tool_item_init (GtkToolItem *toolitem)
toolitem->priv->visible_vertical = TRUE;
toolitem->priv->homogeneous = FALSE;
toolitem->priv->expand = FALSE;
+
+ toolitem->priv->use_action_appearance = TRUE;
}
static void
@@ -292,6 +320,20 @@ gtk_tool_item_finalize (GObject *object)
}
static void
+gtk_tool_item_dispose (GObject *object)
+{
+ GtkToolItem *item = GTK_TOOL_ITEM (object);
+
+ if (item->priv->action)
+ {
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (item), NULL);
+ item->priv->action = NULL;
+ }
+ G_OBJECT_CLASS (gtk_tool_item_parent_class)->dispose (object);
+}
+
+
+static void
gtk_tool_item_parent_set (GtkWidget *toolitem,
GtkWidget *prev_parent)
{
@@ -318,6 +360,12 @@ gtk_tool_item_set_property (GObject *object,
case PROP_IS_IMPORTANT:
gtk_tool_item_set_is_important (toolitem, g_value_get_boolean (value));
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ gtk_tool_item_set_related_action (toolitem, g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ gtk_tool_item_set_use_action_appearance (toolitem, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -343,6 +391,12 @@ gtk_tool_item_get_property (GObject *object,
case PROP_IS_IMPORTANT:
g_value_set_boolean (value, toolitem->priv->is_important);
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, toolitem->priv->action);
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, toolitem->priv->use_action_appearance);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -503,9 +557,117 @@ gtk_tool_item_size_allocate (GtkWidget *widget,
static gboolean
gtk_tool_item_create_menu_proxy (GtkToolItem *item)
{
+ GtkWidget *menu_item;
+ gboolean visible_overflown;
+
+ if (item->priv->action)
+ {
+ g_object_get (item->priv->action, "visible-overflown", &visible_overflown, NULL);
+
+ if (visible_overflown)
+ {
+ menu_item = gtk_action_create_menu_item (item->priv->action);
+
+ g_object_ref_sink (menu_item);
+ gtk_tool_item_set_proxy_menu_item (item, "gtk-action-menu-item", menu_item);
+ g_object_unref (menu_item);
+ }
+ else
+ gtk_tool_item_set_proxy_menu_item (item, "gtk-action-menu-item", NULL);
+ }
+
return FALSE;
}
+static void
+gtk_tool_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+ iface->update = gtk_tool_item_activatable_update;
+ iface->reset = gtk_tool_item_activatable_reset;
+}
+
+static void
+gtk_tool_item_activatable_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ if (strcmp (property_name, "visible") == 0)
+ {
+ if (gtk_action_is_visible (action))
+ gtk_widget_show (GTK_WIDGET (activatable));
+ else
+ gtk_widget_hide (GTK_WIDGET (activatable));
+ }
+ else if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+ else if (strcmp (property_name, "tooltip") == 0)
+ gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_tooltip (action));
+ else if (strcmp (property_name, "visible-horizontal") == 0)
+ gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_visible_horizontal (action));
+ else if (strcmp (property_name, "visible-vertical") == 0)
+ gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_visible_vertical (action));
+ else if (strcmp (property_name, "is-important") == 0)
+ gtk_tool_item_set_is_important (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_is_important (action));
+}
+
+static void
+gtk_tool_item_activatable_reset (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ if (!action)
+ return;
+
+ if (gtk_action_is_visible (action))
+ gtk_widget_show (GTK_WIDGET (activatable));
+ else
+ gtk_widget_hide (GTK_WIDGET (activatable));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_tooltip (action));
+ gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_visible_horizontal (action));
+ gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_visible_vertical (action));
+ gtk_tool_item_set_is_important (GTK_TOOL_ITEM (activatable),
+ gtk_action_get_is_important (action));
+}
+
+static void
+gtk_tool_item_set_related_action (GtkToolItem *item,
+ GtkAction *action)
+{
+ if (item->priv->action == action)
+ return;
+
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (item), action);
+
+ item->priv->action = action;
+
+ if (action)
+ {
+ gtk_tool_item_rebuild_menu (item);
+ }
+}
+
+static void
+gtk_tool_item_set_use_action_appearance (GtkToolItem *item,
+ gboolean use_appearance)
+{
+ if (item->priv->use_action_appearance != use_appearance)
+ {
+ item->priv->use_action_appearance = use_appearance;
+
+ gtk_activatable_reset (GTK_ACTIVATABLE (item), item->priv->action);
+ }
+}
+
+
/**
* gtk_tool_item_new:
*