]> Pileus Git - ~andy/gtk/blob - gtk/gtkaction.c
c24ee7859fb6d2b1aa5a6e00648a0fa92096f5cc
[~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 the Gnome Library; see the file COPYING.LIB.  If not,
18  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /*
23  * Author: James Henstridge <james@daa.com.au>
24  *
25  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
26  * file for a list of people on the GTK+ Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
29  */
30
31 /**
32  * SECTION:gtkaction
33  * @Short_description: An action which can be triggered by a menu or toolbar item
34  * @Title: GtkAction
35  * @See_also: #GtkActionGroup, #GtkUIManager, #GtkActivatable
36  *
37  * Actions represent operations that the user can be perform, along with
38  * some information how it should be presented in the interface. Each action
39  * provides methods to create icons, menu items and toolbar items
40  * representing itself.
41  *
42  * As well as the callback that is called when the action gets activated,
43  * the following also gets associated with the action:
44  * <itemizedlist>
45  *   <listitem><para>a name (not translated, for path lookup)</para></listitem>
46  *   <listitem><para>a label (translated, for display)</para></listitem>
47  *   <listitem><para>an accelerator</para></listitem>
48  *   <listitem><para>whether label indicates a stock id</para></listitem>
49  *   <listitem><para>a tooltip (optional, translated)</para></listitem>
50  *   <listitem><para>a toolbar label (optional, shorter than label)</para></listitem>
51  * </itemizedlist>
52  * The action will also have some state information:
53  * <itemizedlist>
54  *   <listitem><para>visible (shown/hidden)</para></listitem>
55  *   <listitem><para>sensitive (enabled/disabled)</para></listitem>
56  * </itemizedlist>
57  * Apart from regular actions, there are <link linkend="GtkToggleAction">toggle
58  * actions</link>, which can be toggled between two states and <link
59  * linkend="GtkRadioAction">radio actions</link>, of which only one in a group
60  * can be in the "active" state. Other actions can be implemented as #GtkAction
61  * subclasses.
62  *
63  * Each action can have one or more proxy widgets. To act as an action proxy,
64  * widget needs to implement #GtkActivatable interface. Proxies mirror the state
65  * of the action and should change when the action's state changes. Properties
66  * that are always mirrored by proxies are #GtkAction:sensitive and
67  * #GtkAction:visible. #GtkAction:gicon, #GtkAction:icon-name, #GtkAction:label,
68  * #GtkAction:short-label and #GtkAction:stock-id properties are only mirorred
69  * if proxy widget has #GtkActivatable:use-action-appearance property set to
70  * %TRUE.
71  *
72  * When the proxy is activated, it should activate its action.
73  */
74
75 #include "config.h"
76
77 #include "gtkaction.h"
78 #include "gtkactiongroup.h"
79 #include "gtkaccellabel.h"
80 #include "gtkbutton.h"
81 #include "gtkiconfactory.h"
82 #include "gtkimage.h"
83 #include "gtkimagemenuitem.h"
84 #include "gtkintl.h"
85 #include "gtklabel.h"
86 #include "gtkmarshalers.h"
87 #include "gtkmenuitem.h"
88 #include "gtkstock.h"
89 #include "deprecated/gtktearoffmenuitem.h"
90 #include "gtktoolbutton.h"
91 #include "gtktoolbar.h"
92 #include "gtkprivate.h"
93 #include "gtkbuildable.h"
94 #include "gtkactivatable.h"
95
96
97 struct _GtkActionPrivate 
98 {
99   const gchar *name; /* interned */
100   gchar *label;
101   gchar *short_label;
102   gchar *tooltip;
103   gchar *stock_id; /* stock icon */
104   gchar *icon_name; /* themed icon */
105   GIcon *gicon;
106
107   guint sensitive          : 1;
108   guint visible            : 1;
109   guint label_set          : 1; /* these two used so we can set label */
110   guint short_label_set    : 1; /* based on stock id */
111   guint visible_horizontal : 1;
112   guint visible_vertical   : 1;
113   guint is_important       : 1;
114   guint hide_if_empty      : 1;
115   guint visible_overflown  : 1;
116   guint always_show_image  : 1;
117   guint recursion_guard    : 1;
118   guint activate_blocked   : 1;
119
120   /* accelerator */
121   guint          accel_count;
122   GtkAccelGroup *accel_group;
123   GClosure      *accel_closure;
124   GQuark         accel_quark;
125
126   GtkActionGroup *action_group;
127
128   /* list of proxy widgets */
129   GSList *proxies;
130 };
131
132 enum 
133 {
134   ACTIVATE,
135   LAST_SIGNAL
136 };
137
138 enum 
139 {
140   PROP_0,
141   PROP_NAME,
142   PROP_LABEL,
143   PROP_SHORT_LABEL,
144   PROP_TOOLTIP,
145   PROP_STOCK_ID,
146   PROP_ICON_NAME,
147   PROP_GICON,
148   PROP_VISIBLE_HORIZONTAL,
149   PROP_VISIBLE_VERTICAL,
150   PROP_VISIBLE_OVERFLOWN,
151   PROP_IS_IMPORTANT,
152   PROP_HIDE_IF_EMPTY,
153   PROP_SENSITIVE,
154   PROP_VISIBLE,
155   PROP_ACTION_GROUP,
156   PROP_ALWAYS_SHOW_IMAGE
157 };
158
159 /* GtkBuildable */
160 static void gtk_action_buildable_init             (GtkBuildableIface *iface);
161 static void gtk_action_buildable_set_name         (GtkBuildable *buildable,
162                                                    const gchar  *name);
163 static const gchar* gtk_action_buildable_get_name (GtkBuildable *buildable);
164
165 G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
166                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
167                                                 gtk_action_buildable_init))
168
169 static void gtk_action_finalize     (GObject *object);
170 static void gtk_action_set_property (GObject         *object,
171                                      guint            prop_id,
172                                      const GValue    *value,
173                                      GParamSpec      *pspec);
174 static void gtk_action_get_property (GObject         *object,
175                                      guint            prop_id,
176                                      GValue          *value,
177                                      GParamSpec      *pspec);
178 static void gtk_action_set_action_group (GtkAction      *action,
179                                          GtkActionGroup *action_group);
180
181 static GtkWidget *create_menu_item    (GtkAction *action);
182 static GtkWidget *create_tool_item    (GtkAction *action);
183 static void       connect_proxy       (GtkAction *action,
184                                        GtkWidget *proxy);
185 static void       disconnect_proxy    (GtkAction *action,
186                                        GtkWidget *proxy);
187  
188 static void       closure_accel_activate (GClosure     *closure,
189                                           GValue       *return_value,
190                                           guint         n_param_values,
191                                           const GValue *param_values,
192                                           gpointer      invocation_hint,
193                                           gpointer      marshal_data);
194
195 static guint         action_signals[LAST_SIGNAL] = { 0 };
196
197
198 static void
199 gtk_action_class_init (GtkActionClass *klass)
200 {
201   GObjectClass *gobject_class;
202
203   gobject_class = G_OBJECT_CLASS (klass);
204
205   gobject_class->finalize     = gtk_action_finalize;
206   gobject_class->set_property = gtk_action_set_property;
207   gobject_class->get_property = gtk_action_get_property;
208
209   klass->activate = NULL;
210
211   klass->create_menu_item  = create_menu_item;
212   klass->create_tool_item  = create_tool_item;
213   klass->create_menu       = NULL;
214   klass->menu_item_type    = GTK_TYPE_IMAGE_MENU_ITEM;
215   klass->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
216   klass->connect_proxy    = connect_proxy;
217   klass->disconnect_proxy = disconnect_proxy;
218
219   g_object_class_install_property (gobject_class,
220                                    PROP_NAME,
221                                    g_param_spec_string ("name",
222                                                         P_("Name"),
223                                                         P_("A unique name for the action."),
224                                                         NULL,
225                                                         GTK_PARAM_READWRITE | 
226                                                         G_PARAM_CONSTRUCT_ONLY));
227
228   /**
229    * GtkAction:label:
230    *
231    * The label used for menu items and buttons that activate
232    * this action. If the label is %NULL, GTK+ uses the stock 
233    * label specified via the stock-id property.
234    *
235    * This is an appearance property and thus only applies if 
236    * #GtkActivatable:use-action-appearance is %TRUE.
237    */
238   g_object_class_install_property (gobject_class,
239                                    PROP_LABEL,
240                                    g_param_spec_string ("label",
241                                                         P_("Label"),
242                                                         P_("The label used for menu items and buttons "
243                                                            "that activate this action."),
244                                                         NULL,
245                                                         GTK_PARAM_READWRITE));
246
247   /**
248    * GtkAction:short-label:
249    *
250    * A shorter label that may be used on toolbar buttons.
251    *
252    * This is an appearance property and thus only applies if 
253    * #GtkActivatable:use-action-appearance is %TRUE.
254    */
255   g_object_class_install_property (gobject_class,
256                                    PROP_SHORT_LABEL,
257                                    g_param_spec_string ("short-label",
258                                                         P_("Short label"),
259                                                         P_("A shorter label that may be used on toolbar buttons."),
260                                                         NULL,
261                                                         GTK_PARAM_READWRITE));
262
263
264   g_object_class_install_property (gobject_class,
265                                    PROP_TOOLTIP,
266                                    g_param_spec_string ("tooltip",
267                                                         P_("Tooltip"),
268                                                         P_("A tooltip for this action."),
269                                                         NULL,
270                                                         GTK_PARAM_READWRITE));
271
272   /**
273    * GtkAction:stock-id:
274    *
275    * The stock icon displayed in widgets representing this action.
276    *
277    * This is an appearance property and thus only applies if 
278    * #GtkActivatable:use-action-appearance is %TRUE.
279    */
280   g_object_class_install_property (gobject_class,
281                                    PROP_STOCK_ID,
282                                    g_param_spec_string ("stock-id",
283                                                         P_("Stock Icon"),
284                                                         P_("The stock icon displayed in widgets representing "
285                                                            "this action."),
286                                                         NULL,
287                                                         GTK_PARAM_READWRITE));
288   /**
289    * GtkAction:gicon:
290    *
291    * The #GIcon displayed in the #GtkAction.
292    *
293    * Note that the stock icon is preferred, if the #GtkAction:stock-id 
294    * property holds the id of an existing stock icon.
295    *
296    * This is an appearance property and thus only applies if 
297    * #GtkActivatable:use-action-appearance is %TRUE.
298    *
299    * Since: 2.16
300    */
301   g_object_class_install_property (gobject_class,
302                                    PROP_GICON,
303                                    g_param_spec_object ("gicon",
304                                                         P_("GIcon"),
305                                                         P_("The GIcon being displayed"),
306                                                         G_TYPE_ICON,
307                                                         GTK_PARAM_READWRITE));                                                  
308   /**
309    * GtkAction:icon-name:
310    *
311    * The name of the icon from the icon theme. 
312    * 
313    * Note that the stock icon is preferred, if the #GtkAction:stock-id 
314    * property holds the id of an existing stock icon, and the #GIcon is
315    * preferred if the #GtkAction:gicon property is set. 
316    *
317    * This is an appearance property and thus only applies if 
318    * #GtkActivatable:use-action-appearance is %TRUE.
319    *
320    * Since: 2.10
321    */
322   g_object_class_install_property (gobject_class,
323                                    PROP_ICON_NAME,
324                                    g_param_spec_string ("icon-name",
325                                                         P_("Icon Name"),
326                                                         P_("The name of the icon from the icon theme"),
327                                                         NULL,
328                                                         GTK_PARAM_READWRITE));
329
330   g_object_class_install_property (gobject_class,
331                                    PROP_VISIBLE_HORIZONTAL,
332                                    g_param_spec_boolean ("visible-horizontal",
333                                                          P_("Visible when horizontal"),
334                                                          P_("Whether the toolbar item is visible when the toolbar "
335                                                             "is in a horizontal orientation."),
336                                                          TRUE,
337                                                          GTK_PARAM_READWRITE));
338   /**
339    * GtkAction:visible-overflown:
340    *
341    * When %TRUE, toolitem proxies for this action are represented in the 
342    * toolbar overflow menu.
343    *
344    * Since: 2.6
345    */
346   g_object_class_install_property (gobject_class,
347                                    PROP_VISIBLE_OVERFLOWN,
348                                    g_param_spec_boolean ("visible-overflown",
349                                                          P_("Visible when overflown"),
350                                                          P_("When TRUE, toolitem proxies for this action "
351                                                             "are represented in the toolbar overflow menu."),
352                                                          TRUE,
353                                                          GTK_PARAM_READWRITE));
354   g_object_class_install_property (gobject_class,
355                                    PROP_VISIBLE_VERTICAL,
356                                    g_param_spec_boolean ("visible-vertical",
357                                                          P_("Visible when vertical"),
358                                                          P_("Whether the toolbar item is visible when the toolbar "
359                                                             "is in a vertical orientation."),
360                                                          TRUE,
361                                                          GTK_PARAM_READWRITE));
362   g_object_class_install_property (gobject_class,
363                                    PROP_IS_IMPORTANT,
364                                    g_param_spec_boolean ("is-important",
365                                                          P_("Is important"),
366                                                          P_("Whether the action is considered important. "
367                                                             "When TRUE, toolitem proxies for this action "
368                                                             "show text in GTK_TOOLBAR_BOTH_HORIZ mode."),
369                                                          FALSE,
370                                                          GTK_PARAM_READWRITE));
371   g_object_class_install_property (gobject_class,
372                                    PROP_HIDE_IF_EMPTY,
373                                    g_param_spec_boolean ("hide-if-empty",
374                                                          P_("Hide if empty"),
375                                                          P_("When TRUE, empty menu proxies for this action are hidden."),
376                                                          TRUE,
377                                                          GTK_PARAM_READWRITE));
378   g_object_class_install_property (gobject_class,
379                                    PROP_SENSITIVE,
380                                    g_param_spec_boolean ("sensitive",
381                                                          P_("Sensitive"),
382                                                          P_("Whether the action is enabled."),
383                                                          TRUE,
384                                                          GTK_PARAM_READWRITE));
385   g_object_class_install_property (gobject_class,
386                                    PROP_VISIBLE,
387                                    g_param_spec_boolean ("visible",
388                                                          P_("Visible"),
389                                                          P_("Whether the action is visible."),
390                                                          TRUE,
391                                                          GTK_PARAM_READWRITE));
392   g_object_class_install_property (gobject_class,
393                                    PROP_ACTION_GROUP,
394                                    g_param_spec_object ("action-group",
395                                                          P_("Action Group"),
396                                                          P_("The GtkActionGroup this GtkAction is associated with, or NULL (for internal use)."),
397                                                          GTK_TYPE_ACTION_GROUP,
398                                                          GTK_PARAM_READWRITE));
399
400   /**
401    * GtkAction:always-show-image:
402    *
403    * If %TRUE, the action's menu item proxies will ignore the #GtkSettings:gtk-menu-images 
404    * setting and always show their image, if available.
405    *
406    * Use this property if the menu item would be useless or hard to use
407    * without their image. 
408    *
409    * Since: 2.20
410    **/
411   g_object_class_install_property (gobject_class,
412                                    PROP_ALWAYS_SHOW_IMAGE,
413                                    g_param_spec_boolean ("always-show-image",
414                                                          P_("Always show image"),
415                                                          P_("Whether the image will always be shown"),
416                                                          FALSE,
417                                                          GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
418
419   /**
420    * GtkAction::activate:
421    * @action: the #GtkAction
422    *
423    * The "activate" signal is emitted when the action is activated.
424    *
425    * Since: 2.4
426    */
427   action_signals[ACTIVATE] =
428     g_signal_new (I_("activate"),
429                   G_OBJECT_CLASS_TYPE (klass),
430                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
431                   G_STRUCT_OFFSET (GtkActionClass, activate),  NULL, NULL,
432                   g_cclosure_marshal_VOID__VOID,
433                   G_TYPE_NONE, 0);
434
435   g_type_class_add_private (gobject_class, sizeof (GtkActionPrivate));
436 }
437
438
439 static void
440 gtk_action_init (GtkAction *action)
441 {
442   action->private_data = G_TYPE_INSTANCE_GET_PRIVATE (action,
443                                                       GTK_TYPE_ACTION,
444                                                       GtkActionPrivate);
445
446   action->private_data->name = NULL;
447   action->private_data->label = NULL;
448   action->private_data->short_label = NULL;
449   action->private_data->tooltip = NULL;
450   action->private_data->stock_id = NULL;
451   action->private_data->icon_name = NULL;
452   action->private_data->visible_horizontal = TRUE;
453   action->private_data->visible_vertical   = TRUE;
454   action->private_data->visible_overflown  = TRUE;
455   action->private_data->is_important = FALSE;
456   action->private_data->hide_if_empty = TRUE;
457   action->private_data->always_show_image = FALSE;
458   action->private_data->activate_blocked = FALSE;
459
460   action->private_data->sensitive = TRUE;
461   action->private_data->visible = TRUE;
462
463   action->private_data->label_set = FALSE;
464   action->private_data->short_label_set = FALSE;
465
466   action->private_data->accel_count = 0;
467   action->private_data->accel_group = NULL;
468   action->private_data->accel_quark = 0;
469   action->private_data->accel_closure = 
470     g_closure_new_object (sizeof (GClosure), G_OBJECT (action));
471   g_closure_set_marshal (action->private_data->accel_closure, 
472                          closure_accel_activate);
473   g_closure_ref (action->private_data->accel_closure);
474   g_closure_sink (action->private_data->accel_closure);
475
476   action->private_data->action_group = NULL;
477
478   action->private_data->proxies = NULL;
479   action->private_data->gicon = NULL;  
480 }
481
482 static void
483 gtk_action_buildable_init (GtkBuildableIface *iface)
484 {
485   iface->set_name = gtk_action_buildable_set_name;
486   iface->get_name = gtk_action_buildable_get_name;
487 }
488
489 static void
490 gtk_action_buildable_set_name (GtkBuildable *buildable,
491                                const gchar  *name)
492 {
493   GtkAction *action = GTK_ACTION (buildable);
494
495   action->private_data->name = g_intern_string (name);
496 }
497
498 static const gchar *
499 gtk_action_buildable_get_name (GtkBuildable *buildable)
500 {
501   GtkAction *action = GTK_ACTION (buildable);
502
503   return action->private_data->name;
504 }
505
506 /**
507  * gtk_action_new:
508  * @name: A unique name for the action
509  * @label: (allow-none): the label displayed in menu items and on buttons,
510  *         or %NULL
511  * @tooltip: (allow-none): a tooltip for the action, or %NULL
512  * @stock_id: (allow-none): the stock icon to display in widgets representing
513  *            the action, or %NULL
514  *
515  * Creates a new #GtkAction object. To add the action to a
516  * #GtkActionGroup and set the accelerator for the action,
517  * call gtk_action_group_add_action_with_accel().
518  * See <xref linkend="XML-UI"/> for information on allowed action
519  * names.
520  *
521  * Return value: a new #GtkAction
522  *
523  * Since: 2.4
524  */
525 GtkAction *
526 gtk_action_new (const gchar *name,
527                 const gchar *label,
528                 const gchar *tooltip,
529                 const gchar *stock_id)
530 {
531   g_return_val_if_fail (name != NULL, NULL);
532
533   return g_object_new (GTK_TYPE_ACTION,
534                        "name", name,
535                        "label", label,
536                        "tooltip", tooltip,
537                        "stock-id", stock_id,
538                        NULL);
539 }
540
541 static void
542 gtk_action_finalize (GObject *object)
543 {
544   GtkAction *action;
545   action = GTK_ACTION (object);
546
547   g_free (action->private_data->label);
548   g_free (action->private_data->short_label);
549   g_free (action->private_data->tooltip);
550   g_free (action->private_data->stock_id);
551   g_free (action->private_data->icon_name);
552   
553   if (action->private_data->gicon)
554     g_object_unref (action->private_data->gicon);
555
556   g_closure_unref (action->private_data->accel_closure);
557   if (action->private_data->accel_group)
558     g_object_unref (action->private_data->accel_group);
559
560   G_OBJECT_CLASS (gtk_action_parent_class)->finalize (object);  
561 }
562
563 static void
564 gtk_action_set_property (GObject         *object,
565                          guint            prop_id,
566                          const GValue    *value,
567                          GParamSpec      *pspec)
568 {
569   GtkAction *action;
570   
571   action = GTK_ACTION (object);
572
573   switch (prop_id)
574     {
575     case PROP_NAME:
576       action->private_data->name = g_intern_string (g_value_get_string (value));
577       break;
578     case PROP_LABEL:
579       gtk_action_set_label (action, g_value_get_string (value));
580       break;
581     case PROP_SHORT_LABEL:
582       gtk_action_set_short_label (action, g_value_get_string (value));
583       break;
584     case PROP_TOOLTIP:
585       gtk_action_set_tooltip (action, g_value_get_string (value));
586       break;
587     case PROP_STOCK_ID:
588       gtk_action_set_stock_id (action, g_value_get_string (value));
589       break;
590     case PROP_GICON:
591       gtk_action_set_gicon (action, g_value_get_object (value));
592       break;
593     case PROP_ICON_NAME:
594       gtk_action_set_icon_name (action, g_value_get_string (value));
595       break;
596     case PROP_VISIBLE_HORIZONTAL:
597       gtk_action_set_visible_horizontal (action, g_value_get_boolean (value));
598       break;
599     case PROP_VISIBLE_VERTICAL:
600       gtk_action_set_visible_vertical (action, g_value_get_boolean (value));
601       break;
602     case PROP_VISIBLE_OVERFLOWN:
603       action->private_data->visible_overflown = g_value_get_boolean (value);
604       break;
605     case PROP_IS_IMPORTANT:
606       gtk_action_set_is_important (action, g_value_get_boolean (value));
607       break;
608     case PROP_HIDE_IF_EMPTY:
609       action->private_data->hide_if_empty = g_value_get_boolean (value);
610       break;
611     case PROP_SENSITIVE:
612       gtk_action_set_sensitive (action, g_value_get_boolean (value));
613       break;
614     case PROP_VISIBLE:
615       gtk_action_set_visible (action, g_value_get_boolean (value));
616       break;
617     case PROP_ACTION_GROUP:
618       gtk_action_set_action_group (action, g_value_get_object (value));
619       break;
620     case PROP_ALWAYS_SHOW_IMAGE:
621       gtk_action_set_always_show_image (action, g_value_get_boolean (value));
622       break;
623     default:
624       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
625       break;
626     }
627 }
628
629 static void
630 gtk_action_get_property (GObject    *object,
631                          guint       prop_id,
632                          GValue     *value,
633                          GParamSpec *pspec)
634 {
635   GtkAction *action;
636
637   action = GTK_ACTION (object);
638
639   switch (prop_id)
640     {
641     case PROP_NAME:
642       g_value_set_static_string (value, action->private_data->name);
643       break;
644     case PROP_LABEL:
645       g_value_set_string (value, action->private_data->label);
646       break;
647     case PROP_SHORT_LABEL:
648       g_value_set_string (value, action->private_data->short_label);
649       break;
650     case PROP_TOOLTIP:
651       g_value_set_string (value, action->private_data->tooltip);
652       break;
653     case PROP_STOCK_ID:
654       g_value_set_string (value, action->private_data->stock_id);
655       break;
656     case PROP_ICON_NAME:
657       g_value_set_string (value, action->private_data->icon_name);
658       break;
659     case PROP_GICON:
660       g_value_set_object (value, action->private_data->gicon);
661       break;
662     case PROP_VISIBLE_HORIZONTAL:
663       g_value_set_boolean (value, action->private_data->visible_horizontal);
664       break;
665     case PROP_VISIBLE_VERTICAL:
666       g_value_set_boolean (value, action->private_data->visible_vertical);
667       break;
668     case PROP_VISIBLE_OVERFLOWN:
669       g_value_set_boolean (value, action->private_data->visible_overflown);
670       break;
671     case PROP_IS_IMPORTANT:
672       g_value_set_boolean (value, action->private_data->is_important);
673       break;
674     case PROP_HIDE_IF_EMPTY:
675       g_value_set_boolean (value, action->private_data->hide_if_empty);
676       break;
677     case PROP_SENSITIVE:
678       g_value_set_boolean (value, action->private_data->sensitive);
679       break;
680     case PROP_VISIBLE:
681       g_value_set_boolean (value, action->private_data->visible);
682       break;
683     case PROP_ACTION_GROUP:
684       g_value_set_object (value, action->private_data->action_group);
685       break;
686     case PROP_ALWAYS_SHOW_IMAGE:
687       g_value_set_boolean (value, action->private_data->always_show_image);
688       break;
689     default:
690       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
691       break;
692     }
693 }
694
695 static GtkWidget *
696 create_menu_item (GtkAction *action)
697 {
698   GType menu_item_type;
699
700   menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type;
701
702   return g_object_new (menu_item_type, NULL);
703 }
704
705 static GtkWidget *
706 create_tool_item (GtkAction *action)
707 {
708   GType toolbar_item_type;
709
710   toolbar_item_type = GTK_ACTION_GET_CLASS (action)->toolbar_item_type;
711
712   return g_object_new (toolbar_item_type, NULL);
713 }
714
715 static void
716 remove_proxy (GtkAction *action,
717               GtkWidget *proxy)
718 {
719   g_object_unref (proxy);
720   action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
721 }
722
723 static void
724 connect_proxy (GtkAction *action,
725                GtkWidget *proxy)
726 {
727   action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
728
729   g_object_ref_sink (proxy);
730
731   if (action->private_data->action_group)
732     _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
733
734 }
735
736 static void
737 disconnect_proxy (GtkAction *action,
738                   GtkWidget *proxy)
739 {
740   remove_proxy (action, proxy);
741
742   if (action->private_data->action_group)
743     _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
744 }
745
746 /**
747  * _gtk_action_sync_menu_visible:
748  * @action: (allow-none): a #GtkAction, or %NULL to determine the action from @proxy
749  * @proxy: a proxy menu item
750  * @empty: whether the submenu attached to @proxy is empty
751  * 
752  * Updates the visibility of @proxy from the visibility of @action
753  * according to the following rules:
754  * <itemizedlist>
755  * <listitem><para>if @action is invisible, @proxy is too
756  * </para></listitem>
757  * <listitem><para>if @empty is %TRUE, hide @proxy unless the "hide-if-empty" 
758  *   property of @action indicates otherwise
759  * </para></listitem>
760  * </itemizedlist>
761  * 
762  * This function is used in the implementation of #GtkUIManager.
763  **/
764 void
765 _gtk_action_sync_menu_visible (GtkAction *action,
766                                GtkWidget *proxy,
767                                gboolean   empty)
768 {
769   gboolean visible = TRUE;
770   gboolean hide_if_empty = TRUE;
771
772   g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
773   g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
774
775   if (action == NULL)
776     action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
777
778   if (action)
779     {
780       /* a GtkMenu for a <popup/> doesn't have to have an action */
781       visible = gtk_action_is_visible (action);
782       hide_if_empty = action->private_data->hide_if_empty;
783     }
784
785   if (visible && !(empty && hide_if_empty))
786     gtk_widget_show (proxy);
787   else
788     gtk_widget_hide (proxy);
789 }
790
791 void
792 _gtk_action_emit_activate (GtkAction *action)
793 {
794   GtkActionGroup *group = action->private_data->action_group;
795
796   if (group != NULL) 
797     {
798       g_object_ref (group);
799       _gtk_action_group_emit_pre_activate (group, action);
800     }
801
802     g_signal_emit (action, action_signals[ACTIVATE], 0);
803
804   if (group != NULL) 
805     {
806       _gtk_action_group_emit_post_activate (group, action);
807       g_object_unref (group);
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 }