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