]> Pileus Git - ~andy/gtk/blob - gtk/gtkaction.c
Merge branch 'windows_list'
[~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 "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, or %NULL
510  * @tooltip: (allow-none): a tooltip for the action, or %NULL
511  * @stock_id: the stock icon to display in widgets representing the
512  *   action, or %NULL
513  *
514  * Creates a new #GtkAction object. To add the action to a
515  * #GtkActionGroup and set the accelerator for the action,
516  * call gtk_action_group_add_action_with_accel().
517  * See <xref linkend="XML-UI"/> for information on allowed action
518  * names.
519  *
520  * Return value: a new #GtkAction
521  *
522  * Since: 2.4
523  */
524 GtkAction *
525 gtk_action_new (const gchar *name,
526                 const gchar *label,
527                 const gchar *tooltip,
528                 const gchar *stock_id)
529 {
530   g_return_val_if_fail (name != NULL, NULL);
531
532   return g_object_new (GTK_TYPE_ACTION,
533                        "name", name,
534                        "label", label,
535                        "tooltip", tooltip,
536                        "stock-id", stock_id,
537                        NULL);
538 }
539
540 static void
541 gtk_action_finalize (GObject *object)
542 {
543   GtkAction *action;
544   action = GTK_ACTION (object);
545
546   g_free (action->private_data->label);
547   g_free (action->private_data->short_label);
548   g_free (action->private_data->tooltip);
549   g_free (action->private_data->stock_id);
550   g_free (action->private_data->icon_name);
551   
552   if (action->private_data->gicon)
553     g_object_unref (action->private_data->gicon);
554
555   g_closure_unref (action->private_data->accel_closure);
556   if (action->private_data->accel_group)
557     g_object_unref (action->private_data->accel_group);
558
559   G_OBJECT_CLASS (gtk_action_parent_class)->finalize (object);  
560 }
561
562 static void
563 gtk_action_set_property (GObject         *object,
564                          guint            prop_id,
565                          const GValue    *value,
566                          GParamSpec      *pspec)
567 {
568   GtkAction *action;
569   
570   action = GTK_ACTION (object);
571
572   switch (prop_id)
573     {
574     case PROP_NAME:
575       action->private_data->name = g_intern_string (g_value_get_string (value));
576       break;
577     case PROP_LABEL:
578       gtk_action_set_label (action, g_value_get_string (value));
579       break;
580     case PROP_SHORT_LABEL:
581       gtk_action_set_short_label (action, g_value_get_string (value));
582       break;
583     case PROP_TOOLTIP:
584       gtk_action_set_tooltip (action, g_value_get_string (value));
585       break;
586     case PROP_STOCK_ID:
587       gtk_action_set_stock_id (action, g_value_get_string (value));
588       break;
589     case PROP_GICON:
590       gtk_action_set_gicon (action, g_value_get_object (value));
591       break;
592     case PROP_ICON_NAME:
593       gtk_action_set_icon_name (action, g_value_get_string (value));
594       break;
595     case PROP_VISIBLE_HORIZONTAL:
596       gtk_action_set_visible_horizontal (action, g_value_get_boolean (value));
597       break;
598     case PROP_VISIBLE_VERTICAL:
599       gtk_action_set_visible_vertical (action, g_value_get_boolean (value));
600       break;
601     case PROP_VISIBLE_OVERFLOWN:
602       action->private_data->visible_overflown = g_value_get_boolean (value);
603       break;
604     case PROP_IS_IMPORTANT:
605       gtk_action_set_is_important (action, g_value_get_boolean (value));
606       break;
607     case PROP_HIDE_IF_EMPTY:
608       action->private_data->hide_if_empty = g_value_get_boolean (value);
609       break;
610     case PROP_SENSITIVE:
611       gtk_action_set_sensitive (action, g_value_get_boolean (value));
612       break;
613     case PROP_VISIBLE:
614       gtk_action_set_visible (action, g_value_get_boolean (value));
615       break;
616     case PROP_ACTION_GROUP:
617       gtk_action_set_action_group (action, g_value_get_object (value));
618       break;
619     case PROP_ALWAYS_SHOW_IMAGE:
620       gtk_action_set_always_show_image (action, g_value_get_boolean (value));
621       break;
622     default:
623       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
624       break;
625     }
626 }
627
628 static void
629 gtk_action_get_property (GObject    *object,
630                          guint       prop_id,
631                          GValue     *value,
632                          GParamSpec *pspec)
633 {
634   GtkAction *action;
635
636   action = GTK_ACTION (object);
637
638   switch (prop_id)
639     {
640     case PROP_NAME:
641       g_value_set_static_string (value, action->private_data->name);
642       break;
643     case PROP_LABEL:
644       g_value_set_string (value, action->private_data->label);
645       break;
646     case PROP_SHORT_LABEL:
647       g_value_set_string (value, action->private_data->short_label);
648       break;
649     case PROP_TOOLTIP:
650       g_value_set_string (value, action->private_data->tooltip);
651       break;
652     case PROP_STOCK_ID:
653       g_value_set_string (value, action->private_data->stock_id);
654       break;
655     case PROP_ICON_NAME:
656       g_value_set_string (value, action->private_data->icon_name);
657       break;
658     case PROP_GICON:
659       g_value_set_object (value, action->private_data->gicon);
660       break;
661     case PROP_VISIBLE_HORIZONTAL:
662       g_value_set_boolean (value, action->private_data->visible_horizontal);
663       break;
664     case PROP_VISIBLE_VERTICAL:
665       g_value_set_boolean (value, action->private_data->visible_vertical);
666       break;
667     case PROP_VISIBLE_OVERFLOWN:
668       g_value_set_boolean (value, action->private_data->visible_overflown);
669       break;
670     case PROP_IS_IMPORTANT:
671       g_value_set_boolean (value, action->private_data->is_important);
672       break;
673     case PROP_HIDE_IF_EMPTY:
674       g_value_set_boolean (value, action->private_data->hide_if_empty);
675       break;
676     case PROP_SENSITIVE:
677       g_value_set_boolean (value, action->private_data->sensitive);
678       break;
679     case PROP_VISIBLE:
680       g_value_set_boolean (value, action->private_data->visible);
681       break;
682     case PROP_ACTION_GROUP:
683       g_value_set_object (value, action->private_data->action_group);
684       break;
685     case PROP_ALWAYS_SHOW_IMAGE:
686       g_value_set_boolean (value, action->private_data->always_show_image);
687       break;
688     default:
689       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
690       break;
691     }
692 }
693
694 static GtkWidget *
695 create_menu_item (GtkAction *action)
696 {
697   GType menu_item_type;
698
699   menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type;
700
701   return g_object_new (menu_item_type, NULL);
702 }
703
704 static GtkWidget *
705 create_tool_item (GtkAction *action)
706 {
707   GType toolbar_item_type;
708
709   toolbar_item_type = GTK_ACTION_GET_CLASS (action)->toolbar_item_type;
710
711   return g_object_new (toolbar_item_type, NULL);
712 }
713
714 static void
715 remove_proxy (GtkAction *action,
716               GtkWidget *proxy)
717 {
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   if (action->private_data->action_group)
728     _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
729
730 }
731
732 static void
733 disconnect_proxy (GtkAction *action,
734                   GtkWidget *proxy)
735 {
736   remove_proxy (action, proxy);
737
738   if (action->private_data->action_group)
739     _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
740 }
741
742 /**
743  * _gtk_action_sync_menu_visible:
744  * @action: (allow-none): a #GtkAction, or %NULL to determine the action from @proxy
745  * @proxy: a proxy menu item
746  * @empty: whether the submenu attached to @proxy is empty
747  * 
748  * Updates the visibility of @proxy from the visibility of @action
749  * according to the following rules:
750  * <itemizedlist>
751  * <listitem><para>if @action is invisible, @proxy is too
752  * </para></listitem>
753  * <listitem><para>if @empty is %TRUE, hide @proxy unless the "hide-if-empty" 
754  *   property of @action indicates otherwise
755  * </para></listitem>
756  * </itemizedlist>
757  * 
758  * This function is used in the implementation of #GtkUIManager.
759  **/
760 void
761 _gtk_action_sync_menu_visible (GtkAction *action,
762                                GtkWidget *proxy,
763                                gboolean   empty)
764 {
765   gboolean visible = TRUE;
766   gboolean hide_if_empty = TRUE;
767
768   g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
769   g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
770
771   if (action == NULL)
772     action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
773
774   if (action)
775     {
776       /* a GtkMenu for a <popup/> doesn't have to have an action */
777       visible = gtk_action_is_visible (action);
778       hide_if_empty = action->private_data->hide_if_empty;
779     }
780
781   if (visible && !(empty && hide_if_empty))
782     gtk_widget_show (proxy);
783   else
784     gtk_widget_hide (proxy);
785 }
786
787 void
788 _gtk_action_emit_activate (GtkAction *action)
789 {
790   GtkActionGroup *group = action->private_data->action_group;
791
792   if (group != NULL) 
793     {
794       g_object_ref (group);
795       _gtk_action_group_emit_pre_activate (group, action);
796     }
797
798     g_signal_emit (action, action_signals[ACTIVATE], 0);
799
800   if (group != NULL) 
801     {
802       _gtk_action_group_emit_post_activate (group, action);
803       g_object_unref (group);
804     }
805 }
806
807 /**
808  * gtk_action_activate:
809  * @action: the action object
810  *
811  * Emits the "activate" signal on the specified action, if it isn't 
812  * insensitive. This gets called by the proxy widgets when they get 
813  * activated.
814  *
815  * It can also be used to manually activate an action.
816  *
817  * Since: 2.4
818  */
819 void
820 gtk_action_activate (GtkAction *action)
821 {
822   g_return_if_fail (GTK_IS_ACTION (action));
823   
824   if (action->private_data->activate_blocked)
825     return;
826
827   if (gtk_action_is_sensitive (action))
828     _gtk_action_emit_activate (action);
829 }
830
831 /**
832  * gtk_action_block_activate:
833  * @action: a #GtkAction
834  *
835  * Disable activation signals from the action 
836  *
837  * This is needed when updating the state of your proxy
838  * #GtkActivatable widget could result in calling gtk_action_activate(),
839  * this is a convenience function to avoid recursing in those
840  * cases (updating toggle state for instance).
841  *
842  * Since: 2.16
843  */
844 void
845 gtk_action_block_activate (GtkAction *action)
846 {
847   g_return_if_fail (GTK_IS_ACTION (action));
848
849   action->private_data->activate_blocked = TRUE;
850 }
851
852 /**
853  * gtk_action_unblock_activate:
854  * @action: a #GtkAction
855  *
856  * Reenable activation signals from the action 
857  *
858  * Since: 2.16
859  */
860 void
861 gtk_action_unblock_activate (GtkAction *action)
862 {
863   g_return_if_fail (GTK_IS_ACTION (action));
864
865   action->private_data->activate_blocked = FALSE;
866 }
867
868 /**
869  * gtk_action_create_icon:
870  * @action: the action object
871  * @icon_size: (type int): the size of the icon that should be created.
872  *
873  * This function is intended for use by action implementations to
874  * create icons displayed in the proxy widgets.
875  *
876  * Returns: a widget that displays the icon for this action.
877  *
878  * Since: 2.4
879  */
880 GtkWidget *
881 gtk_action_create_icon (GtkAction *action, GtkIconSize icon_size)
882 {
883   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
884
885   if (action->private_data->stock_id &&
886       gtk_icon_factory_lookup_default (action->private_data->stock_id))
887     return gtk_image_new_from_stock (action->private_data->stock_id, icon_size);
888   else if (action->private_data->gicon)
889     return gtk_image_new_from_gicon (action->private_data->gicon, icon_size);
890   else if (action->private_data->icon_name)
891     return gtk_image_new_from_icon_name (action->private_data->icon_name, icon_size);
892   else
893     return NULL;
894 }
895
896 /**
897  * gtk_action_create_menu_item:
898  * @action: the action object
899  *
900  * Creates a menu item widget that proxies for the given action.
901  *
902  * Returns: a menu item connected to the action.
903  *
904  * Since: 2.4
905  */
906 GtkWidget *
907 gtk_action_create_menu_item (GtkAction *action)
908 {
909   GtkWidget *menu_item;
910
911   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
912
913   menu_item = GTK_ACTION_GET_CLASS (action)->create_menu_item (action);
914
915   gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (menu_item), TRUE);
916   gtk_activatable_set_related_action (GTK_ACTIVATABLE (menu_item), action);
917
918   return menu_item;
919 }
920
921 /**
922  * gtk_action_create_tool_item:
923  * @action: the action object
924  *
925  * Creates a toolbar item widget that proxies for the given action.
926  *
927  * Returns: a toolbar item connected to the action.
928  *
929  * Since: 2.4
930  */
931 GtkWidget *
932 gtk_action_create_tool_item (GtkAction *action)
933 {
934   GtkWidget *button;
935
936   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
937
938   button = GTK_ACTION_GET_CLASS (action)->create_tool_item (action);
939
940   gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (button), TRUE);
941   gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
942
943   return button;
944 }
945
946 void
947 _gtk_action_add_to_proxy_list (GtkAction     *action,
948                                GtkWidget     *proxy)
949 {
950   g_return_if_fail (GTK_IS_ACTION (action));
951   g_return_if_fail (GTK_IS_WIDGET (proxy));
952  
953   GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
954 }
955
956 void
957 _gtk_action_remove_from_proxy_list (GtkAction     *action,
958                                     GtkWidget     *proxy)
959 {
960   g_return_if_fail (GTK_IS_ACTION (action));
961   g_return_if_fail (GTK_IS_WIDGET (proxy));
962
963   GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
964 }
965
966 /**
967  * gtk_action_get_proxies:
968  * @action: the action object
969  * 
970  * Returns the proxy widgets for an action.
971  * See also gtk_activatable_get_related_action().
972  *
973  * Return value: (element-type GtkWidget) (transfer none): a #GSList of proxy widgets. The list is owned by GTK+
974  * and must not be modified.
975  *
976  * Since: 2.4
977  **/
978 GSList*
979 gtk_action_get_proxies (GtkAction *action)
980 {
981   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
982
983   return action->private_data->proxies;
984 }
985
986 /**
987  * gtk_action_get_name:
988  * @action: the action object
989  * 
990  * Returns the name of the action.
991  * 
992  * Return value: the name of the action. The string belongs to GTK+ and should not
993  *   be freed.
994  *
995  * Since: 2.4
996  **/
997 G_CONST_RETURN gchar *
998 gtk_action_get_name (GtkAction *action)
999 {
1000   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1001
1002   return action->private_data->name;
1003 }
1004
1005 /**
1006  * gtk_action_is_sensitive:
1007  * @action: the action object
1008  * 
1009  * Returns whether the action is effectively sensitive.
1010  *
1011  * Return value: %TRUE if the action and its associated action group 
1012  * are both sensitive.
1013  *
1014  * Since: 2.4
1015  **/
1016 gboolean
1017 gtk_action_is_sensitive (GtkAction *action)
1018 {
1019   GtkActionPrivate *priv;
1020   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1021
1022   priv = action->private_data;
1023   return priv->sensitive &&
1024     (priv->action_group == NULL ||
1025      gtk_action_group_get_sensitive (priv->action_group));
1026 }
1027
1028 /**
1029  * gtk_action_get_sensitive:
1030  * @action: the action object
1031  * 
1032  * Returns whether the action itself is sensitive. Note that this doesn't 
1033  * necessarily mean effective sensitivity. See gtk_action_is_sensitive() 
1034  * for that.
1035  *
1036  * Return value: %TRUE if the action itself is sensitive.
1037  *
1038  * Since: 2.4
1039  **/
1040 gboolean
1041 gtk_action_get_sensitive (GtkAction *action)
1042 {
1043   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1044
1045   return action->private_data->sensitive;
1046 }
1047
1048 /**
1049  * gtk_action_set_sensitive:
1050  * @action: the action object
1051  * @sensitive: %TRUE to make the action sensitive
1052  * 
1053  * Sets the ::sensitive property of the action to @sensitive. Note that 
1054  * this doesn't necessarily mean effective sensitivity. See 
1055  * gtk_action_is_sensitive() 
1056  * for that.
1057  *
1058  * Since: 2.6
1059  **/
1060 void
1061 gtk_action_set_sensitive (GtkAction *action,
1062                           gboolean   sensitive)
1063 {
1064   g_return_if_fail (GTK_IS_ACTION (action));
1065
1066   sensitive = sensitive != FALSE;
1067   
1068   if (action->private_data->sensitive != sensitive)
1069     {
1070       action->private_data->sensitive = sensitive;
1071
1072       g_object_notify (G_OBJECT (action), "sensitive");
1073     }
1074 }
1075
1076 /**
1077  * gtk_action_is_visible:
1078  * @action: the action object
1079  * 
1080  * Returns whether the action is effectively visible.
1081  *
1082  * Return value: %TRUE if the action and its associated action group 
1083  * are both visible.
1084  *
1085  * Since: 2.4
1086  **/
1087 gboolean
1088 gtk_action_is_visible (GtkAction *action)
1089 {
1090   GtkActionPrivate *priv;
1091   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1092
1093   priv = action->private_data;
1094   return priv->visible &&
1095     (priv->action_group == NULL ||
1096      gtk_action_group_get_visible (priv->action_group));
1097 }
1098
1099 /**
1100  * gtk_action_get_visible:
1101  * @action: the action object
1102  * 
1103  * Returns whether the action itself is visible. Note that this doesn't 
1104  * necessarily mean effective visibility. See gtk_action_is_sensitive() 
1105  * for that.
1106  *
1107  * Return value: %TRUE if the action itself is visible.
1108  *
1109  * Since: 2.4
1110  **/
1111 gboolean
1112 gtk_action_get_visible (GtkAction *action)
1113 {
1114   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1115
1116   return action->private_data->visible;
1117 }
1118
1119 /**
1120  * gtk_action_set_visible:
1121  * @action: the action object
1122  * @visible: %TRUE to make the action visible
1123  * 
1124  * Sets the ::visible property of the action to @visible. Note that 
1125  * this doesn't necessarily mean effective visibility. See 
1126  * gtk_action_is_visible() 
1127  * for that.
1128  *
1129  * Since: 2.6
1130  **/
1131 void
1132 gtk_action_set_visible (GtkAction *action,
1133                         gboolean   visible)
1134 {
1135   g_return_if_fail (GTK_IS_ACTION (action));
1136
1137   visible = visible != FALSE;
1138   
1139   if (action->private_data->visible != visible)
1140     {
1141       action->private_data->visible = visible;
1142
1143       g_object_notify (G_OBJECT (action), "visible");
1144     }
1145 }
1146 /**
1147  * gtk_action_set_is_important:
1148  * @action: the action object
1149  * @is_important: %TRUE to make the action important
1150  *
1151  * Sets whether the action is important, this attribute is used
1152  * primarily by toolbar items to decide whether to show a label
1153  * or not.
1154  *
1155  * Since: 2.16
1156  */
1157 void 
1158 gtk_action_set_is_important (GtkAction *action,
1159                              gboolean   is_important)
1160 {
1161   g_return_if_fail (GTK_IS_ACTION (action));
1162
1163   is_important = is_important != FALSE;
1164   
1165   if (action->private_data->is_important != is_important)
1166     {
1167       action->private_data->is_important = is_important;
1168       
1169       g_object_notify (G_OBJECT (action), "is-important");
1170     }  
1171 }
1172
1173 /**
1174  * gtk_action_get_is_important:
1175  * @action: a #GtkAction
1176  *
1177  * Checks whether @action is important or not
1178  * 
1179  * Returns: whether @action is important
1180  *
1181  * Since: 2.16
1182  */
1183 gboolean 
1184 gtk_action_get_is_important (GtkAction *action)
1185 {
1186   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1187
1188   return action->private_data->is_important;
1189 }
1190
1191 /**
1192  * gtk_action_set_always_show_image:
1193  * @action: a #GtkAction
1194  * @always_show: %TRUE if menuitem proxies should always show their image
1195  *
1196  * Sets whether @action<!-- -->'s menu item proxies will ignore the
1197  * #GtkSettings:gtk-menu-images setting and always show their image, if available.
1198  *
1199  * Use this if the menu item would be useless or hard to use
1200  * without their image.
1201  *
1202  * Since: 2.20
1203  */
1204 void
1205 gtk_action_set_always_show_image (GtkAction *action,
1206                                   gboolean   always_show)
1207 {
1208   GtkActionPrivate *priv;
1209
1210   g_return_if_fail (GTK_IS_ACTION (action));
1211
1212   priv = action->private_data;
1213
1214   always_show = always_show != FALSE;
1215   
1216   if (priv->always_show_image != always_show)
1217     {
1218       priv->always_show_image = always_show;
1219
1220       g_object_notify (G_OBJECT (action), "always-show-image");
1221     }
1222 }
1223
1224 /**
1225  * gtk_action_get_always_show_image:
1226  * @action: a #GtkAction
1227  *
1228  * Returns whether @action<!-- -->'s menu item proxies will ignore the
1229  * #GtkSettings:gtk-menu-images setting and always show their image,
1230  * if available.
1231  *
1232  * Returns: %TRUE if the menu item proxies will always show their image
1233  *
1234  * Since: 2.20
1235  */
1236 gboolean
1237 gtk_action_get_always_show_image  (GtkAction *action)
1238 {
1239   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1240
1241   return action->private_data->always_show_image;
1242 }
1243
1244 /**
1245  * gtk_action_set_label:
1246  * @action: a #GtkAction
1247  * @label: the label text to set
1248  *
1249  * Sets the label of @action.
1250  *
1251  * Since: 2.16
1252  */
1253 void 
1254 gtk_action_set_label (GtkAction   *action,
1255                       const gchar *label)
1256 {
1257   gchar *tmp;
1258   
1259   g_return_if_fail (GTK_IS_ACTION (action));
1260   
1261   tmp = action->private_data->label;
1262   action->private_data->label = g_strdup (label);
1263   g_free (tmp);
1264   action->private_data->label_set = (action->private_data->label != NULL);
1265   /* if label is unset, then use the label from the stock item */
1266   if (!action->private_data->label_set && action->private_data->stock_id)
1267     {
1268       GtkStockItem stock_item;
1269       
1270       if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1271         action->private_data->label = g_strdup (stock_item.label);
1272     }
1273
1274   g_object_notify (G_OBJECT (action), "label");
1275   
1276   /* if short_label is unset, set short_label=label */
1277   if (!action->private_data->short_label_set)
1278     {
1279       gtk_action_set_short_label (action, action->private_data->label);
1280       action->private_data->short_label_set = FALSE;
1281     }
1282 }
1283
1284 /**
1285  * gtk_action_get_label:
1286  * @action: a #GtkAction
1287  *
1288  * Gets the label text of @action.
1289  *
1290  * Returns: the label text
1291  *
1292  * Since: 2.16
1293  */
1294 G_CONST_RETURN gchar * 
1295 gtk_action_get_label (GtkAction *action)
1296 {
1297   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1298
1299   return action->private_data->label;
1300 }
1301
1302 /**
1303  * gtk_action_set_short_label:
1304  * @action: a #GtkAction
1305  * @short_label: the label text to set
1306  *
1307  * Sets a shorter label text on @action.
1308  *
1309  * Since: 2.16
1310  */
1311 void 
1312 gtk_action_set_short_label (GtkAction   *action,
1313                             const gchar *short_label)
1314 {
1315   gchar *tmp;
1316
1317   g_return_if_fail (GTK_IS_ACTION (action));
1318
1319   tmp = action->private_data->short_label;
1320   action->private_data->short_label = g_strdup (short_label);
1321   g_free (tmp);
1322   action->private_data->short_label_set = (action->private_data->short_label != NULL);
1323   /* if short_label is unset, then use the value of label */
1324   if (!action->private_data->short_label_set)
1325     action->private_data->short_label = g_strdup (action->private_data->label);
1326
1327   g_object_notify (G_OBJECT (action), "short-label");
1328 }
1329
1330 /**
1331  * gtk_action_get_short_label:
1332  * @action: a #GtkAction
1333  *
1334  * Gets the short label text of @action.
1335  *
1336  * Returns: the short label text.
1337  *
1338  * Since: 2.16
1339  */
1340 G_CONST_RETURN gchar * 
1341 gtk_action_get_short_label (GtkAction *action)
1342 {
1343   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1344
1345   return action->private_data->short_label;
1346 }
1347
1348 /**
1349  * gtk_action_set_visible_horizontal:
1350  * @action: a #GtkAction
1351  * @visible_horizontal: whether the action is visible horizontally
1352  *
1353  * Sets whether @action is visible when horizontal
1354  *
1355  * Since: 2.16
1356  */
1357 void 
1358 gtk_action_set_visible_horizontal (GtkAction *action,
1359                                    gboolean   visible_horizontal)
1360 {
1361   g_return_if_fail (GTK_IS_ACTION (action));
1362
1363   g_return_if_fail (GTK_IS_ACTION (action));
1364
1365   visible_horizontal = visible_horizontal != FALSE;
1366   
1367   if (action->private_data->visible_horizontal != visible_horizontal)
1368     {
1369       action->private_data->visible_horizontal = visible_horizontal;
1370       
1371       g_object_notify (G_OBJECT (action), "visible-horizontal");
1372     }  
1373 }
1374
1375 /**
1376  * gtk_action_get_visible_horizontal:
1377  * @action: a #GtkAction
1378  *
1379  * Checks whether @action is visible when horizontal
1380  * 
1381  * Returns: whether @action is visible when horizontal
1382  *
1383  * Since: 2.16
1384  */
1385 gboolean 
1386 gtk_action_get_visible_horizontal (GtkAction *action)
1387 {
1388   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1389
1390   return action->private_data->visible_horizontal;
1391 }
1392
1393 /**
1394  * gtk_action_set_visible_vertical:
1395  * @action: a #GtkAction
1396  * @visible_vertical: whether the action is visible vertically
1397  *
1398  * Sets whether @action is visible when vertical 
1399  *
1400  * Since: 2.16
1401  */
1402 void 
1403 gtk_action_set_visible_vertical (GtkAction *action,
1404                                  gboolean   visible_vertical)
1405 {
1406   g_return_if_fail (GTK_IS_ACTION (action));
1407
1408   g_return_if_fail (GTK_IS_ACTION (action));
1409
1410   visible_vertical = visible_vertical != FALSE;
1411   
1412   if (action->private_data->visible_vertical != visible_vertical)
1413     {
1414       action->private_data->visible_vertical = visible_vertical;
1415       
1416       g_object_notify (G_OBJECT (action), "visible-vertical");
1417     }  
1418 }
1419
1420 /**
1421  * gtk_action_get_visible_vertical:
1422  * @action: a #GtkAction
1423  *
1424  * Checks whether @action is visible when horizontal
1425  * 
1426  * Returns: whether @action is visible when horizontal
1427  *
1428  * Since: 2.16
1429  */
1430 gboolean 
1431 gtk_action_get_visible_vertical (GtkAction *action)
1432 {
1433   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1434
1435   return action->private_data->visible_vertical;
1436 }
1437
1438 /**
1439  * gtk_action_set_tooltip:
1440  * @action: a #GtkAction
1441  * @tooltip: the tooltip text
1442  *
1443  * Sets the tooltip text on @action
1444  *
1445  * Since: 2.16
1446  */
1447 void 
1448 gtk_action_set_tooltip (GtkAction   *action,
1449                         const gchar *tooltip)
1450 {
1451   gchar *tmp;
1452
1453   g_return_if_fail (GTK_IS_ACTION (action));
1454
1455   tmp = action->private_data->tooltip;
1456   action->private_data->tooltip = g_strdup (tooltip);
1457   g_free (tmp);
1458
1459   g_object_notify (G_OBJECT (action), "tooltip");
1460 }
1461
1462 /**
1463  * gtk_action_get_tooltip:
1464  * @action: a #GtkAction
1465  *
1466  * Gets the tooltip text of @action.
1467  *
1468  * Returns: the tooltip text
1469  *
1470  * Since: 2.16
1471  */
1472 G_CONST_RETURN gchar * 
1473 gtk_action_get_tooltip (GtkAction *action)
1474 {
1475   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1476
1477   return action->private_data->tooltip;
1478 }
1479
1480 /**
1481  * gtk_action_set_stock_id:
1482  * @action: a #GtkAction
1483  * @stock_id: the stock id
1484  *
1485  * Sets the stock id on @action
1486  *
1487  * Since: 2.16
1488  */
1489 void 
1490 gtk_action_set_stock_id (GtkAction   *action,
1491                          const gchar *stock_id)
1492 {
1493   gchar *tmp;
1494
1495   g_return_if_fail (GTK_IS_ACTION (action));
1496
1497   g_return_if_fail (GTK_IS_ACTION (action));
1498
1499   tmp = action->private_data->stock_id;
1500   action->private_data->stock_id = g_strdup (stock_id);
1501   g_free (tmp);
1502
1503   g_object_notify (G_OBJECT (action), "stock-id");
1504   
1505   /* update label and short_label if appropriate */
1506   if (!action->private_data->label_set)
1507     {
1508       GtkStockItem stock_item;
1509       
1510       if (action->private_data->stock_id &&
1511           gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1512         gtk_action_set_label (action, stock_item.label);
1513       else 
1514         gtk_action_set_label (action, NULL);
1515       
1516       action->private_data->label_set = FALSE;
1517     }
1518 }
1519
1520 /**
1521  * gtk_action_get_stock_id:
1522  * @action: a #GtkAction
1523  *
1524  * Gets the stock id of @action.
1525  *
1526  * Returns: the stock id
1527  *
1528  * Since: 2.16
1529  */
1530 G_CONST_RETURN gchar * 
1531 gtk_action_get_stock_id (GtkAction *action)
1532 {
1533   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1534
1535   return action->private_data->stock_id;
1536 }
1537
1538 /**
1539  * gtk_action_set_icon_name:
1540  * @action: a #GtkAction
1541  * @icon_name: the icon name to set
1542  *
1543  * Sets the icon name on @action
1544  *
1545  * Since: 2.16
1546  */
1547 void 
1548 gtk_action_set_icon_name (GtkAction   *action,
1549                           const gchar *icon_name)
1550 {
1551   gchar *tmp;
1552
1553   g_return_if_fail (GTK_IS_ACTION (action));
1554
1555   tmp = action->private_data->icon_name;
1556   action->private_data->icon_name = g_strdup (icon_name);
1557   g_free (tmp);
1558
1559   g_object_notify (G_OBJECT (action), "icon-name");
1560 }
1561
1562 /**
1563  * gtk_action_get_icon_name:
1564  * @action: a #GtkAction
1565  *
1566  * Gets the icon name of @action.
1567  *
1568  * Returns: the icon name
1569  *
1570  * Since: 2.16
1571  */
1572 G_CONST_RETURN gchar * 
1573 gtk_action_get_icon_name (GtkAction *action)
1574 {
1575   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1576
1577   return action->private_data->icon_name;
1578 }
1579
1580 /**
1581  * gtk_action_set_gicon:
1582  * @action: a #GtkAction
1583  * @icon: the #GIcon to set
1584  *
1585  * Sets the icon of @action.
1586  *
1587  * Since: 2.16
1588  */
1589 void
1590 gtk_action_set_gicon (GtkAction *action,
1591                       GIcon     *icon)
1592 {
1593   g_return_if_fail (GTK_IS_ACTION (action));
1594
1595   if (action->private_data->gicon)
1596     g_object_unref (action->private_data->gicon);
1597
1598   action->private_data->gicon = icon;
1599
1600   if (action->private_data->gicon)
1601     g_object_ref (action->private_data->gicon);
1602
1603   g_object_notify (G_OBJECT (action), "gicon");
1604 }
1605
1606 /**
1607  * gtk_action_get_gicon:
1608  * @action: a #GtkAction
1609  *
1610  * Gets the gicon of @action.
1611  *
1612  * Returns: The action's #GIcon if one is set.
1613  *
1614  * Since: 2.16
1615  */
1616 GIcon *
1617 gtk_action_get_gicon (GtkAction *action)
1618 {
1619   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1620
1621   return action->private_data->gicon;
1622 }
1623
1624 static void
1625 closure_accel_activate (GClosure     *closure,
1626                         GValue       *return_value,
1627                         guint         n_param_values,
1628                         const GValue *param_values,
1629                         gpointer      invocation_hint,
1630                         gpointer      marshal_data)
1631 {
1632   if (gtk_action_is_sensitive (GTK_ACTION (closure->data)))
1633     {
1634       _gtk_action_emit_activate (GTK_ACTION (closure->data));
1635       
1636       /* we handled the accelerator */
1637       g_value_set_boolean (return_value, TRUE);
1638     }
1639 }
1640
1641 static void
1642 gtk_action_set_action_group (GtkAction      *action,
1643                              GtkActionGroup *action_group)
1644 {
1645   if (action->private_data->action_group == NULL)
1646     g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1647   else
1648     g_return_if_fail (action_group == NULL);
1649
1650   action->private_data->action_group = action_group;
1651 }
1652
1653 /**
1654  * gtk_action_set_accel_path:
1655  * @action: the action object
1656  * @accel_path: the accelerator path
1657  *
1658  * Sets the accel path for this action.  All proxy widgets associated
1659  * with the action will have this accel path, so that their
1660  * accelerators are consistent.
1661  *
1662  * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
1663  * pass a static string, you can save some memory by interning it first with 
1664  * g_intern_static_string().
1665  *
1666  * Since: 2.4
1667  */
1668 void
1669 gtk_action_set_accel_path (GtkAction   *action, 
1670                            const gchar *accel_path)
1671 {
1672   g_return_if_fail (GTK_IS_ACTION (action));
1673
1674   action->private_data->accel_quark = g_quark_from_string (accel_path);
1675 }
1676
1677 /**
1678  * gtk_action_get_accel_path:
1679  * @action: the action object
1680  *
1681  * Returns the accel path for this action.  
1682  *
1683  * Since: 2.6
1684  *
1685  * Returns: the accel path for this action, or %NULL
1686  *   if none is set. The returned string is owned by GTK+ 
1687  *   and must not be freed or modified.
1688  */
1689 G_CONST_RETURN gchar *
1690 gtk_action_get_accel_path (GtkAction *action)
1691 {
1692   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1693
1694   if (action->private_data->accel_quark)
1695     return g_quark_to_string (action->private_data->accel_quark);
1696   else
1697     return NULL;
1698 }
1699
1700 /**
1701  * gtk_action_get_accel_closure:
1702  * @action: the action object
1703  *
1704  * Returns the accel closure for this action.
1705  *
1706  * Since: 2.8
1707  *
1708  * Returns: the accel closure for this action. The returned closure is
1709  *          owned by GTK+ and must not be unreffed or modified.
1710  */
1711 GClosure *
1712 gtk_action_get_accel_closure (GtkAction *action)
1713 {
1714   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1715
1716   return action->private_data->accel_closure;
1717 }
1718
1719
1720 /**
1721  * gtk_action_set_accel_group:
1722  * @action: the action object
1723  * @accel_group: (allow-none): a #GtkAccelGroup or %NULL
1724  *
1725  * Sets the #GtkAccelGroup in which the accelerator for this action
1726  * will be installed.
1727  *
1728  * Since: 2.4
1729  **/
1730 void
1731 gtk_action_set_accel_group (GtkAction     *action,
1732                             GtkAccelGroup *accel_group)
1733 {
1734   g_return_if_fail (GTK_IS_ACTION (action));
1735   g_return_if_fail (accel_group == NULL || GTK_IS_ACCEL_GROUP (accel_group));
1736   
1737   if (accel_group)
1738     g_object_ref (accel_group);
1739   if (action->private_data->accel_group)
1740     g_object_unref (action->private_data->accel_group);
1741
1742   action->private_data->accel_group = accel_group;
1743 }
1744
1745 /**
1746  * gtk_action_connect_accelerator:
1747  * @action: a #GtkAction
1748  * 
1749  * Installs the accelerator for @action if @action has an
1750  * accel path and group. See gtk_action_set_accel_path() and 
1751  * gtk_action_set_accel_group()
1752  *
1753  * Since multiple proxies may independently trigger the installation
1754  * of the accelerator, the @action counts the number of times this
1755  * function has been called and doesn't remove the accelerator until
1756  * gtk_action_disconnect_accelerator() has been called as many times.
1757  *
1758  * Since: 2.4
1759  **/
1760 void 
1761 gtk_action_connect_accelerator (GtkAction *action)
1762 {
1763   g_return_if_fail (GTK_IS_ACTION (action));
1764
1765   if (!action->private_data->accel_quark ||
1766       !action->private_data->accel_group)
1767     return;
1768
1769   if (action->private_data->accel_count == 0)
1770     {
1771       const gchar *accel_path = 
1772         g_quark_to_string (action->private_data->accel_quark);
1773       
1774       gtk_accel_group_connect_by_path (action->private_data->accel_group,
1775                                        accel_path,
1776                                        action->private_data->accel_closure);
1777     }
1778
1779   action->private_data->accel_count++;
1780 }
1781
1782 /**
1783  * gtk_action_disconnect_accelerator:
1784  * @action: a #GtkAction
1785  * 
1786  * Undoes the effect of one call to gtk_action_connect_accelerator().
1787  *
1788  * Since: 2.4
1789  **/
1790 void 
1791 gtk_action_disconnect_accelerator (GtkAction *action)
1792 {
1793   g_return_if_fail (GTK_IS_ACTION (action));
1794
1795   if (!action->private_data->accel_quark ||
1796       !action->private_data->accel_group)
1797     return;
1798
1799   action->private_data->accel_count--;
1800
1801   if (action->private_data->accel_count == 0)
1802     gtk_accel_group_disconnect (action->private_data->accel_group,
1803                                 action->private_data->accel_closure);
1804 }
1805
1806 /**
1807  * gtk_action_create_menu:
1808  * @action: a #GtkAction
1809  *
1810  * If @action provides a #GtkMenu widget as a submenu for the menu
1811  * item or the toolbar item it creates, this function returns an
1812  * instance of that menu.
1813  *
1814  * Return value: the menu item provided by the action, or %NULL.
1815  *
1816  * Since: 2.12
1817  */
1818 GtkWidget *
1819 gtk_action_create_menu (GtkAction *action)
1820 {
1821   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1822
1823   if (GTK_ACTION_GET_CLASS (action)->create_menu)
1824     return GTK_ACTION_GET_CLASS (action)->create_menu (action);
1825
1826   return NULL;
1827 }