]> Pileus Git - ~andy/gtk/blob - gtk/gtkaction.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkaction.c
1 /*
2  * GTK - The GIMP Toolkit
3  * Copyright (C) 1998, 1999 Red Hat, Inc.
4  * All rights reserved.
5  *
6  * This Library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * Author: James Henstridge <james@daa.com.au>
22  *
23  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
24  * file for a list of people on the GTK+ Team.  See the ChangeLog
25  * files for a list of changes.  These files are distributed with
26  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
27  */
28
29 /**
30  * SECTION:gtkaction
31  * @Short_description: An action which can be triggered by a menu or toolbar item
32  * @Title: GtkAction
33  * @See_also: #GtkActionGroup, #GtkUIManager, #GtkActivatable
34  *
35  * Actions represent operations that the user can be perform, along with
36  * some information how it should be presented in the interface. Each action
37  * provides methods to create icons, menu items and toolbar items
38  * representing itself.
39  *
40  * As well as the callback that is called when the action gets activated,
41  * the following also gets associated with the action:
42  * <itemizedlist>
43  *   <listitem><para>a name (not translated, for path lookup)</para></listitem>
44  *   <listitem><para>a label (translated, for display)</para></listitem>
45  *   <listitem><para>an accelerator</para></listitem>
46  *   <listitem><para>whether label indicates a stock id</para></listitem>
47  *   <listitem><para>a tooltip (optional, translated)</para></listitem>
48  *   <listitem><para>a toolbar label (optional, shorter than label)</para></listitem>
49  * </itemizedlist>
50  * The action will also have some state information:
51  * <itemizedlist>
52  *   <listitem><para>visible (shown/hidden)</para></listitem>
53  *   <listitem><para>sensitive (enabled/disabled)</para></listitem>
54  * </itemizedlist>
55  * Apart from regular actions, there are <link linkend="GtkToggleAction">toggle
56  * actions</link>, which can be toggled between two states and <link
57  * linkend="GtkRadioAction">radio actions</link>, of which only one in a group
58  * can be in the "active" state. Other actions can be implemented as #GtkAction
59  * subclasses.
60  *
61  * Each action can have one or more proxy widgets. To act as an action proxy,
62  * widget needs to implement #GtkActivatable interface. Proxies mirror the state
63  * of the action and should change when the action's state changes. Properties
64  * that are always mirrored by proxies are #GtkAction:sensitive and
65  * #GtkAction:visible. #GtkAction:gicon, #GtkAction:icon-name, #GtkAction:label,
66  * #GtkAction:short-label and #GtkAction:stock-id properties are only mirorred
67  * if proxy widget has #GtkActivatable:use-action-appearance property set to
68  * %TRUE.
69  *
70  * When the proxy is activated, it should activate its action.
71  */
72
73 #include "config.h"
74
75 #include "gtkaction.h"
76 #include "gtkactiongroup.h"
77 #include "gtkaccellabel.h"
78 #include "gtkbutton.h"
79 #include "gtkiconfactory.h"
80 #include "gtkimage.h"
81 #include "gtkimagemenuitem.h"
82 #include "gtkintl.h"
83 #include "gtklabel.h"
84 #include "gtkmarshalers.h"
85 #include "gtkmenuitem.h"
86 #include "gtkstock.h"
87 #include "deprecated/gtktearoffmenuitem.h"
88 #include "gtktoolbutton.h"
89 #include "gtktoolbar.h"
90 #include "gtkprivate.h"
91 #include "gtkbuildable.h"
92 #include "gtkactivatable.h"
93
94
95 struct _GtkActionPrivate 
96 {
97   const gchar *name; /* interned */
98   gchar *label;
99   gchar *short_label;
100   gchar *tooltip;
101   gchar *stock_id; /* stock icon */
102   gchar *icon_name; /* themed icon */
103   GIcon *gicon;
104
105   guint sensitive          : 1;
106   guint visible            : 1;
107   guint label_set          : 1; /* these two used so we can set label */
108   guint short_label_set    : 1; /* based on stock id */
109   guint visible_horizontal : 1;
110   guint visible_vertical   : 1;
111   guint is_important       : 1;
112   guint hide_if_empty      : 1;
113   guint visible_overflown  : 1;
114   guint always_show_image  : 1;
115   guint recursion_guard    : 1;
116   guint activate_blocked   : 1;
117
118   /* accelerator */
119   guint          accel_count;
120   GtkAccelGroup *accel_group;
121   GClosure      *accel_closure;
122   GQuark         accel_quark;
123
124   GtkActionGroup *action_group;
125
126   /* list of proxy widgets */
127   GSList *proxies;
128 };
129
130 enum 
131 {
132   ACTIVATE,
133   LAST_SIGNAL
134 };
135
136 enum 
137 {
138   PROP_0,
139   PROP_NAME,
140   PROP_LABEL,
141   PROP_SHORT_LABEL,
142   PROP_TOOLTIP,
143   PROP_STOCK_ID,
144   PROP_ICON_NAME,
145   PROP_GICON,
146   PROP_VISIBLE_HORIZONTAL,
147   PROP_VISIBLE_VERTICAL,
148   PROP_VISIBLE_OVERFLOWN,
149   PROP_IS_IMPORTANT,
150   PROP_HIDE_IF_EMPTY,
151   PROP_SENSITIVE,
152   PROP_VISIBLE,
153   PROP_ACTION_GROUP,
154   PROP_ALWAYS_SHOW_IMAGE
155 };
156
157 /* GtkBuildable */
158 static void gtk_action_buildable_init             (GtkBuildableIface *iface);
159 static void gtk_action_buildable_set_name         (GtkBuildable *buildable,
160                                                    const gchar  *name);
161 static const gchar* gtk_action_buildable_get_name (GtkBuildable *buildable);
162
163 G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
164                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
165                                                 gtk_action_buildable_init))
166
167 static void gtk_action_finalize     (GObject *object);
168 static void gtk_action_set_property (GObject         *object,
169                                      guint            prop_id,
170                                      const GValue    *value,
171                                      GParamSpec      *pspec);
172 static void gtk_action_get_property (GObject         *object,
173                                      guint            prop_id,
174                                      GValue          *value,
175                                      GParamSpec      *pspec);
176 static void gtk_action_set_action_group (GtkAction      *action,
177                                          GtkActionGroup *action_group);
178
179 static GtkWidget *create_menu_item    (GtkAction *action);
180 static GtkWidget *create_tool_item    (GtkAction *action);
181 static void       connect_proxy       (GtkAction *action,
182                                        GtkWidget *proxy);
183 static void       disconnect_proxy    (GtkAction *action,
184                                        GtkWidget *proxy);
185  
186 static void       closure_accel_activate (GClosure     *closure,
187                                           GValue       *return_value,
188                                           guint         n_param_values,
189                                           const GValue *param_values,
190                                           gpointer      invocation_hint,
191                                           gpointer      marshal_data);
192
193 static guint         action_signals[LAST_SIGNAL] = { 0 };
194
195
196 static void
197 gtk_action_class_init (GtkActionClass *klass)
198 {
199   GObjectClass *gobject_class;
200
201   gobject_class = G_OBJECT_CLASS (klass);
202
203   gobject_class->finalize     = gtk_action_finalize;
204   gobject_class->set_property = gtk_action_set_property;
205   gobject_class->get_property = gtk_action_get_property;
206
207   klass->activate = NULL;
208
209   klass->create_menu_item  = create_menu_item;
210   klass->create_tool_item  = create_tool_item;
211   klass->create_menu       = NULL;
212   klass->menu_item_type    = GTK_TYPE_IMAGE_MENU_ITEM;
213   klass->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
214   klass->connect_proxy    = connect_proxy;
215   klass->disconnect_proxy = disconnect_proxy;
216
217   g_object_class_install_property (gobject_class,
218                                    PROP_NAME,
219                                    g_param_spec_string ("name",
220                                                         P_("Name"),
221                                                         P_("A unique name for the action."),
222                                                         NULL,
223                                                         GTK_PARAM_READWRITE | 
224                                                         G_PARAM_CONSTRUCT_ONLY));
225
226   /**
227    * GtkAction:label:
228    *
229    * The label used for menu items and buttons that activate
230    * this action. If the label is %NULL, GTK+ uses the stock 
231    * label specified via the stock-id property.
232    *
233    * This is an appearance property and thus only applies if 
234    * #GtkActivatable:use-action-appearance is %TRUE.
235    */
236   g_object_class_install_property (gobject_class,
237                                    PROP_LABEL,
238                                    g_param_spec_string ("label",
239                                                         P_("Label"),
240                                                         P_("The label used for menu items and buttons "
241                                                            "that activate this action."),
242                                                         NULL,
243                                                         GTK_PARAM_READWRITE));
244
245   /**
246    * GtkAction:short-label:
247    *
248    * A shorter label that may be used on toolbar buttons.
249    *
250    * This is an appearance property and thus only applies if 
251    * #GtkActivatable:use-action-appearance is %TRUE.
252    */
253   g_object_class_install_property (gobject_class,
254                                    PROP_SHORT_LABEL,
255                                    g_param_spec_string ("short-label",
256                                                         P_("Short label"),
257                                                         P_("A shorter label that may be used on toolbar buttons."),
258                                                         NULL,
259                                                         GTK_PARAM_READWRITE));
260
261
262   g_object_class_install_property (gobject_class,
263                                    PROP_TOOLTIP,
264                                    g_param_spec_string ("tooltip",
265                                                         P_("Tooltip"),
266                                                         P_("A tooltip for this action."),
267                                                         NULL,
268                                                         GTK_PARAM_READWRITE));
269
270   /**
271    * GtkAction:stock-id:
272    *
273    * The stock icon displayed in widgets representing this action.
274    *
275    * This is an appearance property and thus only applies if 
276    * #GtkActivatable:use-action-appearance is %TRUE.
277    */
278   g_object_class_install_property (gobject_class,
279                                    PROP_STOCK_ID,
280                                    g_param_spec_string ("stock-id",
281                                                         P_("Stock Icon"),
282                                                         P_("The stock icon displayed in widgets representing "
283                                                            "this action."),
284                                                         NULL,
285                                                         GTK_PARAM_READWRITE));
286   /**
287    * GtkAction:gicon:
288    *
289    * The #GIcon displayed in the #GtkAction.
290    *
291    * Note that the stock icon is preferred, if the #GtkAction:stock-id 
292    * property holds the id of an existing stock icon.
293    *
294    * This is an appearance property and thus only applies if 
295    * #GtkActivatable:use-action-appearance is %TRUE.
296    *
297    * Since: 2.16
298    */
299   g_object_class_install_property (gobject_class,
300                                    PROP_GICON,
301                                    g_param_spec_object ("gicon",
302                                                         P_("GIcon"),
303                                                         P_("The GIcon being displayed"),
304                                                         G_TYPE_ICON,
305                                                         GTK_PARAM_READWRITE));                                                  
306   /**
307    * GtkAction:icon-name:
308    *
309    * The name of the icon from the icon theme. 
310    * 
311    * Note that the stock icon is preferred, if the #GtkAction:stock-id 
312    * property holds the id of an existing stock icon, and the #GIcon is
313    * preferred if the #GtkAction:gicon property is set. 
314    *
315    * This is an appearance property and thus only applies if 
316    * #GtkActivatable:use-action-appearance is %TRUE.
317    *
318    * Since: 2.10
319    */
320   g_object_class_install_property (gobject_class,
321                                    PROP_ICON_NAME,
322                                    g_param_spec_string ("icon-name",
323                                                         P_("Icon Name"),
324                                                         P_("The name of the icon from the icon theme"),
325                                                         NULL,
326                                                         GTK_PARAM_READWRITE));
327
328   g_object_class_install_property (gobject_class,
329                                    PROP_VISIBLE_HORIZONTAL,
330                                    g_param_spec_boolean ("visible-horizontal",
331                                                          P_("Visible when horizontal"),
332                                                          P_("Whether the toolbar item is visible when the toolbar "
333                                                             "is in a horizontal orientation."),
334                                                          TRUE,
335                                                          GTK_PARAM_READWRITE));
336   /**
337    * GtkAction:visible-overflown:
338    *
339    * When %TRUE, toolitem proxies for this action are represented in the 
340    * toolbar overflow menu.
341    *
342    * Since: 2.6
343    */
344   g_object_class_install_property (gobject_class,
345                                    PROP_VISIBLE_OVERFLOWN,
346                                    g_param_spec_boolean ("visible-overflown",
347                                                          P_("Visible when overflown"),
348                                                          P_("When TRUE, toolitem proxies for this action "
349                                                             "are represented in the toolbar overflow menu."),
350                                                          TRUE,
351                                                          GTK_PARAM_READWRITE));
352   g_object_class_install_property (gobject_class,
353                                    PROP_VISIBLE_VERTICAL,
354                                    g_param_spec_boolean ("visible-vertical",
355                                                          P_("Visible when vertical"),
356                                                          P_("Whether the toolbar item is visible when the toolbar "
357                                                             "is in a vertical orientation."),
358                                                          TRUE,
359                                                          GTK_PARAM_READWRITE));
360   g_object_class_install_property (gobject_class,
361                                    PROP_IS_IMPORTANT,
362                                    g_param_spec_boolean ("is-important",
363                                                          P_("Is important"),
364                                                          P_("Whether the action is considered important. "
365                                                             "When TRUE, toolitem proxies for this action "
366                                                             "show text in GTK_TOOLBAR_BOTH_HORIZ mode."),
367                                                          FALSE,
368                                                          GTK_PARAM_READWRITE));
369   g_object_class_install_property (gobject_class,
370                                    PROP_HIDE_IF_EMPTY,
371                                    g_param_spec_boolean ("hide-if-empty",
372                                                          P_("Hide if empty"),
373                                                          P_("When TRUE, empty menu proxies for this action are hidden."),
374                                                          TRUE,
375                                                          GTK_PARAM_READWRITE));
376   g_object_class_install_property (gobject_class,
377                                    PROP_SENSITIVE,
378                                    g_param_spec_boolean ("sensitive",
379                                                          P_("Sensitive"),
380                                                          P_("Whether the action is enabled."),
381                                                          TRUE,
382                                                          GTK_PARAM_READWRITE));
383   g_object_class_install_property (gobject_class,
384                                    PROP_VISIBLE,
385                                    g_param_spec_boolean ("visible",
386                                                          P_("Visible"),
387                                                          P_("Whether the action is visible."),
388                                                          TRUE,
389                                                          GTK_PARAM_READWRITE));
390   g_object_class_install_property (gobject_class,
391                                    PROP_ACTION_GROUP,
392                                    g_param_spec_object ("action-group",
393                                                          P_("Action Group"),
394                                                          P_("The GtkActionGroup this GtkAction is associated with, or NULL (for internal use)."),
395                                                          GTK_TYPE_ACTION_GROUP,
396                                                          GTK_PARAM_READWRITE));
397
398   /**
399    * GtkAction:always-show-image:
400    *
401    * If %TRUE, the action's menu item proxies will ignore the #GtkSettings:gtk-menu-images 
402    * setting and always show their image, if available.
403    *
404    * Use this property if the menu item would be useless or hard to use
405    * without their image. 
406    *
407    * Since: 2.20
408    **/
409   g_object_class_install_property (gobject_class,
410                                    PROP_ALWAYS_SHOW_IMAGE,
411                                    g_param_spec_boolean ("always-show-image",
412                                                          P_("Always show image"),
413                                                          P_("Whether the image will always be shown"),
414                                                          FALSE,
415                                                          GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
416
417   /**
418    * GtkAction::activate:
419    * @action: the #GtkAction
420    *
421    * The "activate" signal is emitted when the action is activated.
422    *
423    * Since: 2.4
424    */
425   action_signals[ACTIVATE] =
426     g_signal_new (I_("activate"),
427                   G_OBJECT_CLASS_TYPE (klass),
428                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
429                   G_STRUCT_OFFSET (GtkActionClass, activate),  NULL, NULL,
430                   g_cclosure_marshal_VOID__VOID,
431                   G_TYPE_NONE, 0);
432
433   g_type_class_add_private (gobject_class, sizeof (GtkActionPrivate));
434 }
435
436
437 static void
438 gtk_action_init (GtkAction *action)
439 {
440   action->private_data = G_TYPE_INSTANCE_GET_PRIVATE (action,
441                                                       GTK_TYPE_ACTION,
442                                                       GtkActionPrivate);
443
444   action->private_data->name = NULL;
445   action->private_data->label = NULL;
446   action->private_data->short_label = NULL;
447   action->private_data->tooltip = NULL;
448   action->private_data->stock_id = NULL;
449   action->private_data->icon_name = NULL;
450   action->private_data->visible_horizontal = TRUE;
451   action->private_data->visible_vertical   = TRUE;
452   action->private_data->visible_overflown  = TRUE;
453   action->private_data->is_important = FALSE;
454   action->private_data->hide_if_empty = TRUE;
455   action->private_data->always_show_image = FALSE;
456   action->private_data->activate_blocked = FALSE;
457
458   action->private_data->sensitive = TRUE;
459   action->private_data->visible = TRUE;
460
461   action->private_data->label_set = FALSE;
462   action->private_data->short_label_set = FALSE;
463
464   action->private_data->accel_count = 0;
465   action->private_data->accel_group = NULL;
466   action->private_data->accel_quark = 0;
467   action->private_data->accel_closure = 
468     g_closure_new_object (sizeof (GClosure), G_OBJECT (action));
469   g_closure_set_marshal (action->private_data->accel_closure, 
470                          closure_accel_activate);
471   g_closure_ref (action->private_data->accel_closure);
472   g_closure_sink (action->private_data->accel_closure);
473
474   action->private_data->action_group = NULL;
475
476   action->private_data->proxies = NULL;
477   action->private_data->gicon = NULL;  
478 }
479
480 static void
481 gtk_action_buildable_init (GtkBuildableIface *iface)
482 {
483   iface->set_name = gtk_action_buildable_set_name;
484   iface->get_name = gtk_action_buildable_get_name;
485 }
486
487 static void
488 gtk_action_buildable_set_name (GtkBuildable *buildable,
489                                const gchar  *name)
490 {
491   GtkAction *action = GTK_ACTION (buildable);
492
493   action->private_data->name = g_intern_string (name);
494 }
495
496 static const gchar *
497 gtk_action_buildable_get_name (GtkBuildable *buildable)
498 {
499   GtkAction *action = GTK_ACTION (buildable);
500
501   return action->private_data->name;
502 }
503
504 /**
505  * gtk_action_new:
506  * @name: A unique name for the action
507  * @label: (allow-none): the label displayed in menu items and on buttons,
508  *         or %NULL
509  * @tooltip: (allow-none): a tooltip for the action, or %NULL
510  * @stock_id: (allow-none): the stock icon to display in widgets representing
511  *            the action, or %NULL
512  *
513  * Creates a new #GtkAction object. To add the action to a
514  * #GtkActionGroup and set the accelerator for the action,
515  * call gtk_action_group_add_action_with_accel().
516  * See <xref linkend="XML-UI"/> for information on allowed action
517  * names.
518  *
519  * Return value: a new #GtkAction
520  *
521  * Since: 2.4
522  */
523 GtkAction *
524 gtk_action_new (const gchar *name,
525                 const gchar *label,
526                 const gchar *tooltip,
527                 const gchar *stock_id)
528 {
529   g_return_val_if_fail (name != NULL, NULL);
530
531   return g_object_new (GTK_TYPE_ACTION,
532                        "name", name,
533                        "label", label,
534                        "tooltip", tooltip,
535                        "stock-id", stock_id,
536                        NULL);
537 }
538
539 static void
540 gtk_action_finalize (GObject *object)
541 {
542   GtkAction *action;
543   action = GTK_ACTION (object);
544
545   g_free (action->private_data->label);
546   g_free (action->private_data->short_label);
547   g_free (action->private_data->tooltip);
548   g_free (action->private_data->stock_id);
549   g_free (action->private_data->icon_name);
550   
551   if (action->private_data->gicon)
552     g_object_unref (action->private_data->gicon);
553
554   g_closure_unref (action->private_data->accel_closure);
555   if (action->private_data->accel_group)
556     g_object_unref (action->private_data->accel_group);
557
558   G_OBJECT_CLASS (gtk_action_parent_class)->finalize (object);  
559 }
560
561 static void
562 gtk_action_set_property (GObject         *object,
563                          guint            prop_id,
564                          const GValue    *value,
565                          GParamSpec      *pspec)
566 {
567   GtkAction *action;
568   
569   action = GTK_ACTION (object);
570
571   switch (prop_id)
572     {
573     case PROP_NAME:
574       action->private_data->name = g_intern_string (g_value_get_string (value));
575       break;
576     case PROP_LABEL:
577       gtk_action_set_label (action, g_value_get_string (value));
578       break;
579     case PROP_SHORT_LABEL:
580       gtk_action_set_short_label (action, g_value_get_string (value));
581       break;
582     case PROP_TOOLTIP:
583       gtk_action_set_tooltip (action, g_value_get_string (value));
584       break;
585     case PROP_STOCK_ID:
586       gtk_action_set_stock_id (action, g_value_get_string (value));
587       break;
588     case PROP_GICON:
589       gtk_action_set_gicon (action, g_value_get_object (value));
590       break;
591     case PROP_ICON_NAME:
592       gtk_action_set_icon_name (action, g_value_get_string (value));
593       break;
594     case PROP_VISIBLE_HORIZONTAL:
595       gtk_action_set_visible_horizontal (action, g_value_get_boolean (value));
596       break;
597     case PROP_VISIBLE_VERTICAL:
598       gtk_action_set_visible_vertical (action, g_value_get_boolean (value));
599       break;
600     case PROP_VISIBLE_OVERFLOWN:
601       action->private_data->visible_overflown = g_value_get_boolean (value);
602       break;
603     case PROP_IS_IMPORTANT:
604       gtk_action_set_is_important (action, g_value_get_boolean (value));
605       break;
606     case PROP_HIDE_IF_EMPTY:
607       action->private_data->hide_if_empty = g_value_get_boolean (value);
608       break;
609     case PROP_SENSITIVE:
610       gtk_action_set_sensitive (action, g_value_get_boolean (value));
611       break;
612     case PROP_VISIBLE:
613       gtk_action_set_visible (action, g_value_get_boolean (value));
614       break;
615     case PROP_ACTION_GROUP:
616       gtk_action_set_action_group (action, g_value_get_object (value));
617       break;
618     case PROP_ALWAYS_SHOW_IMAGE:
619       gtk_action_set_always_show_image (action, g_value_get_boolean (value));
620       break;
621     default:
622       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
623       break;
624     }
625 }
626
627 static void
628 gtk_action_get_property (GObject    *object,
629                          guint       prop_id,
630                          GValue     *value,
631                          GParamSpec *pspec)
632 {
633   GtkAction *action;
634
635   action = GTK_ACTION (object);
636
637   switch (prop_id)
638     {
639     case PROP_NAME:
640       g_value_set_static_string (value, action->private_data->name);
641       break;
642     case PROP_LABEL:
643       g_value_set_string (value, action->private_data->label);
644       break;
645     case PROP_SHORT_LABEL:
646       g_value_set_string (value, action->private_data->short_label);
647       break;
648     case PROP_TOOLTIP:
649       g_value_set_string (value, action->private_data->tooltip);
650       break;
651     case PROP_STOCK_ID:
652       g_value_set_string (value, action->private_data->stock_id);
653       break;
654     case PROP_ICON_NAME:
655       g_value_set_string (value, action->private_data->icon_name);
656       break;
657     case PROP_GICON:
658       g_value_set_object (value, action->private_data->gicon);
659       break;
660     case PROP_VISIBLE_HORIZONTAL:
661       g_value_set_boolean (value, action->private_data->visible_horizontal);
662       break;
663     case PROP_VISIBLE_VERTICAL:
664       g_value_set_boolean (value, action->private_data->visible_vertical);
665       break;
666     case PROP_VISIBLE_OVERFLOWN:
667       g_value_set_boolean (value, action->private_data->visible_overflown);
668       break;
669     case PROP_IS_IMPORTANT:
670       g_value_set_boolean (value, action->private_data->is_important);
671       break;
672     case PROP_HIDE_IF_EMPTY:
673       g_value_set_boolean (value, action->private_data->hide_if_empty);
674       break;
675     case PROP_SENSITIVE:
676       g_value_set_boolean (value, action->private_data->sensitive);
677       break;
678     case PROP_VISIBLE:
679       g_value_set_boolean (value, action->private_data->visible);
680       break;
681     case PROP_ACTION_GROUP:
682       g_value_set_object (value, action->private_data->action_group);
683       break;
684     case PROP_ALWAYS_SHOW_IMAGE:
685       g_value_set_boolean (value, action->private_data->always_show_image);
686       break;
687     default:
688       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
689       break;
690     }
691 }
692
693 static GtkWidget *
694 create_menu_item (GtkAction *action)
695 {
696   GType menu_item_type;
697
698   menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type;
699
700   return g_object_new (menu_item_type, NULL);
701 }
702
703 static GtkWidget *
704 create_tool_item (GtkAction *action)
705 {
706   GType toolbar_item_type;
707
708   toolbar_item_type = GTK_ACTION_GET_CLASS (action)->toolbar_item_type;
709
710   return g_object_new (toolbar_item_type, NULL);
711 }
712
713 static void
714 remove_proxy (GtkAction *action,
715               GtkWidget *proxy)
716 {
717   g_object_unref (proxy);
718   action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
719 }
720
721 static void
722 connect_proxy (GtkAction *action,
723                GtkWidget *proxy)
724 {
725   action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
726
727   g_object_ref_sink (proxy);
728
729   if (action->private_data->action_group)
730     _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
731
732 }
733
734 static void
735 disconnect_proxy (GtkAction *action,
736                   GtkWidget *proxy)
737 {
738   remove_proxy (action, proxy);
739
740   if (action->private_data->action_group)
741     _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
742 }
743
744 /**
745  * _gtk_action_sync_menu_visible:
746  * @action: (allow-none): a #GtkAction, or %NULL to determine the action from @proxy
747  * @proxy: a proxy menu item
748  * @empty: whether the submenu attached to @proxy is empty
749  * 
750  * Updates the visibility of @proxy from the visibility of @action
751  * according to the following rules:
752  * <itemizedlist>
753  * <listitem><para>if @action is invisible, @proxy is too
754  * </para></listitem>
755  * <listitem><para>if @empty is %TRUE, hide @proxy unless the "hide-if-empty" 
756  *   property of @action indicates otherwise
757  * </para></listitem>
758  * </itemizedlist>
759  * 
760  * This function is used in the implementation of #GtkUIManager.
761  **/
762 void
763 _gtk_action_sync_menu_visible (GtkAction *action,
764                                GtkWidget *proxy,
765                                gboolean   empty)
766 {
767   gboolean visible = TRUE;
768   gboolean hide_if_empty = TRUE;
769
770   g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
771   g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
772
773   if (action == NULL)
774     action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
775
776   if (action)
777     {
778       /* a GtkMenu for a <popup/> doesn't have to have an action */
779       visible = gtk_action_is_visible (action);
780       hide_if_empty = action->private_data->hide_if_empty;
781     }
782
783   if (visible && !(empty && hide_if_empty))
784     gtk_widget_show (proxy);
785   else
786     gtk_widget_hide (proxy);
787 }
788
789 void
790 _gtk_action_emit_activate (GtkAction *action)
791 {
792   GtkActionGroup *group = action->private_data->action_group;
793
794   if (group != NULL)
795     {
796       g_object_ref (action);
797       g_object_ref (group);
798       _gtk_action_group_emit_pre_activate (group, action);
799     }
800
801   g_signal_emit (action, action_signals[ACTIVATE], 0);
802
803   if (group != NULL)
804     {
805       _gtk_action_group_emit_post_activate (group, action);
806       g_object_unref (group);
807       g_object_unref (action);
808     }
809 }
810
811 /**
812  * gtk_action_activate:
813  * @action: the action object
814  *
815  * Emits the "activate" signal on the specified action, if it isn't 
816  * insensitive. This gets called by the proxy widgets when they get 
817  * activated.
818  *
819  * It can also be used to manually activate an action.
820  *
821  * Since: 2.4
822  */
823 void
824 gtk_action_activate (GtkAction *action)
825 {
826   g_return_if_fail (GTK_IS_ACTION (action));
827   
828   if (action->private_data->activate_blocked)
829     return;
830
831   if (gtk_action_is_sensitive (action))
832     _gtk_action_emit_activate (action);
833 }
834
835 /**
836  * gtk_action_block_activate:
837  * @action: a #GtkAction
838  *
839  * Disable activation signals from the action 
840  *
841  * This is needed when updating the state of your proxy
842  * #GtkActivatable widget could result in calling gtk_action_activate(),
843  * this is a convenience function to avoid recursing in those
844  * cases (updating toggle state for instance).
845  *
846  * Since: 2.16
847  */
848 void
849 gtk_action_block_activate (GtkAction *action)
850 {
851   g_return_if_fail (GTK_IS_ACTION (action));
852
853   action->private_data->activate_blocked = TRUE;
854 }
855
856 /**
857  * gtk_action_unblock_activate:
858  * @action: a #GtkAction
859  *
860  * Reenable activation signals from the action 
861  *
862  * Since: 2.16
863  */
864 void
865 gtk_action_unblock_activate (GtkAction *action)
866 {
867   g_return_if_fail (GTK_IS_ACTION (action));
868
869   action->private_data->activate_blocked = FALSE;
870 }
871
872 /**
873  * gtk_action_create_icon:
874  * @action: the action object
875  * @icon_size: (type int): the size of the icon that should be created.
876  *
877  * This function is intended for use by action implementations to
878  * create icons displayed in the proxy widgets.
879  *
880  * Returns: (transfer none): a widget that displays the icon for this action.
881  *
882  * Since: 2.4
883  */
884 GtkWidget *
885 gtk_action_create_icon (GtkAction *action, GtkIconSize icon_size)
886 {
887   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
888
889   if (action->private_data->stock_id &&
890       gtk_icon_factory_lookup_default (action->private_data->stock_id))
891     return gtk_image_new_from_stock (action->private_data->stock_id, icon_size);
892   else if (action->private_data->gicon)
893     return gtk_image_new_from_gicon (action->private_data->gicon, icon_size);
894   else if (action->private_data->icon_name)
895     return gtk_image_new_from_icon_name (action->private_data->icon_name, icon_size);
896   else
897     return NULL;
898 }
899
900 /**
901  * gtk_action_create_menu_item:
902  * @action: the action object
903  *
904  * Creates a menu item widget that proxies for the given action.
905  *
906  * Returns: (transfer none): a menu item connected to the action.
907  *
908  * Since: 2.4
909  */
910 GtkWidget *
911 gtk_action_create_menu_item (GtkAction *action)
912 {
913   GtkWidget *menu_item;
914
915   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
916
917   menu_item = GTK_ACTION_GET_CLASS (action)->create_menu_item (action);
918
919   gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (menu_item), TRUE);
920   gtk_activatable_set_related_action (GTK_ACTIVATABLE (menu_item), action);
921
922   return menu_item;
923 }
924
925 /**
926  * gtk_action_create_tool_item:
927  * @action: the action object
928  *
929  * Creates a toolbar item widget that proxies for the given action.
930  *
931  * Returns: (transfer none): a toolbar item connected to the action.
932  *
933  * Since: 2.4
934  */
935 GtkWidget *
936 gtk_action_create_tool_item (GtkAction *action)
937 {
938   GtkWidget *button;
939
940   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
941
942   button = GTK_ACTION_GET_CLASS (action)->create_tool_item (action);
943
944   gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (button), TRUE);
945   gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
946
947   return button;
948 }
949
950 void
951 _gtk_action_add_to_proxy_list (GtkAction     *action,
952                                GtkWidget     *proxy)
953 {
954   g_return_if_fail (GTK_IS_ACTION (action));
955   g_return_if_fail (GTK_IS_WIDGET (proxy));
956  
957   GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
958 }
959
960 void
961 _gtk_action_remove_from_proxy_list (GtkAction     *action,
962                                     GtkWidget     *proxy)
963 {
964   g_return_if_fail (GTK_IS_ACTION (action));
965   g_return_if_fail (GTK_IS_WIDGET (proxy));
966
967   GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
968 }
969
970 /**
971  * gtk_action_get_proxies:
972  * @action: the action object
973  * 
974  * Returns the proxy widgets for an action.
975  * See also gtk_activatable_get_related_action().
976  *
977  * Return value: (element-type GtkWidget) (transfer none): a #GSList of proxy widgets. The list is owned by GTK+
978  * and must not be modified.
979  *
980  * Since: 2.4
981  **/
982 GSList*
983 gtk_action_get_proxies (GtkAction *action)
984 {
985   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
986
987   return action->private_data->proxies;
988 }
989
990 /**
991  * gtk_action_get_name:
992  * @action: the action object
993  * 
994  * Returns the name of the action.
995  * 
996  * Return value: the name of the action. The string belongs to GTK+ and should not
997  *   be freed.
998  *
999  * Since: 2.4
1000  **/
1001 const gchar *
1002 gtk_action_get_name (GtkAction *action)
1003 {
1004   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1005
1006   return action->private_data->name;
1007 }
1008
1009 /**
1010  * gtk_action_is_sensitive:
1011  * @action: the action object
1012  * 
1013  * Returns whether the action is effectively sensitive.
1014  *
1015  * Return value: %TRUE if the action and its associated action group 
1016  * are both sensitive.
1017  *
1018  * Since: 2.4
1019  **/
1020 gboolean
1021 gtk_action_is_sensitive (GtkAction *action)
1022 {
1023   GtkActionPrivate *priv;
1024   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1025
1026   priv = action->private_data;
1027   return priv->sensitive &&
1028     (priv->action_group == NULL ||
1029      gtk_action_group_get_sensitive (priv->action_group));
1030 }
1031
1032 /**
1033  * gtk_action_get_sensitive:
1034  * @action: the action object
1035  * 
1036  * Returns whether the action itself is sensitive. Note that this doesn't 
1037  * necessarily mean effective sensitivity. See gtk_action_is_sensitive() 
1038  * for that.
1039  *
1040  * Return value: %TRUE if the action itself is sensitive.
1041  *
1042  * Since: 2.4
1043  **/
1044 gboolean
1045 gtk_action_get_sensitive (GtkAction *action)
1046 {
1047   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1048
1049   return action->private_data->sensitive;
1050 }
1051
1052 /**
1053  * gtk_action_set_sensitive:
1054  * @action: the action object
1055  * @sensitive: %TRUE to make the action sensitive
1056  * 
1057  * Sets the ::sensitive property of the action to @sensitive. Note that 
1058  * this doesn't necessarily mean effective sensitivity. See 
1059  * gtk_action_is_sensitive() 
1060  * for that.
1061  *
1062  * Since: 2.6
1063  **/
1064 void
1065 gtk_action_set_sensitive (GtkAction *action,
1066                           gboolean   sensitive)
1067 {
1068   g_return_if_fail (GTK_IS_ACTION (action));
1069
1070   sensitive = sensitive != FALSE;
1071   
1072   if (action->private_data->sensitive != sensitive)
1073     {
1074       action->private_data->sensitive = sensitive;
1075
1076       g_object_notify (G_OBJECT (action), "sensitive");
1077     }
1078 }
1079
1080 /**
1081  * gtk_action_is_visible:
1082  * @action: the action object
1083  * 
1084  * Returns whether the action is effectively visible.
1085  *
1086  * Return value: %TRUE if the action and its associated action group 
1087  * are both visible.
1088  *
1089  * Since: 2.4
1090  **/
1091 gboolean
1092 gtk_action_is_visible (GtkAction *action)
1093 {
1094   GtkActionPrivate *priv;
1095   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1096
1097   priv = action->private_data;
1098   return priv->visible &&
1099     (priv->action_group == NULL ||
1100      gtk_action_group_get_visible (priv->action_group));
1101 }
1102
1103 /**
1104  * gtk_action_get_visible:
1105  * @action: the action object
1106  * 
1107  * Returns whether the action itself is visible. Note that this doesn't 
1108  * necessarily mean effective visibility. See gtk_action_is_sensitive() 
1109  * for that.
1110  *
1111  * Return value: %TRUE if the action itself is visible.
1112  *
1113  * Since: 2.4
1114  **/
1115 gboolean
1116 gtk_action_get_visible (GtkAction *action)
1117 {
1118   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1119
1120   return action->private_data->visible;
1121 }
1122
1123 /**
1124  * gtk_action_set_visible:
1125  * @action: the action object
1126  * @visible: %TRUE to make the action visible
1127  * 
1128  * Sets the ::visible property of the action to @visible. Note that 
1129  * this doesn't necessarily mean effective visibility. See 
1130  * gtk_action_is_visible() 
1131  * for that.
1132  *
1133  * Since: 2.6
1134  **/
1135 void
1136 gtk_action_set_visible (GtkAction *action,
1137                         gboolean   visible)
1138 {
1139   g_return_if_fail (GTK_IS_ACTION (action));
1140
1141   visible = visible != FALSE;
1142   
1143   if (action->private_data->visible != visible)
1144     {
1145       action->private_data->visible = visible;
1146
1147       g_object_notify (G_OBJECT (action), "visible");
1148     }
1149 }
1150 /**
1151  * gtk_action_set_is_important:
1152  * @action: the action object
1153  * @is_important: %TRUE to make the action important
1154  *
1155  * Sets whether the action is important, this attribute is used
1156  * primarily by toolbar items to decide whether to show a label
1157  * or not.
1158  *
1159  * Since: 2.16
1160  */
1161 void 
1162 gtk_action_set_is_important (GtkAction *action,
1163                              gboolean   is_important)
1164 {
1165   g_return_if_fail (GTK_IS_ACTION (action));
1166
1167   is_important = is_important != FALSE;
1168   
1169   if (action->private_data->is_important != is_important)
1170     {
1171       action->private_data->is_important = is_important;
1172       
1173       g_object_notify (G_OBJECT (action), "is-important");
1174     }  
1175 }
1176
1177 /**
1178  * gtk_action_get_is_important:
1179  * @action: a #GtkAction
1180  *
1181  * Checks whether @action is important or not
1182  * 
1183  * Returns: whether @action is important
1184  *
1185  * Since: 2.16
1186  */
1187 gboolean 
1188 gtk_action_get_is_important (GtkAction *action)
1189 {
1190   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1191
1192   return action->private_data->is_important;
1193 }
1194
1195 /**
1196  * gtk_action_set_always_show_image:
1197  * @action: a #GtkAction
1198  * @always_show: %TRUE if menuitem proxies should always show their image
1199  *
1200  * Sets whether @action<!-- -->'s menu item proxies will ignore the
1201  * #GtkSettings:gtk-menu-images setting and always show their image, if available.
1202  *
1203  * Use this if the menu item would be useless or hard to use
1204  * without their image.
1205  *
1206  * Since: 2.20
1207  */
1208 void
1209 gtk_action_set_always_show_image (GtkAction *action,
1210                                   gboolean   always_show)
1211 {
1212   GtkActionPrivate *priv;
1213
1214   g_return_if_fail (GTK_IS_ACTION (action));
1215
1216   priv = action->private_data;
1217
1218   always_show = always_show != FALSE;
1219   
1220   if (priv->always_show_image != always_show)
1221     {
1222       priv->always_show_image = always_show;
1223
1224       g_object_notify (G_OBJECT (action), "always-show-image");
1225     }
1226 }
1227
1228 /**
1229  * gtk_action_get_always_show_image:
1230  * @action: a #GtkAction
1231  *
1232  * Returns whether @action<!-- -->'s menu item proxies will ignore the
1233  * #GtkSettings:gtk-menu-images setting and always show their image,
1234  * if available.
1235  *
1236  * Returns: %TRUE if the menu item proxies will always show their image
1237  *
1238  * Since: 2.20
1239  */
1240 gboolean
1241 gtk_action_get_always_show_image  (GtkAction *action)
1242 {
1243   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1244
1245   return action->private_data->always_show_image;
1246 }
1247
1248 /**
1249  * gtk_action_set_label:
1250  * @action: a #GtkAction
1251  * @label: the label text to set
1252  *
1253  * Sets the label of @action.
1254  *
1255  * Since: 2.16
1256  */
1257 void 
1258 gtk_action_set_label (GtkAction   *action,
1259                       const gchar *label)
1260 {
1261   gchar *tmp;
1262   
1263   g_return_if_fail (GTK_IS_ACTION (action));
1264   
1265   tmp = action->private_data->label;
1266   action->private_data->label = g_strdup (label);
1267   g_free (tmp);
1268   action->private_data->label_set = (action->private_data->label != NULL);
1269   /* if label is unset, then use the label from the stock item */
1270   if (!action->private_data->label_set && action->private_data->stock_id)
1271     {
1272       GtkStockItem stock_item;
1273       
1274       if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1275         action->private_data->label = g_strdup (stock_item.label);
1276     }
1277
1278   g_object_notify (G_OBJECT (action), "label");
1279   
1280   /* if short_label is unset, set short_label=label */
1281   if (!action->private_data->short_label_set)
1282     {
1283       gtk_action_set_short_label (action, action->private_data->label);
1284       action->private_data->short_label_set = FALSE;
1285     }
1286 }
1287
1288 /**
1289  * gtk_action_get_label:
1290  * @action: a #GtkAction
1291  *
1292  * Gets the label text of @action.
1293  *
1294  * Returns: the label text
1295  *
1296  * Since: 2.16
1297  */
1298 const gchar *
1299 gtk_action_get_label (GtkAction *action)
1300 {
1301   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1302
1303   return action->private_data->label;
1304 }
1305
1306 /**
1307  * gtk_action_set_short_label:
1308  * @action: a #GtkAction
1309  * @short_label: the label text to set
1310  *
1311  * Sets a shorter label text on @action.
1312  *
1313  * Since: 2.16
1314  */
1315 void 
1316 gtk_action_set_short_label (GtkAction   *action,
1317                             const gchar *short_label)
1318 {
1319   gchar *tmp;
1320
1321   g_return_if_fail (GTK_IS_ACTION (action));
1322
1323   tmp = action->private_data->short_label;
1324   action->private_data->short_label = g_strdup (short_label);
1325   g_free (tmp);
1326   action->private_data->short_label_set = (action->private_data->short_label != NULL);
1327   /* if short_label is unset, then use the value of label */
1328   if (!action->private_data->short_label_set)
1329     action->private_data->short_label = g_strdup (action->private_data->label);
1330
1331   g_object_notify (G_OBJECT (action), "short-label");
1332 }
1333
1334 /**
1335  * gtk_action_get_short_label:
1336  * @action: a #GtkAction
1337  *
1338  * Gets the short label text of @action.
1339  *
1340  * Returns: the short label text.
1341  *
1342  * Since: 2.16
1343  */
1344 const gchar *
1345 gtk_action_get_short_label (GtkAction *action)
1346 {
1347   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1348
1349   return action->private_data->short_label;
1350 }
1351
1352 /**
1353  * gtk_action_set_visible_horizontal:
1354  * @action: a #GtkAction
1355  * @visible_horizontal: whether the action is visible horizontally
1356  *
1357  * Sets whether @action is visible when horizontal
1358  *
1359  * Since: 2.16
1360  */
1361 void 
1362 gtk_action_set_visible_horizontal (GtkAction *action,
1363                                    gboolean   visible_horizontal)
1364 {
1365   g_return_if_fail (GTK_IS_ACTION (action));
1366
1367   g_return_if_fail (GTK_IS_ACTION (action));
1368
1369   visible_horizontal = visible_horizontal != FALSE;
1370   
1371   if (action->private_data->visible_horizontal != visible_horizontal)
1372     {
1373       action->private_data->visible_horizontal = visible_horizontal;
1374       
1375       g_object_notify (G_OBJECT (action), "visible-horizontal");
1376     }  
1377 }
1378
1379 /**
1380  * gtk_action_get_visible_horizontal:
1381  * @action: a #GtkAction
1382  *
1383  * Checks whether @action is visible when horizontal
1384  * 
1385  * Returns: whether @action is visible when horizontal
1386  *
1387  * Since: 2.16
1388  */
1389 gboolean 
1390 gtk_action_get_visible_horizontal (GtkAction *action)
1391 {
1392   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1393
1394   return action->private_data->visible_horizontal;
1395 }
1396
1397 /**
1398  * gtk_action_set_visible_vertical:
1399  * @action: a #GtkAction
1400  * @visible_vertical: whether the action is visible vertically
1401  *
1402  * Sets whether @action is visible when vertical 
1403  *
1404  * Since: 2.16
1405  */
1406 void 
1407 gtk_action_set_visible_vertical (GtkAction *action,
1408                                  gboolean   visible_vertical)
1409 {
1410   g_return_if_fail (GTK_IS_ACTION (action));
1411
1412   g_return_if_fail (GTK_IS_ACTION (action));
1413
1414   visible_vertical = visible_vertical != FALSE;
1415   
1416   if (action->private_data->visible_vertical != visible_vertical)
1417     {
1418       action->private_data->visible_vertical = visible_vertical;
1419       
1420       g_object_notify (G_OBJECT (action), "visible-vertical");
1421     }  
1422 }
1423
1424 /**
1425  * gtk_action_get_visible_vertical:
1426  * @action: a #GtkAction
1427  *
1428  * Checks whether @action is visible when horizontal
1429  * 
1430  * Returns: whether @action is visible when horizontal
1431  *
1432  * Since: 2.16
1433  */
1434 gboolean 
1435 gtk_action_get_visible_vertical (GtkAction *action)
1436 {
1437   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1438
1439   return action->private_data->visible_vertical;
1440 }
1441
1442 /**
1443  * gtk_action_set_tooltip:
1444  * @action: a #GtkAction
1445  * @tooltip: the tooltip text
1446  *
1447  * Sets the tooltip text on @action
1448  *
1449  * Since: 2.16
1450  */
1451 void 
1452 gtk_action_set_tooltip (GtkAction   *action,
1453                         const gchar *tooltip)
1454 {
1455   gchar *tmp;
1456
1457   g_return_if_fail (GTK_IS_ACTION (action));
1458
1459   tmp = action->private_data->tooltip;
1460   action->private_data->tooltip = g_strdup (tooltip);
1461   g_free (tmp);
1462
1463   g_object_notify (G_OBJECT (action), "tooltip");
1464 }
1465
1466 /**
1467  * gtk_action_get_tooltip:
1468  * @action: a #GtkAction
1469  *
1470  * Gets the tooltip text of @action.
1471  *
1472  * Returns: the tooltip text
1473  *
1474  * Since: 2.16
1475  */
1476 const gchar *
1477 gtk_action_get_tooltip (GtkAction *action)
1478 {
1479   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1480
1481   return action->private_data->tooltip;
1482 }
1483
1484 /**
1485  * gtk_action_set_stock_id:
1486  * @action: a #GtkAction
1487  * @stock_id: the stock id
1488  *
1489  * Sets the stock id on @action
1490  *
1491  * Since: 2.16
1492  */
1493 void 
1494 gtk_action_set_stock_id (GtkAction   *action,
1495                          const gchar *stock_id)
1496 {
1497   gchar *tmp;
1498
1499   g_return_if_fail (GTK_IS_ACTION (action));
1500
1501   g_return_if_fail (GTK_IS_ACTION (action));
1502
1503   tmp = action->private_data->stock_id;
1504   action->private_data->stock_id = g_strdup (stock_id);
1505   g_free (tmp);
1506
1507   g_object_notify (G_OBJECT (action), "stock-id");
1508   
1509   /* update label and short_label if appropriate */
1510   if (!action->private_data->label_set)
1511     {
1512       GtkStockItem stock_item;
1513       
1514       if (action->private_data->stock_id &&
1515           gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1516         gtk_action_set_label (action, stock_item.label);
1517       else 
1518         gtk_action_set_label (action, NULL);
1519       
1520       action->private_data->label_set = FALSE;
1521     }
1522 }
1523
1524 /**
1525  * gtk_action_get_stock_id:
1526  * @action: a #GtkAction
1527  *
1528  * Gets the stock id of @action.
1529  *
1530  * Returns: the stock id
1531  *
1532  * Since: 2.16
1533  */
1534 const gchar *
1535 gtk_action_get_stock_id (GtkAction *action)
1536 {
1537   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1538
1539   return action->private_data->stock_id;
1540 }
1541
1542 /**
1543  * gtk_action_set_icon_name:
1544  * @action: a #GtkAction
1545  * @icon_name: the icon name to set
1546  *
1547  * Sets the icon name on @action
1548  *
1549  * Since: 2.16
1550  */
1551 void 
1552 gtk_action_set_icon_name (GtkAction   *action,
1553                           const gchar *icon_name)
1554 {
1555   gchar *tmp;
1556
1557   g_return_if_fail (GTK_IS_ACTION (action));
1558
1559   tmp = action->private_data->icon_name;
1560   action->private_data->icon_name = g_strdup (icon_name);
1561   g_free (tmp);
1562
1563   g_object_notify (G_OBJECT (action), "icon-name");
1564 }
1565
1566 /**
1567  * gtk_action_get_icon_name:
1568  * @action: a #GtkAction
1569  *
1570  * Gets the icon name of @action.
1571  *
1572  * Returns: the icon name
1573  *
1574  * Since: 2.16
1575  */
1576 const gchar *
1577 gtk_action_get_icon_name (GtkAction *action)
1578 {
1579   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1580
1581   return action->private_data->icon_name;
1582 }
1583
1584 /**
1585  * gtk_action_set_gicon:
1586  * @action: a #GtkAction
1587  * @icon: the #GIcon to set
1588  *
1589  * Sets the icon of @action.
1590  *
1591  * Since: 2.16
1592  */
1593 void
1594 gtk_action_set_gicon (GtkAction *action,
1595                       GIcon     *icon)
1596 {
1597   g_return_if_fail (GTK_IS_ACTION (action));
1598
1599   if (action->private_data->gicon)
1600     g_object_unref (action->private_data->gicon);
1601
1602   action->private_data->gicon = icon;
1603
1604   if (action->private_data->gicon)
1605     g_object_ref (action->private_data->gicon);
1606
1607   g_object_notify (G_OBJECT (action), "gicon");
1608 }
1609
1610 /**
1611  * gtk_action_get_gicon:
1612  * @action: a #GtkAction
1613  *
1614  * Gets the gicon of @action.
1615  *
1616  * Returns: (transfer none): The action's #GIcon if one is set.
1617  *
1618  * Since: 2.16
1619  */
1620 GIcon *
1621 gtk_action_get_gicon (GtkAction *action)
1622 {
1623   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1624
1625   return action->private_data->gicon;
1626 }
1627
1628 static void
1629 closure_accel_activate (GClosure     *closure,
1630                         GValue       *return_value,
1631                         guint         n_param_values,
1632                         const GValue *param_values,
1633                         gpointer      invocation_hint,
1634                         gpointer      marshal_data)
1635 {
1636   if (gtk_action_is_sensitive (GTK_ACTION (closure->data)))
1637     {
1638       _gtk_action_emit_activate (GTK_ACTION (closure->data));
1639       
1640       /* we handled the accelerator */
1641       g_value_set_boolean (return_value, TRUE);
1642     }
1643 }
1644
1645 static void
1646 gtk_action_set_action_group (GtkAction      *action,
1647                              GtkActionGroup *action_group)
1648 {
1649   if (action->private_data->action_group == NULL)
1650     g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1651   else
1652     g_return_if_fail (action_group == NULL);
1653
1654   action->private_data->action_group = action_group;
1655 }
1656
1657 /**
1658  * gtk_action_set_accel_path:
1659  * @action: the action object
1660  * @accel_path: the accelerator path
1661  *
1662  * Sets the accel path for this action.  All proxy widgets associated
1663  * with the action will have this accel path, so that their
1664  * accelerators are consistent.
1665  *
1666  * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
1667  * pass a static string, you can save some memory by interning it first with 
1668  * g_intern_static_string().
1669  *
1670  * Since: 2.4
1671  */
1672 void
1673 gtk_action_set_accel_path (GtkAction   *action, 
1674                            const gchar *accel_path)
1675 {
1676   g_return_if_fail (GTK_IS_ACTION (action));
1677
1678   action->private_data->accel_quark = g_quark_from_string (accel_path);
1679 }
1680
1681 /**
1682  * gtk_action_get_accel_path:
1683  * @action: the action object
1684  *
1685  * Returns the accel path for this action.  
1686  *
1687  * Since: 2.6
1688  *
1689  * Returns: the accel path for this action, or %NULL
1690  *   if none is set. The returned string is owned by GTK+ 
1691  *   and must not be freed or modified.
1692  */
1693 const gchar *
1694 gtk_action_get_accel_path (GtkAction *action)
1695 {
1696   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1697
1698   if (action->private_data->accel_quark)
1699     return g_quark_to_string (action->private_data->accel_quark);
1700   else
1701     return NULL;
1702 }
1703
1704 /**
1705  * gtk_action_get_accel_closure:
1706  * @action: the action object
1707  *
1708  * Returns the accel closure for this action.
1709  *
1710  * Since: 2.8
1711  *
1712  * Returns: (transfer none): the accel closure for this action. The
1713  *          returned closure is owned by GTK+ and must not be unreffed
1714  *          or modified.
1715  */
1716 GClosure *
1717 gtk_action_get_accel_closure (GtkAction *action)
1718 {
1719   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1720
1721   return action->private_data->accel_closure;
1722 }
1723
1724
1725 /**
1726  * gtk_action_set_accel_group:
1727  * @action: the action object
1728  * @accel_group: (allow-none): a #GtkAccelGroup or %NULL
1729  *
1730  * Sets the #GtkAccelGroup in which the accelerator for this action
1731  * will be installed.
1732  *
1733  * Since: 2.4
1734  **/
1735 void
1736 gtk_action_set_accel_group (GtkAction     *action,
1737                             GtkAccelGroup *accel_group)
1738 {
1739   g_return_if_fail (GTK_IS_ACTION (action));
1740   g_return_if_fail (accel_group == NULL || GTK_IS_ACCEL_GROUP (accel_group));
1741   
1742   if (accel_group)
1743     g_object_ref (accel_group);
1744   if (action->private_data->accel_group)
1745     g_object_unref (action->private_data->accel_group);
1746
1747   action->private_data->accel_group = accel_group;
1748 }
1749
1750 /**
1751  * gtk_action_connect_accelerator:
1752  * @action: a #GtkAction
1753  * 
1754  * Installs the accelerator for @action if @action has an
1755  * accel path and group. See gtk_action_set_accel_path() and 
1756  * gtk_action_set_accel_group()
1757  *
1758  * Since multiple proxies may independently trigger the installation
1759  * of the accelerator, the @action counts the number of times this
1760  * function has been called and doesn't remove the accelerator until
1761  * gtk_action_disconnect_accelerator() has been called as many times.
1762  *
1763  * Since: 2.4
1764  **/
1765 void 
1766 gtk_action_connect_accelerator (GtkAction *action)
1767 {
1768   g_return_if_fail (GTK_IS_ACTION (action));
1769
1770   if (!action->private_data->accel_quark ||
1771       !action->private_data->accel_group)
1772     return;
1773
1774   if (action->private_data->accel_count == 0)
1775     {
1776       const gchar *accel_path = 
1777         g_quark_to_string (action->private_data->accel_quark);
1778       
1779       gtk_accel_group_connect_by_path (action->private_data->accel_group,
1780                                        accel_path,
1781                                        action->private_data->accel_closure);
1782     }
1783
1784   action->private_data->accel_count++;
1785 }
1786
1787 /**
1788  * gtk_action_disconnect_accelerator:
1789  * @action: a #GtkAction
1790  * 
1791  * Undoes the effect of one call to gtk_action_connect_accelerator().
1792  *
1793  * Since: 2.4
1794  **/
1795 void 
1796 gtk_action_disconnect_accelerator (GtkAction *action)
1797 {
1798   g_return_if_fail (GTK_IS_ACTION (action));
1799
1800   if (!action->private_data->accel_quark ||
1801       !action->private_data->accel_group)
1802     return;
1803
1804   action->private_data->accel_count--;
1805
1806   if (action->private_data->accel_count == 0)
1807     gtk_accel_group_disconnect (action->private_data->accel_group,
1808                                 action->private_data->accel_closure);
1809 }
1810
1811 /**
1812  * gtk_action_create_menu:
1813  * @action: a #GtkAction
1814  *
1815  * If @action provides a #GtkMenu widget as a submenu for the menu
1816  * item or the toolbar item it creates, this function returns an
1817  * instance of that menu.
1818  *
1819  * Return value: (transfer none): the menu item provided by the
1820  *               action, or %NULL.
1821  *
1822  * Since: 2.12
1823  */
1824 GtkWidget *
1825 gtk_action_create_menu (GtkAction *action)
1826 {
1827   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1828
1829   if (GTK_ACTION_GET_CLASS (action)->create_menu)
1830     return GTK_ACTION_GET_CLASS (action)->create_menu (action);
1831
1832   return NULL;
1833 }