]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkaction.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkaction.c
index ed893edacac0937ffd10cee50c25019c9c0cc884..6bb0ae9d7b6eb3a07063bf6d4fb70f515aa56e48 100644 (file)
@@ -14,9 +14,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <config.h>
+/**
+ * SECTION:gtkaction
+ * @Short_description: An action which can be triggered by a menu or toolbar item
+ * @Title: GtkAction
+ * @See_also: #GtkActionGroup, #GtkUIManager, #GtkActivatable
+ *
+ * Actions represent operations that the user can be perform, along with
+ * some information how it should be presented in the interface. Each action
+ * provides methods to create icons, menu items and toolbar items
+ * representing itself.
+ *
+ * As well as the callback that is called when the action gets activated,
+ * the following also gets associated with the action:
+ * <itemizedlist>
+ *   <listitem><para>a name (not translated, for path lookup)</para></listitem>
+ *   <listitem><para>a label (translated, for display)</para></listitem>
+ *   <listitem><para>an accelerator</para></listitem>
+ *   <listitem><para>whether label indicates a stock id</para></listitem>
+ *   <listitem><para>a tooltip (optional, translated)</para></listitem>
+ *   <listitem><para>a toolbar label (optional, shorter than label)</para></listitem>
+ * </itemizedlist>
+ * The action will also have some state information:
+ * <itemizedlist>
+ *   <listitem><para>visible (shown/hidden)</para></listitem>
+ *   <listitem><para>sensitive (enabled/disabled)</para></listitem>
+ * </itemizedlist>
+ * Apart from regular actions, there are <link linkend="GtkToggleAction">toggle
+ * actions</link>, which can be toggled between two states and <link
+ * linkend="GtkRadioAction">radio actions</link>, of which only one in a group
+ * can be in the "active" state. Other actions can be implemented as #GtkAction
+ * subclasses.
+ *
+ * Each action can have one or more proxy widgets. To act as an action proxy,
+ * widget needs to implement #GtkActivatable interface. Proxies mirror the state
+ * of the action and should change when the action's state changes. Properties
+ * that are always mirrored by proxies are #GtkAction:sensitive and
+ * #GtkAction:visible. #GtkAction:gicon, #GtkAction:icon-name, #GtkAction:label,
+ * #GtkAction:short-label and #GtkAction:stock-id properties are only mirorred
+ * if proxy widget has #GtkActivatable:use-action-appearance property set to
+ * %TRUE.
+ *
+ * When the proxy is activated, it should activate its action.
+ */
+
+#include "config.h"
 
 #include "gtkaction.h"
 #include "gtkactiongroup.h"
 #include "gtkaccellabel.h"
 #include "gtkbutton.h"
+#include "gtkiconfactory.h"
 #include "gtkimage.h"
 #include "gtkimagemenuitem.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtkmenuitem.h"
 #include "gtkstock.h"
-#include "gtktearoffmenuitem.h"
+#include "deprecated/gtktearoffmenuitem.h"
 #include "gtktoolbutton.h"
 #include "gtktoolbar.h"
 #include "gtkprivate.h"
-#include "gtkalias.h"
-
+#include "gtkbuildable.h"
+#include "gtkactivatable.h"
 
-#define GTK_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION, GtkActionPrivate))
 
 struct _GtkActionPrivate 
 {
-  gchar *name;
+  const gchar *name; /* interned */
   gchar *label;
   gchar *short_label;
   gchar *tooltip;
-  gchar *stock_id; /* icon */
+  gchar *stock_id; /* stock icon */
+  gchar *icon_name; /* themed icon */
+  GIcon *gicon;
 
   guint sensitive          : 1;
   guint visible            : 1;
@@ -67,6 +111,9 @@ struct _GtkActionPrivate
   guint is_important       : 1;
   guint hide_if_empty      : 1;
   guint visible_overflown  : 1;
+  guint always_show_image  : 1;
+  guint recursion_guard    : 1;
+  guint activate_blocked   : 1;
 
   /* accelerator */
   guint          accel_count;
@@ -94,6 +141,8 @@ enum
   PROP_SHORT_LABEL,
   PROP_TOOLTIP,
   PROP_STOCK_ID,
+  PROP_ICON_NAME,
+  PROP_GICON,
   PROP_VISIBLE_HORIZONTAL,
   PROP_VISIBLE_VERTICAL,
   PROP_VISIBLE_OVERFLOWN,
@@ -101,42 +150,19 @@ enum
   PROP_HIDE_IF_EMPTY,
   PROP_SENSITIVE,
   PROP_VISIBLE,
-  PROP_ACTION_GROUP
+  PROP_ACTION_GROUP,
+  PROP_ALWAYS_SHOW_IMAGE
 };
 
-static void gtk_action_init       (GtkAction *action);
-static void gtk_action_class_init (GtkActionClass *class);
+/* GtkBuildable */
+static void gtk_action_buildable_init             (GtkBuildableIface *iface);
+static void gtk_action_buildable_set_name         (GtkBuildable *buildable,
+                                                  const gchar  *name);
+static const gchar* gtk_action_buildable_get_name (GtkBuildable *buildable);
 
-static GQuark       accel_path_id  = 0;
-static const gchar accel_path_key[] = "GtkAction::accel_path";
-
-GType
-gtk_action_get_type (void)
-{
-  static GtkType type = 0;
-
-  if (!type)
-    {
-      static const GTypeInfo type_info =
-      {
-        sizeof (GtkActionClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gtk_action_class_init,
-        (GClassFinalizeFunc) NULL,
-        NULL,
-        
-        sizeof (GtkAction),
-        0, /* n_preallocs */
-        (GInstanceInitFunc) gtk_action_init,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT,
-                                    "GtkAction",
-                                    &type_info, 0);
-    }
-  return type;
-}
+G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_action_buildable_init))
 
 static void gtk_action_finalize     (GObject *object);
 static void gtk_action_set_property (GObject         *object,
@@ -147,15 +173,16 @@ static void gtk_action_get_property (GObject         *object,
                                     guint            prop_id,
                                     GValue          *value,
                                     GParamSpec      *pspec);
-static void gtk_action_set_action_group (GtkAction         *action,
+static void gtk_action_set_action_group (GtkAction     *action,
                                         GtkActionGroup *action_group);
 
 static GtkWidget *create_menu_item    (GtkAction *action);
 static GtkWidget *create_tool_item    (GtkAction *action);
-static void       connect_proxy       (GtkAction     *action,
-                                      GtkWidget     *proxy);
+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,
@@ -163,7 +190,6 @@ static void       closure_accel_activate (GClosure     *closure,
                                          gpointer      invocation_hint,
                                          gpointer      marshal_data);
 
-static GObjectClass *parent_class = NULL;
 static guint         action_signals[LAST_SIGNAL] = { 0 };
 
 
@@ -172,9 +198,6 @@ gtk_action_class_init (GtkActionClass *klass)
 {
   GObjectClass *gobject_class;
 
-  accel_path_id = g_quark_from_static_string (accel_path_key);
-
-  parent_class = g_type_class_peek_parent (klass);
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize     = gtk_action_finalize;
@@ -183,13 +206,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->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,
@@ -199,6 +222,17 @@ gtk_action_class_init (GtkActionClass *klass)
                                                        NULL,
                                                        GTK_PARAM_READWRITE | 
                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkAction:label:
+   *
+   * 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,
                                   g_param_spec_string ("label",
@@ -207,6 +241,15 @@ gtk_action_class_init (GtkActionClass *klass)
                                                           "that activate this action."),
                                                        NULL,
                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * 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,
                                   g_param_spec_string ("short-label",
@@ -214,6 +257,8 @@ gtk_action_class_init (GtkActionClass *klass)
                                                        P_("A shorter label that may be used on toolbar buttons."),
                                                        NULL,
                                                        GTK_PARAM_READWRITE));
+
+
   g_object_class_install_property (gobject_class,
                                   PROP_TOOLTIP,
                                   g_param_spec_string ("tooltip",
@@ -221,6 +266,15 @@ gtk_action_class_init (GtkActionClass *klass)
                                                        P_("A tooltip for this action."),
                                                        NULL,
                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * 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,
                                   g_param_spec_string ("stock-id",
@@ -229,6 +283,48 @@ gtk_action_class_init (GtkActionClass *klass)
                                                           "this action."),
                                                        NULL,
                                                        GTK_PARAM_READWRITE));
+  /**
+   * GtkAction:gicon:
+   *
+   * The #GIcon displayed in the #GtkAction.
+   *
+   * 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,
+                                  PROP_GICON,
+                                  g_param_spec_object ("gicon",
+                                                       P_("GIcon"),
+                                                       P_("The GIcon being displayed"),
+                                                       G_TYPE_ICON,
+                                                       GTK_PARAM_READWRITE));                                                  
+  /**
+   * GtkAction:icon-name:
+   *
+   * The name of the icon from the icon theme. 
+   * 
+   * Note that the stock icon is preferred, if the #GtkAction:stock-id 
+   * 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,
+                                  PROP_ICON_NAME,
+                                  g_param_spec_string ("icon-name",
+                                                       P_("Icon Name"),
+                                                       P_("The name of the icon from the icon theme"),
+                                                       NULL,
+                                                       GTK_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class,
                                   PROP_VISIBLE_HORIZONTAL,
                                   g_param_spec_boolean ("visible-horizontal",
@@ -299,6 +395,25 @@ gtk_action_class_init (GtkActionClass *klass)
                                                         GTK_TYPE_ACTION_GROUP,
                                                         GTK_PARAM_READWRITE));
 
+  /**
+   * GtkAction:always-show-image:
+   *
+   * If %TRUE, the action's menu item proxies will ignore the #GtkSettings:gtk-menu-images 
+   * setting and always show their image, if available.
+   *
+   * Use this property if the menu item would be useless or hard to use
+   * without their image. 
+   *
+   * Since: 2.20
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_ALWAYS_SHOW_IMAGE,
+                                   g_param_spec_boolean ("always-show-image",
+                                                         P_("Always show image"),
+                                                         P_("Whether the image will always be shown"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
   /**
    * GtkAction::activate:
    * @action: the #GtkAction
@@ -308,7 +423,7 @@ gtk_action_class_init (GtkActionClass *klass)
    * Since: 2.4
    */
   action_signals[ACTIVATE] =
-    g_signal_new ("activate",
+    g_signal_new (I_("activate"),
                  G_OBJECT_CLASS_TYPE (klass),
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
                  G_STRUCT_OFFSET (GtkActionClass, activate),  NULL, NULL,
@@ -322,18 +437,23 @@ gtk_action_class_init (GtkActionClass *klass)
 static void
 gtk_action_init (GtkAction *action)
 {
-  action->private_data = GTK_ACTION_GET_PRIVATE (action);
+  action->private_data = G_TYPE_INSTANCE_GET_PRIVATE (action,
+                                                      GTK_TYPE_ACTION,
+                                                      GtkActionPrivate);
 
   action->private_data->name = NULL;
   action->private_data->label = NULL;
   action->private_data->short_label = NULL;
   action->private_data->tooltip = NULL;
   action->private_data->stock_id = NULL;
+  action->private_data->icon_name = NULL;
   action->private_data->visible_horizontal = TRUE;
   action->private_data->visible_vertical   = TRUE;
   action->private_data->visible_overflown  = TRUE;
   action->private_data->is_important = FALSE;
   action->private_data->hide_if_empty = TRUE;
+  action->private_data->always_show_image = FALSE;
+  action->private_data->activate_blocked = FALSE;
 
   action->private_data->sensitive = TRUE;
   action->private_data->visible = TRUE;
@@ -354,14 +474,41 @@ gtk_action_init (GtkAction *action)
   action->private_data->action_group = NULL;
 
   action->private_data->proxies = NULL;
+  action->private_data->gicon = NULL;  
+}
+
+static void
+gtk_action_buildable_init (GtkBuildableIface *iface)
+{
+  iface->set_name = gtk_action_buildable_set_name;
+  iface->get_name = gtk_action_buildable_get_name;
+}
+
+static void
+gtk_action_buildable_set_name (GtkBuildable *buildable,
+                              const gchar  *name)
+{
+  GtkAction *action = GTK_ACTION (buildable);
+
+  action->private_data->name = g_intern_string (name);
+}
+
+static const gchar *
+gtk_action_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkAction *action = GTK_ACTION (buildable);
+
+  return action->private_data->name;
 }
 
 /**
  * gtk_action_new:
  * @name: A unique name for the action
- * @label: the label displayed in menu items and on buttons
- * @tooltip: a tooltip for the action
- * @stock_id: the stock icon to display in widgets representing the action
+ * @label: (allow-none): the label displayed in menu items and on buttons,
+ *         or %NULL
+ * @tooltip: (allow-none): a tooltip for the action, or %NULL
+ * @stock_id: (allow-none): the stock icon to display in widgets representing
+ *            the action, or %NULL
  *
  * Creates a new #GtkAction object. To add the action to a
  * #GtkActionGroup and set the accelerator for the action,
@@ -379,16 +526,14 @@ gtk_action_new (const gchar *name,
                const gchar *tooltip,
                const gchar *stock_id)
 {
-  GtkAction *action;
-
-  action = g_object_new (GTK_TYPE_ACTION,
-                        "name", name,
-                        "label", label,
-                        "tooltip", tooltip,
-                        "stock_id", stock_id,
-                        NULL);
-
-  return action;
+  g_return_val_if_fail (name != NULL, NULL);
+
+  return g_object_new (GTK_TYPE_ACTION,
+                       "name", name,
+                      "label", label,
+                      "tooltip", tooltip,
+                      "stock-id", stock_id,
+                      NULL);
 }
 
 static void
@@ -397,17 +542,20 @@ gtk_action_finalize (GObject *object)
   GtkAction *action;
   action = GTK_ACTION (object);
 
-  g_free (action->private_data->name);
   g_free (action->private_data->label);
   g_free (action->private_data->short_label);
   g_free (action->private_data->tooltip);
   g_free (action->private_data->stock_id);
+  g_free (action->private_data->icon_name);
+  
+  if (action->private_data->gicon)
+    g_object_unref (action->private_data->gicon);
 
   g_closure_unref (action->private_data->accel_closure);
   if (action->private_data->accel_group)
     g_object_unref (action->private_data->accel_group);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);  
+  G_OBJECT_CLASS (gtk_action_parent_class)->finalize (object);  
 }
 
 static void
@@ -417,103 +565,59 @@ gtk_action_set_property (GObject         *object,
                         GParamSpec      *pspec)
 {
   GtkAction *action;
-  gchar *tmp;
   
   action = GTK_ACTION (object);
 
   switch (prop_id)
     {
     case PROP_NAME:
-      tmp = action->private_data->name;
-      action->private_data->name = g_value_dup_string (value);
-      g_free (tmp);
+      action->private_data->name = g_intern_string (g_value_get_string (value));
       break;
     case PROP_LABEL:
-      tmp = action->private_data->label;
-      action->private_data->label = g_value_dup_string (value);
-      g_free (tmp);
-      action->private_data->label_set = (action->private_data->label != NULL);
-      /* if label is unset, then use the label from the stock item */
-      if (!action->private_data->label_set && action->private_data->stock_id)
-       {
-         GtkStockItem stock_item;
-
-         if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
-           action->private_data->label = g_strdup (stock_item.label);
-       }
-      /* if short_label is unset, set short_label=label */
-      if (!action->private_data->short_label_set)
-       {
-         tmp = action->private_data->short_label;
-         action->private_data->short_label = g_strdup (action->private_data->label);
-         g_free (tmp);
-         g_object_notify (object, "short-label");
-       }
+      gtk_action_set_label (action, g_value_get_string (value));
       break;
     case PROP_SHORT_LABEL:
-      tmp = action->private_data->short_label;
-      action->private_data->short_label = g_value_dup_string (value);
-      g_free (tmp);
-      action->private_data->short_label_set = (action->private_data->short_label != NULL);
-      /* if short_label is unset, then use the value of label */
-      if (!action->private_data->short_label_set)
-       {
-         action->private_data->short_label = g_strdup (action->private_data->label);
-       }
+      gtk_action_set_short_label (action, g_value_get_string (value));
       break;
     case PROP_TOOLTIP:
-      tmp = action->private_data->tooltip;
-      action->private_data->tooltip = g_value_dup_string (value);
-      g_free (tmp);
+      gtk_action_set_tooltip (action, g_value_get_string (value));
       break;
     case PROP_STOCK_ID:
-      tmp = action->private_data->stock_id;
-      action->private_data->stock_id = g_value_dup_string (value);
-      g_free (tmp);
-      /* update label and short_label if appropriate */
-      if (!action->private_data->label_set)
-       {
-         GtkStockItem stock_item;
-
-         g_free (action->private_data->label);
-         if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
-           action->private_data->label = g_strdup (stock_item.label);
-         else
-           action->private_data->label = NULL;
-         g_object_notify (object, "label");
-       }
-      if (!action->private_data->short_label_set)
-       {
-         tmp = action->private_data->short_label;
-         action->private_data->short_label = g_strdup (action->private_data->label);
-         g_free (tmp);
-         g_object_notify (object, "short-label");
-       }
+      gtk_action_set_stock_id (action, g_value_get_string (value));
+      break;
+    case PROP_GICON:
+      gtk_action_set_gicon (action, g_value_get_object (value));
+      break;
+    case PROP_ICON_NAME:
+      gtk_action_set_icon_name (action, g_value_get_string (value));
       break;
     case PROP_VISIBLE_HORIZONTAL:
-      action->private_data->visible_horizontal = g_value_get_boolean (value);
+      gtk_action_set_visible_horizontal (action, g_value_get_boolean (value));
       break;
     case PROP_VISIBLE_VERTICAL:
-      action->private_data->visible_vertical = g_value_get_boolean (value);
+      gtk_action_set_visible_vertical (action, g_value_get_boolean (value));
       break;
     case PROP_VISIBLE_OVERFLOWN:
       action->private_data->visible_overflown = g_value_get_boolean (value);
       break;
     case PROP_IS_IMPORTANT:
-      action->private_data->is_important = g_value_get_boolean (value);
+      gtk_action_set_is_important (action, g_value_get_boolean (value));
       break;
     case PROP_HIDE_IF_EMPTY:
       action->private_data->hide_if_empty = g_value_get_boolean (value);
       break;
     case PROP_SENSITIVE:
-      action->private_data->sensitive = g_value_get_boolean (value);
+      gtk_action_set_sensitive (action, g_value_get_boolean (value));
       break;
     case PROP_VISIBLE:
-      action->private_data->visible = g_value_get_boolean (value);
+      gtk_action_set_visible (action, g_value_get_boolean (value));
       break;
     case PROP_ACTION_GROUP:
       gtk_action_set_action_group (action, g_value_get_object (value));
       break;
+    case PROP_ALWAYS_SHOW_IMAGE:
+      gtk_action_set_always_show_image (action, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -533,7 +637,7 @@ gtk_action_get_property (GObject    *object,
   switch (prop_id)
     {
     case PROP_NAME:
-      g_value_set_string (value, action->private_data->name);
+      g_value_set_static_string (value, action->private_data->name);
       break;
     case PROP_LABEL:
       g_value_set_string (value, action->private_data->label);
@@ -547,6 +651,12 @@ gtk_action_get_property (GObject    *object,
     case PROP_STOCK_ID:
       g_value_set_string (value, action->private_data->stock_id);
       break;
+    case PROP_ICON_NAME:
+      g_value_set_string (value, action->private_data->icon_name);
+      break;
+    case PROP_GICON:
+      g_value_set_object (value, action->private_data->gicon);
+      break;
     case PROP_VISIBLE_HORIZONTAL:
       g_value_set_boolean (value, action->private_data->visible_horizontal);
       break;
@@ -571,6 +681,9 @@ gtk_action_get_property (GObject    *object,
     case PROP_ACTION_GROUP:
       g_value_set_object (value, action->private_data->action_group);
       break;
+    case PROP_ALWAYS_SHOW_IMAGE:
+      g_value_set_boolean (value, action->private_data->always_show_image);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -598,43 +711,39 @@ create_tool_item (GtkAction *action)
 }
 
 static void
-remove_proxy (GtkWidget *proxy, 
-             GtkAction *action)
+remove_proxy (GtkAction *action,
+             GtkWidget *proxy)
 {
-  if (GTK_IS_MENU_ITEM (proxy))
-    gtk_action_disconnect_accelerator (action);
-
+  g_object_unref (proxy);
   action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
 }
 
 static void
-gtk_action_sync_sensitivity (GtkAction  *action, 
-                            GParamSpec *pspec,
-                            GtkWidget  *proxy)
+connect_proxy (GtkAction *action,
+              GtkWidget *proxy)
 {
-  gtk_widget_set_sensitive (proxy, gtk_action_is_sensitive (action));
+  action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
+
+  g_object_ref_sink (proxy);
+
+  if (action->private_data->action_group)
+    _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
+
 }
 
 static void
-gtk_action_sync_property (GtkAction  *action, 
-                         GParamSpec *pspec,
-                         GtkWidget  *proxy)
+disconnect_proxy (GtkAction *action,
+                 GtkWidget *proxy)
 {
-  const gchar *property;
-  GValue value = { 0, };
-
-  property = g_param_spec_get_name (pspec);
-
-  g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
-  g_object_get_property (G_OBJECT (action), property, &value);
+  remove_proxy (action, proxy);
 
-  g_object_set_property (G_OBJECT (proxy), property, &value);
-  g_value_unset (&value);
+  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
+ * @action: (allow-none): a #GtkAction, or %NULL to determine the action from @proxy
  * @proxy: a proxy menu item
  * @empty: whether the submenu attached to @proxy is empty
  * 
@@ -655,373 +764,26 @@ _gtk_action_sync_menu_visible (GtkAction *action,
                               GtkWidget *proxy,
                               gboolean   empty)
 {
-  gboolean visible, hide_if_empty;
+  gboolean visible = TRUE;
+  gboolean hide_if_empty = TRUE;
 
   g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
   g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
-  
-  if (action == NULL)
-    action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
-
-  visible = gtk_action_is_visible (action);
-  hide_if_empty = action->private_data->hide_if_empty;
-
-  if (visible && !(empty && hide_if_empty))
-    gtk_widget_show (proxy);
-  else
-    gtk_widget_hide (proxy);
-}
-
-gboolean _gtk_menu_is_empty (GtkWidget *menu);
-
-static void
-gtk_action_sync_visible (GtkAction  *action, 
-                        GParamSpec *pspec,
-                        GtkWidget  *proxy)
-{
-  if (GTK_IS_MENU_ITEM (proxy))
-    {
-      GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
-
-      _gtk_action_sync_menu_visible (action, proxy, _gtk_menu_is_empty (menu));
-    }
-  else
-    {
-      if (gtk_action_is_visible (action))
-       gtk_widget_show (proxy);
-      else
-       gtk_widget_hide (proxy);
-    }
-}
-
-static void
-gtk_action_sync_label (GtkAction  *action, 
-                      GParamSpec *pspec, 
-                      GtkWidget  *proxy)
-{
-  GtkWidget *label = NULL;
-
-  g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
-  label = GTK_BIN (proxy)->child;
-
-  if (GTK_IS_LABEL (label))
-    gtk_label_set_label (GTK_LABEL (label), action->private_data->label);
-}
-
-static void
-gtk_action_sync_short_label (GtkAction  *action, 
-                            GParamSpec *pspec,
-                            GtkWidget  *proxy)
-{
-  GValue value = { 0, };
-
-  g_value_init (&value, G_TYPE_STRING);
-  g_object_get_property (G_OBJECT (action), "short-label", &value);
-
-  g_object_set_property (G_OBJECT (proxy), "label", &value);
-  g_value_unset (&value);
-}
-
-static void
-gtk_action_sync_stock_id (GtkAction  *action, 
-                         GParamSpec *pspec,
-                         GtkWidget  *proxy)
-{
-  GtkWidget *image = NULL;
-
-  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);
-    }
-}
-
-static void
-gtk_action_sync_button_stock_id (GtkAction  *action, 
-                                GParamSpec *pspec,
-                                GtkWidget  *proxy)
-{
-  g_object_set (G_OBJECT (proxy),
-                "stock-id",
-                action->private_data->stock_id,
-                NULL);
-}
-
-static void
-gtk_action_sync_tooltip (GtkAction  *action, 
-                        GParamSpec *pspec, 
-                        GtkWidget  *proxy)
-{
-  g_return_if_fail (GTK_IS_TOOL_ITEM (proxy));
-
-  if (GTK_IS_TOOLBAR (gtk_widget_get_parent (proxy)))
-    {
-      GtkToolbar *toolbar = GTK_TOOLBAR (gtk_widget_get_parent (proxy));
-      
-      gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (proxy), 
-                                toolbar->tooltips,
-                                action->private_data->tooltip,
-                                NULL);
-    }
-}
 
+  if (action == NULL)
+    action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
 
-static gboolean
-gtk_action_create_menu_proxy (GtkToolItem *tool_item, 
-                             GtkAction   *action)
-{
-  GtkWidget *menu_item;
-  
-  if (action->private_data->visible_overflown)
+  if (action)
     {
-      menu_item = gtk_action_create_menu_item (action);
-
-      g_object_ref (menu_item);
-      gtk_object_sink (GTK_OBJECT (menu_item));
-      
-      gtk_tool_item_set_proxy_menu_item (tool_item, 
-                                        "gtk-action-menu-item", menu_item);
-      g_object_unref (menu_item);
+      /* a GtkMenu for a <popup/> doesn't have to have an action */
+      visible = gtk_action_is_visible (action);
+      hide_if_empty = action->private_data->hide_if_empty;
     }
-  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_data_full (G_OBJECT (proxy), "gtk-action", 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_signal_connect (proxy, "destroy",
-                   G_CALLBACK (remove_proxy), action);
 
-  g_signal_connect_object (action, "notify::sensitive",
-                          G_CALLBACK (gtk_action_sync_sensitivity), proxy, 0);
-  gtk_widget_set_sensitive (proxy, gtk_action_is_sensitive (action));
-
-  g_signal_connect_object (action, "notify::visible",
-                          G_CALLBACK (gtk_action_sync_visible), proxy, 0);
-  if (gtk_action_is_visible (action))
+  if (visible && !(empty && hide_if_empty))
     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);
-      g_signal_connect_object (action, "notify::label",
-                              G_CALLBACK (gtk_action_sync_label), proxy, 0);
-
-      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_from_stock (NULL,
-                                               GTK_ICON_SIZE_MENU);
-             gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),
-                                            image);
-             gtk_widget_show (image);
-           }
-         gtk_image_set_from_stock (GTK_IMAGE (image),
-                                   action->private_data->stock_id, GTK_ICON_SIZE_MENU);
-         g_signal_connect_object (action, "notify::stock-id",
-                                  G_CALLBACK (gtk_action_sync_stock_id),
-                                  proxy, 0);
-       }
-
-      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))
-    {
-      GParamSpec *pspec;
-
-      /* toolbar item specific synchronisers ... */
-
-      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);
-
-      pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (action),
-                                            "tooltip");
-      gtk_action_sync_tooltip (action, pspec, proxy);
-
-      g_signal_connect_object (action, "notify::visible-horizontal",
-                              G_CALLBACK (gtk_action_sync_property), 
-                              proxy, 0);
-      g_signal_connect_object (action, "notify::visible-vertical",
-                              G_CALLBACK (gtk_action_sync_property), 
-                              proxy, 0);
-      g_signal_connect_object (action, "notify::is-important",
-                              G_CALLBACK (gtk_action_sync_property), 
-                              proxy, 0);
-      g_signal_connect_object (action, "notify::tooltip",
-                              G_CALLBACK (gtk_action_sync_tooltip), 
-                              proxy, 0);
-
-      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));
-
-      /* toolbar button specific synchronisers ... */
-      if (GTK_IS_TOOL_BUTTON (proxy))
-       {
-         g_object_set (proxy,
-                       "label", action->private_data->short_label,
-                       "use_underline", TRUE,
-                       "stock_id", action->private_data->stock_id,
-                       NULL);
-
-         g_signal_connect_object (action, "notify::short-label",
-                                  G_CALLBACK (gtk_action_sync_short_label),
-                                  proxy, 0);      
-         g_signal_connect_object (action, "notify::stock-id",
-                                  G_CALLBACK (gtk_action_sync_property), 
-                                  proxy, 0);
-         g_signal_connect_object (proxy, "clicked",
-                                  G_CALLBACK (gtk_action_activate), action,
-                                  G_CONNECT_SWAPPED);
-       }
-    }
-  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,
-                       "stock-id", action->private_data->stock_id,
-                       NULL);
-         g_signal_connect_object (action, "notify::stock-id",
-                                  G_CALLBACK (gtk_action_sync_button_stock_id),
-                                  proxy, 0);
-       }
-      else if (GTK_IS_LABEL(GTK_BIN(proxy)->child))
-       {
-         /* synchronise the label */
-         g_object_set (proxy,
-                       "label", action->private_data->short_label,
-                       "use_underline", TRUE,
-                       NULL);
-         g_signal_connect_object (action, "notify::short-label",
-                                  G_CALLBACK (gtk_action_sync_short_label),
-                                  proxy, 0);
-         
-       }
-      
-      /* 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_data (G_OBJECT (proxy), "gtk-action", NULL);
-
-  /* remove proxy from list of proxies */
-  g_signal_handlers_disconnect_by_func (proxy,
-                                       G_CALLBACK (remove_proxy),
-                                       action);
-  remove_proxy (proxy, action);
-
-  /* disconnect the activate handler */
-  g_signal_handlers_disconnect_by_func (proxy,
-                                       G_CALLBACK (gtk_action_activate),
-                                       action);
-
-  /* disconnect handlers for notify::* signals */
-  g_signal_handlers_disconnect_by_func (action,
-                                       G_CALLBACK (gtk_action_sync_sensitivity),
-                                       proxy);
-  g_signal_handlers_disconnect_by_func (action,
-                                       G_CALLBACK (gtk_action_sync_property),
-                                       proxy);
-
-  g_signal_handlers_disconnect_by_func (action,
-                               G_CALLBACK (gtk_action_sync_stock_id), proxy);
-
-  /* menu item specific synchronisers ... */
-  g_signal_handlers_disconnect_by_func (action,
-                                       G_CALLBACK (gtk_action_sync_label),
-                                       proxy);
-  
-  /* toolbar button specific synchronisers ... */
-  g_signal_handlers_disconnect_by_func (action,
-                                       G_CALLBACK (gtk_action_sync_short_label),
-                                       proxy);
-
-  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
@@ -1029,18 +791,20 @@ _gtk_action_emit_activate (GtkAction *action)
 {
   GtkActionGroup *group = action->private_data->action_group;
 
-  if (group != NULL) 
+  if (group != NULL)
     {
+      g_object_ref (action);
       g_object_ref (group);
       _gtk_action_group_emit_pre_activate (group, action);
     }
 
-    g_signal_emit (action, action_signals[ACTIVATE], 0);
+  g_signal_emit (action, action_signals[ACTIVATE], 0);
 
-  if (group != NULL) 
+  if (group != NULL)
     {
       _gtk_action_group_emit_post_activate (group, action);
       g_object_unref (group);
+      g_object_unref (action);
     }
 }
 
@@ -1061,19 +825,59 @@ gtk_action_activate (GtkAction *action)
 {
   g_return_if_fail (GTK_IS_ACTION (action));
   
+  if (action->private_data->activate_blocked)
+    return;
+
   if (gtk_action_is_sensitive (action))
     _gtk_action_emit_activate (action);
 }
 
+/**
+ * gtk_action_block_activate:
+ * @action: a #GtkAction
+ *
+ * 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).
+ *
+ * Since: 2.16
+ */
+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:
+ * @action: a #GtkAction
+ *
+ * Reenable activation signals from the action 
+ *
+ * Since: 2.16
+ */
+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.
+ * @icon_size: (type int): the size of the icon that should be created.
  *
  * This function is intended for use by action implementations to
  * create icons displayed in the proxy widgets.
  *
- * Returns: a widget that displays the icon for this action.
+ * Returns: (transfer none): a widget that displays the icon for this action.
  *
  * Since: 2.4
  */
@@ -1082,8 +886,13 @@ gtk_action_create_icon (GtkAction *action, GtkIconSize icon_size)
 {
   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
 
-  if (action->private_data->stock_id)
+  if (action->private_data->stock_id &&
+      gtk_icon_factory_lookup_default (action->private_data->stock_id))
     return gtk_image_new_from_stock (action->private_data->stock_id, icon_size);
+  else if (action->private_data->gicon)
+    return gtk_image_new_from_gicon (action->private_data->gicon, icon_size);
+  else if (action->private_data->icon_name)
+    return gtk_image_new_from_icon_name (action->private_data->icon_name, icon_size);
   else
     return NULL;
 }
@@ -1094,7 +903,7 @@ gtk_action_create_icon (GtkAction *action, GtkIconSize icon_size)
  *
  * Creates a menu item widget that proxies for the given action.
  *
- * Returns: a menu item connected to the action.
+ * Returns: (transfer none): a menu item connected to the action.
  *
  * Since: 2.4
  */
@@ -1105,9 +914,10 @@ gtk_action_create_menu_item (GtkAction *action)
 
   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
 
-  menu_item = (* GTK_ACTION_GET_CLASS (action)->create_menu_item) (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;
 }
@@ -1118,7 +928,7 @@ gtk_action_create_menu_item (GtkAction *action)
  *
  * Creates a toolbar item widget that proxies for the given action.
  *
- * Returns: a toolbar item connected to the action.
+ * Returns: (transfer none): a toolbar item connected to the action.
  *
  * Since: 2.4
  */
@@ -1129,65 +939,32 @@ gtk_action_create_tool_item (GtkAction *action)
 
   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
 
-  button = (* GTK_ACTION_GET_CLASS (action)->create_tool_item) (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;
 }
 
-/**
- * gtk_action_connect_proxy:
- * @action: the action object
- * @proxy: the proxy widget
- *
- * Connects a widget to an action object as a proxy.  Synchronises 
- * various properties of the action with the widget (such as label 
- * text, icon, tooltip, etc), and attaches a callback so that the 
- * action gets activated when the proxy widget does.
- *
- * If the widget is already connected to an action, it is disconnected
- * first.
- *
- * Since: 2.4
- */
 void
-gtk_action_connect_proxy (GtkAction *action,
-                         GtkWidget *proxy)
+_gtk_action_add_to_proxy_list (GtkAction     *action,
+                              GtkWidget     *proxy)
 {
-  GtkAction *prev_action;
-
   g_return_if_fail (GTK_IS_ACTION (action));
   g_return_if_fail (GTK_IS_WIDGET (proxy));
-
-  prev_action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
-
-  if (prev_action)
-    (* GTK_ACTION_GET_CLASS (action)->disconnect_proxy) (prev_action, proxy);  
-
-  (* GTK_ACTION_GET_CLASS (action)->connect_proxy) (action, proxy);
+  GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
 }
 
-/**
- * gtk_action_disconnect_proxy:
- * @action: the action object
- * @proxy: the proxy widget
- *
- * Disconnects a proxy widget from an action.  
- * Does <emphasis>not</emphasis> destroy the widget, however.
- *
- * Since: 2.4
- */
 void
-gtk_action_disconnect_proxy (GtkAction *action,
-                            GtkWidget *proxy)
+_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));
 
-  g_return_if_fail (g_object_get_data (G_OBJECT (proxy), "gtk-action") == action);
-
-  (* GTK_ACTION_GET_CLASS (action)->disconnect_proxy) (action, proxy);  
+  GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
 }
 
 /**
@@ -1195,9 +972,10 @@ gtk_action_disconnect_proxy (GtkAction *action,
  * @action: the action object
  * 
  * Returns the proxy widgets for an action.
- * 
- * Return value: a #GSList of proxy widgets. The list is owned by the action and
- * must not be modified.
+ * See also gtk_activatable_get_related_action().
+ *
+ * Return value: (element-type GtkWidget) (transfer none): a #GSList of proxy widgets. The list is owned by GTK+
+ * and must not be modified.
  *
  * Since: 2.4
  **/
@@ -1209,7 +987,6 @@ gtk_action_get_proxies (GtkAction *action)
   return action->private_data->proxies;
 }
 
-
 /**
  * gtk_action_get_name:
  * @action: the action object
@@ -1221,7 +998,7 @@ gtk_action_get_proxies (GtkAction *action)
  *
  * Since: 2.4
  **/
-G_CONST_RETURN gchar *
+const gchar *
 gtk_action_get_name (GtkAction *action)
 {
   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
@@ -1370,51 +1147,482 @@ gtk_action_set_visible (GtkAction *action,
       g_object_notify (G_OBJECT (action), "visible");
     }
 }
-
 /**
- * gtk_action_block_activate_from:
+ * gtk_action_set_is_important:
  * @action: the action object
- * @proxy: a proxy widget
+ * @is_important: %TRUE to make the action important
  *
- * Disables calls to the gtk_action_activate()
- * function by signals on the given proxy widget.  This is used to
- * break notification loops for things like check or radio actions.
+ * Sets whether the action is important, this attribute is used
+ * primarily by toolbar items to decide whether to show a label
+ * or not.
  *
- * This function is intended for use by action implementations.
+ * Since: 2.16
+ */
+void 
+gtk_action_set_is_important (GtkAction *action,
+                            gboolean   is_important)
+{
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  is_important = is_important != FALSE;
+  
+  if (action->private_data->is_important != is_important)
+    {
+      action->private_data->is_important = is_important;
+      
+      g_object_notify (G_OBJECT (action), "is-important");
+    }  
+}
+
+/**
+ * gtk_action_get_is_important:
+ * @action: a #GtkAction
+ *
+ * Checks whether @action is important or not
  * 
- * Since: 2.4
+ * Returns: whether @action is important
+ *
+ * Since: 2.16
+ */
+gboolean 
+gtk_action_get_is_important (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->is_important;
+}
+
+/**
+ * gtk_action_set_always_show_image:
+ * @action: a #GtkAction
+ * @always_show: %TRUE if menuitem proxies should always show their image
+ *
+ * Sets whether @action<!-- -->'s menu item proxies will ignore the
+ * #GtkSettings:gtk-menu-images setting and always show their image, if available.
+ *
+ * Use this if the menu item would be useless or hard to use
+ * without their image.
+ *
+ * Since: 2.20
  */
 void
-gtk_action_block_activate_from (GtkAction *action, 
-                               GtkWidget *proxy)
+gtk_action_set_always_show_image (GtkAction *action,
+                                  gboolean   always_show)
 {
+  GtkActionPrivate *priv;
+
   g_return_if_fail (GTK_IS_ACTION (action));
+
+  priv = action->private_data;
+
+  always_show = always_show != FALSE;
   
-  g_signal_handlers_block_by_func (proxy, G_CALLBACK (gtk_action_activate),
-                                  action);
+  if (priv->always_show_image != always_show)
+    {
+      priv->always_show_image = always_show;
+
+      g_object_notify (G_OBJECT (action), "always-show-image");
+    }
 }
 
 /**
- * gtk_action_unblock_activate_from:
- * @action: the action object
- * @proxy: a proxy widget
+ * gtk_action_get_always_show_image:
+ * @action: a #GtkAction
+ *
+ * Returns whether @action<!-- -->'s menu item proxies will ignore the
+ * #GtkSettings:gtk-menu-images setting and always show their image,
+ * if available.
+ *
+ * Returns: %TRUE if the menu item proxies will always show their image
+ *
+ * Since: 2.20
+ */
+gboolean
+gtk_action_get_always_show_image  (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->always_show_image;
+}
+
+/**
+ * gtk_action_set_label:
+ * @action: a #GtkAction
+ * @label: the label text to set
+ *
+ * Sets the label of @action.
  *
- * Re-enables calls to the gtk_action_activate()
- * function by signals on the given proxy widget.  This undoes the
- * blocking done by gtk_action_block_activate_from().
+ * Since: 2.16
+ */
+void 
+gtk_action_set_label (GtkAction          *action,
+                     const gchar *label)
+{
+  gchar *tmp;
+  
+  g_return_if_fail (GTK_IS_ACTION (action));
+  
+  tmp = action->private_data->label;
+  action->private_data->label = g_strdup (label);
+  g_free (tmp);
+  action->private_data->label_set = (action->private_data->label != NULL);
+  /* if label is unset, then use the label from the stock item */
+  if (!action->private_data->label_set && action->private_data->stock_id)
+    {
+      GtkStockItem stock_item;
+      
+      if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
+       action->private_data->label = g_strdup (stock_item.label);
+    }
+
+  g_object_notify (G_OBJECT (action), "label");
+  
+  /* if short_label is unset, set short_label=label */
+  if (!action->private_data->short_label_set)
+    {
+      gtk_action_set_short_label (action, action->private_data->label);
+      action->private_data->short_label_set = FALSE;
+    }
+}
+
+/**
+ * gtk_action_get_label:
+ * @action: a #GtkAction
+ *
+ * Gets the label text of @action.
+ *
+ * Returns: the label text
+ *
+ * Since: 2.16
+ */
+const gchar *
+gtk_action_get_label (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->label;
+}
+
+/**
+ * gtk_action_set_short_label:
+ * @action: a #GtkAction
+ * @short_label: the label text to set
+ *
+ * Sets a shorter label text on @action.
  *
- * This function is intended for use by action implementations.
+ * Since: 2.16
+ */
+void 
+gtk_action_set_short_label (GtkAction   *action,
+                           const gchar *short_label)
+{
+  gchar *tmp;
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  tmp = action->private_data->short_label;
+  action->private_data->short_label = g_strdup (short_label);
+  g_free (tmp);
+  action->private_data->short_label_set = (action->private_data->short_label != NULL);
+  /* if short_label is unset, then use the value of label */
+  if (!action->private_data->short_label_set)
+    action->private_data->short_label = g_strdup (action->private_data->label);
+
+  g_object_notify (G_OBJECT (action), "short-label");
+}
+
+/**
+ * gtk_action_get_short_label:
+ * @action: a #GtkAction
+ *
+ * Gets the short label text of @action.
+ *
+ * Returns: the short label text.
+ *
+ * Since: 2.16
+ */
+const gchar *
+gtk_action_get_short_label (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->short_label;
+}
+
+/**
+ * gtk_action_set_visible_horizontal:
+ * @action: a #GtkAction
+ * @visible_horizontal: whether the action is visible horizontally
+ *
+ * Sets whether @action is visible when horizontal
+ *
+ * Since: 2.16
+ */
+void 
+gtk_action_set_visible_horizontal (GtkAction *action,
+                                  gboolean   visible_horizontal)
+{
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  visible_horizontal = visible_horizontal != FALSE;
+  
+  if (action->private_data->visible_horizontal != visible_horizontal)
+    {
+      action->private_data->visible_horizontal = visible_horizontal;
+      
+      g_object_notify (G_OBJECT (action), "visible-horizontal");
+    }  
+}
+
+/**
+ * gtk_action_get_visible_horizontal:
+ * @action: a #GtkAction
+ *
+ * Checks whether @action is visible when horizontal
  * 
- * Since: 2.4
+ * Returns: whether @action is visible when horizontal
+ *
+ * Since: 2.16
+ */
+gboolean 
+gtk_action_get_visible_horizontal (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->visible_horizontal;
+}
+
+/**
+ * gtk_action_set_visible_vertical:
+ * @action: a #GtkAction
+ * @visible_vertical: whether the action is visible vertically
+ *
+ * Sets whether @action is visible when vertical 
+ *
+ * Since: 2.16
+ */
+void 
+gtk_action_set_visible_vertical (GtkAction *action,
+                                gboolean   visible_vertical)
+{
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  visible_vertical = visible_vertical != FALSE;
+  
+  if (action->private_data->visible_vertical != visible_vertical)
+    {
+      action->private_data->visible_vertical = visible_vertical;
+      
+      g_object_notify (G_OBJECT (action), "visible-vertical");
+    }  
+}
+
+/**
+ * gtk_action_get_visible_vertical:
+ * @action: a #GtkAction
+ *
+ * Checks whether @action is visible when horizontal
+ * 
+ * Returns: whether @action is visible when horizontal
+ *
+ * Since: 2.16
+ */
+gboolean 
+gtk_action_get_visible_vertical (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->visible_vertical;
+}
+
+/**
+ * gtk_action_set_tooltip:
+ * @action: a #GtkAction
+ * @tooltip: the tooltip text
+ *
+ * Sets the tooltip text on @action
+ *
+ * Since: 2.16
+ */
+void 
+gtk_action_set_tooltip (GtkAction   *action,
+                       const gchar *tooltip)
+{
+  gchar *tmp;
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  tmp = action->private_data->tooltip;
+  action->private_data->tooltip = g_strdup (tooltip);
+  g_free (tmp);
+
+  g_object_notify (G_OBJECT (action), "tooltip");
+}
+
+/**
+ * gtk_action_get_tooltip:
+ * @action: a #GtkAction
+ *
+ * Gets the tooltip text of @action.
+ *
+ * Returns: the tooltip text
+ *
+ * Since: 2.16
+ */
+const gchar *
+gtk_action_get_tooltip (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->tooltip;
+}
+
+/**
+ * gtk_action_set_stock_id:
+ * @action: a #GtkAction
+ * @stock_id: the stock id
+ *
+ * Sets the stock id on @action
+ *
+ * Since: 2.16
+ */
+void 
+gtk_action_set_stock_id (GtkAction   *action,
+                        const gchar *stock_id)
+{
+  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);
+
+  g_object_notify (G_OBJECT (action), "stock-id");
+  
+  /* update label and short_label if appropriate */
+  if (!action->private_data->label_set)
+    {
+      GtkStockItem stock_item;
+      
+      if (action->private_data->stock_id &&
+         gtk_stock_lookup (action->private_data->stock_id, &stock_item))
+       gtk_action_set_label (action, stock_item.label);
+      else 
+       gtk_action_set_label (action, NULL);
+      
+      action->private_data->label_set = FALSE;
+    }
+}
+
+/**
+ * gtk_action_get_stock_id:
+ * @action: a #GtkAction
+ *
+ * Gets the stock id of @action.
+ *
+ * Returns: the stock id
+ *
+ * Since: 2.16
+ */
+const gchar *
+gtk_action_get_stock_id (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->stock_id;
+}
+
+/**
+ * gtk_action_set_icon_name:
+ * @action: a #GtkAction
+ * @icon_name: the icon name to set
+ *
+ * Sets the icon name on @action
+ *
+ * Since: 2.16
+ */
+void 
+gtk_action_set_icon_name (GtkAction   *action,
+                         const gchar *icon_name)
+{
+  gchar *tmp;
+
+  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);
+
+  g_object_notify (G_OBJECT (action), "icon-name");
+}
+
+/**
+ * gtk_action_get_icon_name:
+ * @action: a #GtkAction
+ *
+ * Gets the icon name of @action.
+ *
+ * Returns: the icon name
+ *
+ * Since: 2.16
+ */
+const gchar *
+gtk_action_get_icon_name (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->icon_name;
+}
+
+/**
+ * gtk_action_set_gicon:
+ * @action: a #GtkAction
+ * @icon: the #GIcon to set
+ *
+ * Sets the icon of @action.
+ *
+ * Since: 2.16
  */
 void
-gtk_action_unblock_activate_from (GtkAction *action, 
-                                 GtkWidget *proxy)
+gtk_action_set_gicon (GtkAction *action,
+                      GIcon     *icon)
 {
   g_return_if_fail (GTK_IS_ACTION (action));
 
-  g_signal_handlers_unblock_by_func (proxy, G_CALLBACK (gtk_action_activate),
-                                    action);
+  if (action->private_data->gicon)
+    g_object_unref (action->private_data->gicon);
+
+  action->private_data->gicon = icon;
+
+  if (action->private_data->gicon)
+    g_object_ref (action->private_data->gicon);
+
+  g_object_notify (G_OBJECT (action), "gicon");
+}
+
+/**
+ * gtk_action_get_gicon:
+ * @action: a #GtkAction
+ *
+ * Gets the gicon of @action.
+ *
+ * Returns: (transfer none): The action's #GIcon if one is set.
+ *
+ * Since: 2.16
+ */
+GIcon *
+gtk_action_get_gicon (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->gicon;
 }
 
 static void
@@ -1438,8 +1646,6 @@ static void
 gtk_action_set_action_group (GtkAction     *action,
                             GtkActionGroup *action_group)
 {
-  g_return_if_fail (GTK_IS_ACTION (action));
-
   if (action->private_data->action_group == NULL)
     g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
   else
@@ -1457,6 +1663,10 @@ gtk_action_set_action_group (GtkAction       *action,
  * with the action will have this accel path, so that their
  * accelerators are consistent.
  *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with 
+ * g_intern_static_string().
+ *
  * Since: 2.4
  */
 void
@@ -1477,10 +1687,10 @@ gtk_action_set_accel_path (GtkAction   *action,
  * Since: 2.6
  *
  * Returns: the accel path for this action, or %NULL
- *   if none is set. The returned string is owned by GTK+
+ *   if none is set. The returned string is owned by GTK+ 
  *   and must not be freed or modified.
  */
-G_CONST_RETURN gchar *
+const gchar *
 gtk_action_get_accel_path (GtkAction *action)
 {
   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
@@ -1499,8 +1709,9 @@ gtk_action_get_accel_path (GtkAction *action)
  *
  * Since: 2.8
  *
- * Returns: the accel closure for this action. The returned closure is
- *          owned by GTK+ must and not be unrefed or modified.
+ * Returns: (transfer none): the accel closure for this action. The
+ *          returned closure is owned by GTK+ and must not be unreffed
+ *          or modified.
  */
 GClosure *
 gtk_action_get_accel_closure (GtkAction *action)
@@ -1514,8 +1725,8 @@ gtk_action_get_accel_closure (GtkAction *action)
 /**
  * gtk_action_set_accel_group:
  * @action: the action object
- * @accel_group: a #GtkAccelGroup or %NULL
- * 
+ * @accel_group: (allow-none): a #GtkAccelGroup or %NULL
+ *
  * Sets the #GtkAccelGroup in which the accelerator for this action
  * will be installed.
  *
@@ -1597,5 +1808,26 @@ gtk_action_disconnect_accelerator (GtkAction *action)
                                action->private_data->accel_closure);
 }
 
-#define __GTK_ACTION_C__
-#include "gtkaliasdef.c"
+/**
+ * gtk_action_create_menu:
+ * @action: a #GtkAction
+ *
+ * If @action provides a #GtkMenu widget as a submenu for the menu
+ * item or the toolbar item it creates, this function returns an
+ * instance of that menu.
+ *
+ * Return value: (transfer none): the menu item provided by the
+ *               action, or %NULL.
+ *
+ * Since: 2.12
+ */
+GtkWidget *
+gtk_action_create_menu (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  if (GTK_ACTION_GET_CLASS (action)->create_menu)
+    return GTK_ACTION_GET_CLASS (action)->create_menu (action);
+
+  return NULL;
+}