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