]> Pileus Git - ~andy/gtk/blob - gtk/gtkaction.c
Add setters and getters for GtkAction properties, in preparation for bug
[~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 #include "config.h"
32
33 #include "gtkaction.h"
34 #include "gtkactiongroup.h"
35 #include "gtkaccellabel.h"
36 #include "gtkbutton.h"
37 #include "gtkiconfactory.h"
38 #include "gtkimage.h"
39 #include "gtkimagemenuitem.h"
40 #include "gtkintl.h"
41 #include "gtklabel.h"
42 #include "gtkmarshalers.h"
43 #include "gtkmenuitem.h"
44 #include "gtkstock.h"
45 #include "gtktearoffmenuitem.h"
46 #include "gtktoolbutton.h"
47 #include "gtktoolbar.h"
48 #include "gtkprivate.h"
49 #include "gtkbuildable.h"
50 #include "gtkalias.h"
51
52
53 #define GTK_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION, GtkActionPrivate))
54
55 struct _GtkActionPrivate 
56 {
57   const gchar *name; /* interned */
58   gchar *label;
59   gchar *short_label;
60   gchar *tooltip;
61   gchar *stock_id; /* stock icon */
62   gchar *icon_name; /* themed icon */
63   GIcon *gicon;
64
65   guint sensitive          : 1;
66   guint visible            : 1;
67   guint label_set          : 1; /* these two used so we can set label */
68   guint short_label_set    : 1; /* based on stock id */
69   guint visible_horizontal : 1;
70   guint visible_vertical   : 1;
71   guint is_important       : 1;
72   guint hide_if_empty      : 1;
73   guint visible_overflown  : 1;
74
75   /* accelerator */
76   guint          accel_count;
77   GtkAccelGroup *accel_group;
78   GClosure      *accel_closure;
79   GQuark         accel_quark;
80
81   GtkActionGroup *action_group;
82
83   /* list of proxy widgets */
84   GSList *proxies;
85 };
86
87 enum 
88 {
89   ACTIVATE,
90   LAST_SIGNAL
91 };
92
93 enum 
94 {
95   PROP_0,
96   PROP_NAME,
97   PROP_LABEL,
98   PROP_SHORT_LABEL,
99   PROP_TOOLTIP,
100   PROP_STOCK_ID,
101   PROP_ICON_NAME,
102   PROP_GICON,
103   PROP_VISIBLE_HORIZONTAL,
104   PROP_VISIBLE_VERTICAL,
105   PROP_VISIBLE_OVERFLOWN,
106   PROP_IS_IMPORTANT,
107   PROP_HIDE_IF_EMPTY,
108   PROP_SENSITIVE,
109   PROP_VISIBLE,
110   PROP_ACTION_GROUP
111 };
112
113 /* GtkBuildable */
114 static void gtk_action_buildable_init             (GtkBuildableIface *iface);
115 static void gtk_action_buildable_set_name         (GtkBuildable *buildable,
116                                                    const gchar  *name);
117 static const gchar* gtk_action_buildable_get_name (GtkBuildable *buildable);
118
119 G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
120                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
121                                                 gtk_action_buildable_init))
122
123
124 static GQuark      quark_gtk_action_proxy  = 0;
125 static const gchar gtk_action_proxy_key[] = "gtk-action";
126
127 static void gtk_action_finalize     (GObject *object);
128 static void gtk_action_set_property (GObject         *object,
129                                      guint            prop_id,
130                                      const GValue    *value,
131                                      GParamSpec      *pspec);
132 static void gtk_action_get_property (GObject         *object,
133                                      guint            prop_id,
134                                      GValue          *value,
135                                      GParamSpec      *pspec);
136 static void gtk_action_set_action_group (GtkAction      *action,
137                                          GtkActionGroup *action_group);
138 static void gtk_action_sync_tooltip     (GtkAction      *action,
139                                          GtkWidget      *proxy);
140
141 static GtkWidget *create_menu_item    (GtkAction *action);
142 static GtkWidget *create_tool_item    (GtkAction *action);
143 static void       connect_proxy       (GtkAction *action,
144                                        GtkWidget *proxy);
145 static void       disconnect_proxy    (GtkAction *action,
146                                        GtkWidget *proxy);
147
148 static void       closure_accel_activate (GClosure     *closure,
149                                           GValue       *return_value,
150                                           guint         n_param_values,
151                                           const GValue *param_values,
152                                           gpointer      invocation_hint,
153                                           gpointer      marshal_data);
154
155 static guint         action_signals[LAST_SIGNAL] = { 0 };
156
157
158 static void
159 gtk_action_class_init (GtkActionClass *klass)
160 {
161   GObjectClass *gobject_class;
162
163   quark_gtk_action_proxy = g_quark_from_static_string (gtk_action_proxy_key);
164
165   gobject_class = G_OBJECT_CLASS (klass);
166
167   gobject_class->finalize     = gtk_action_finalize;
168   gobject_class->set_property = gtk_action_set_property;
169   gobject_class->get_property = gtk_action_get_property;
170
171   klass->activate = NULL;
172
173   klass->create_menu_item = create_menu_item;
174   klass->create_tool_item = create_tool_item;
175   klass->create_menu = NULL;
176   klass->connect_proxy = connect_proxy;
177   klass->disconnect_proxy = disconnect_proxy;
178
179   klass->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
180   klass->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
181
182   g_object_class_install_property (gobject_class,
183                                    PROP_NAME,
184                                    g_param_spec_string ("name",
185                                                         P_("Name"),
186                                                         P_("A unique name for the action."),
187                                                         NULL,
188                                                         GTK_PARAM_READWRITE | 
189                                                         G_PARAM_CONSTRUCT_ONLY));
190
191   /**
192    * GtkAction:label:
193    *
194    * The label used for menu items and buttons that activate
195    * this action. If the label is %NULL, GTK+ uses the stock 
196    * label specified via the stock-id property.
197    */
198   g_object_class_install_property (gobject_class,
199                                    PROP_LABEL,
200                                    g_param_spec_string ("label",
201                                                         P_("Label"),
202                                                         P_("The label used for menu items and buttons "
203                                                            "that activate this action."),
204                                                         NULL,
205                                                         GTK_PARAM_READWRITE));
206
207   /**
208    * GtkAction:short-label:
209    *
210    * A shorter label that may be used on toolbar buttons.
211    */
212   g_object_class_install_property (gobject_class,
213                                    PROP_SHORT_LABEL,
214                                    g_param_spec_string ("short-label",
215                                                         P_("Short label"),
216                                                         P_("A shorter label that may be used on toolbar buttons."),
217                                                         NULL,
218                                                         GTK_PARAM_READWRITE));
219
220
221   g_object_class_install_property (gobject_class,
222                                    PROP_TOOLTIP,
223                                    g_param_spec_string ("tooltip",
224                                                         P_("Tooltip"),
225                                                         P_("A tooltip for this action."),
226                                                         NULL,
227                                                         GTK_PARAM_READWRITE));
228
229   /**
230    * GtkAction:stock-id:
231    *
232    * The stock icon displayed in widgets representing this action.
233    */
234   g_object_class_install_property (gobject_class,
235                                    PROP_STOCK_ID,
236                                    g_param_spec_string ("stock-id",
237                                                         P_("Stock Icon"),
238                                                         P_("The stock icon displayed in widgets representing "
239                                                            "this action."),
240                                                         NULL,
241                                                         GTK_PARAM_READWRITE));
242   /**
243    * GtkAction:gicon:
244    *
245    * The #GIcon displayed in the #GtkAction.
246    *
247    * Note that the stock icon is preferred, if the #GtkAction:stock-id 
248    * property holds the id of an existing stock icon.
249    *
250    * Since: 2.16
251    */
252   g_object_class_install_property (gobject_class,
253                                    PROP_GICON,
254                                    g_param_spec_object ("gicon",
255                                                         P_("GIcon"),
256                                                         P_("The GIcon being displayed"),
257                                                         G_TYPE_ICON,
258                                                         GTK_PARAM_READWRITE));                                                  
259   /**
260    * GtkAction:icon-name:
261    *
262    * The name of the icon from the icon theme. 
263    * 
264    * Note that the stock icon is preferred, if the #GtkAction:stock-id 
265    * property holds the id of an existing stock icon, and the #GIcon is
266    * preferred if the #GtkAction:gicon property is set. 
267    *
268    * Since: 2.10
269    */
270   g_object_class_install_property (gobject_class,
271                                    PROP_ICON_NAME,
272                                    g_param_spec_string ("icon-name",
273                                                         P_("Icon Name"),
274                                                         P_("The name of the icon from the icon theme"),
275                                                         NULL,
276                                                         GTK_PARAM_READWRITE));
277
278   g_object_class_install_property (gobject_class,
279                                    PROP_VISIBLE_HORIZONTAL,
280                                    g_param_spec_boolean ("visible-horizontal",
281                                                          P_("Visible when horizontal"),
282                                                          P_("Whether the toolbar item is visible when the toolbar "
283                                                             "is in a horizontal orientation."),
284                                                          TRUE,
285                                                          GTK_PARAM_READWRITE));
286   /**
287    * GtkAction:visible-overflown:
288    *
289    * When %TRUE, toolitem proxies for this action are represented in the 
290    * toolbar overflow menu.
291    *
292    * Since: 2.6
293    */
294   g_object_class_install_property (gobject_class,
295                                    PROP_VISIBLE_OVERFLOWN,
296                                    g_param_spec_boolean ("visible-overflown",
297                                                          P_("Visible when overflown"),
298                                                          P_("When TRUE, toolitem proxies for this action "
299                                                             "are represented in the toolbar overflow menu."),
300                                                          TRUE,
301                                                          GTK_PARAM_READWRITE));
302   g_object_class_install_property (gobject_class,
303                                    PROP_VISIBLE_VERTICAL,
304                                    g_param_spec_boolean ("visible-vertical",
305                                                          P_("Visible when vertical"),
306                                                          P_("Whether the toolbar item is visible when the toolbar "
307                                                             "is in a vertical orientation."),
308                                                          TRUE,
309                                                          GTK_PARAM_READWRITE));
310   g_object_class_install_property (gobject_class,
311                                    PROP_IS_IMPORTANT,
312                                    g_param_spec_boolean ("is-important",
313                                                          P_("Is important"),
314                                                          P_("Whether the action is considered important. "
315                                                             "When TRUE, toolitem proxies for this action "
316                                                             "show text in GTK_TOOLBAR_BOTH_HORIZ mode."),
317                                                          FALSE,
318                                                          GTK_PARAM_READWRITE));
319   g_object_class_install_property (gobject_class,
320                                    PROP_HIDE_IF_EMPTY,
321                                    g_param_spec_boolean ("hide-if-empty",
322                                                          P_("Hide if empty"),
323                                                          P_("When TRUE, empty menu proxies for this action are hidden."),
324                                                          TRUE,
325                                                          GTK_PARAM_READWRITE));
326   g_object_class_install_property (gobject_class,
327                                    PROP_SENSITIVE,
328                                    g_param_spec_boolean ("sensitive",
329                                                          P_("Sensitive"),
330                                                          P_("Whether the action is enabled."),
331                                                          TRUE,
332                                                          GTK_PARAM_READWRITE));
333   g_object_class_install_property (gobject_class,
334                                    PROP_VISIBLE,
335                                    g_param_spec_boolean ("visible",
336                                                          P_("Visible"),
337                                                          P_("Whether the action is visible."),
338                                                          TRUE,
339                                                          GTK_PARAM_READWRITE));
340   g_object_class_install_property (gobject_class,
341                                    PROP_ACTION_GROUP,
342                                    g_param_spec_object ("action-group",
343                                                          P_("Action Group"),
344                                                          P_("The GtkActionGroup this GtkAction is associated with, or NULL (for internal use)."),
345                                                          GTK_TYPE_ACTION_GROUP,
346                                                          GTK_PARAM_READWRITE));
347
348   /**
349    * GtkAction::activate:
350    * @action: the #GtkAction
351    *
352    * The "activate" signal is emitted when the action is activated.
353    *
354    * Since: 2.4
355    */
356   action_signals[ACTIVATE] =
357     g_signal_new (I_("activate"),
358                   G_OBJECT_CLASS_TYPE (klass),
359                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
360                   G_STRUCT_OFFSET (GtkActionClass, activate),  NULL, NULL,
361                   g_cclosure_marshal_VOID__VOID,
362                   G_TYPE_NONE, 0);
363
364   g_type_class_add_private (gobject_class, sizeof (GtkActionPrivate));
365 }
366
367
368 static void
369 gtk_action_init (GtkAction *action)
370 {
371   action->private_data = GTK_ACTION_GET_PRIVATE (action);
372
373   action->private_data->name = NULL;
374   action->private_data->label = NULL;
375   action->private_data->short_label = NULL;
376   action->private_data->tooltip = NULL;
377   action->private_data->stock_id = NULL;
378   action->private_data->icon_name = NULL;
379   action->private_data->visible_horizontal = TRUE;
380   action->private_data->visible_vertical   = TRUE;
381   action->private_data->visible_overflown  = TRUE;
382   action->private_data->is_important = FALSE;
383   action->private_data->hide_if_empty = TRUE;
384
385   action->private_data->sensitive = TRUE;
386   action->private_data->visible = TRUE;
387
388   action->private_data->label_set = FALSE;
389   action->private_data->short_label_set = FALSE;
390
391   action->private_data->accel_count = 0;
392   action->private_data->accel_group = NULL;
393   action->private_data->accel_quark = 0;
394   action->private_data->accel_closure = 
395     g_closure_new_object (sizeof (GClosure), G_OBJECT (action));
396   g_closure_set_marshal (action->private_data->accel_closure, 
397                          closure_accel_activate);
398   g_closure_ref (action->private_data->accel_closure);
399   g_closure_sink (action->private_data->accel_closure);
400
401   action->private_data->action_group = NULL;
402
403   action->private_data->proxies = NULL;
404   action->private_data->gicon = NULL;  
405 }
406
407 static void
408 gtk_action_buildable_init (GtkBuildableIface *iface)
409 {
410   iface->set_name = gtk_action_buildable_set_name;
411   iface->get_name = gtk_action_buildable_get_name;
412 }
413
414 static void
415 gtk_action_buildable_set_name (GtkBuildable *buildable,
416                                const gchar  *name)
417 {
418   GtkAction *action = GTK_ACTION (buildable);
419
420   action->private_data->name = g_intern_string (name);
421 }
422
423 static const gchar *
424 gtk_action_buildable_get_name (GtkBuildable *buildable)
425 {
426   GtkAction *action = GTK_ACTION (buildable);
427
428   return action->private_data->name;
429 }
430
431 /**
432  * gtk_action_new:
433  * @name: A unique name for the action
434  * @label: the label displayed in menu items and on buttons, or %NULL
435  * @tooltip: a tooltip for the action, or %NULL
436  * @stock_id: the stock icon to display in widgets representing the
437  *   action, or %NULL
438  *
439  * Creates a new #GtkAction object. To add the action to a
440  * #GtkActionGroup and set the accelerator for the action,
441  * call gtk_action_group_add_action_with_accel().
442  * See <xref linkend="XML-UI"/> for information on allowed action
443  * names.
444  *
445  * Return value: a new #GtkAction
446  *
447  * Since: 2.4
448  */
449 GtkAction *
450 gtk_action_new (const gchar *name,
451                 const gchar *label,
452                 const gchar *tooltip,
453                 const gchar *stock_id)
454 {
455   g_return_val_if_fail (name != NULL, NULL);
456
457   return g_object_new (GTK_TYPE_ACTION,
458                        "name", name,
459                        "label", label,
460                        "tooltip", tooltip,
461                        "stock-id", stock_id,
462                        NULL);
463 }
464
465 static void
466 gtk_action_finalize (GObject *object)
467 {
468   GtkAction *action;
469   action = GTK_ACTION (object);
470
471   g_free (action->private_data->label);
472   g_free (action->private_data->short_label);
473   g_free (action->private_data->tooltip);
474   g_free (action->private_data->stock_id);
475   g_free (action->private_data->icon_name);
476   
477   if (action->private_data->gicon)
478     g_object_unref (action->private_data->gicon);
479
480   g_closure_unref (action->private_data->accel_closure);
481   if (action->private_data->accel_group)
482     g_object_unref (action->private_data->accel_group);
483
484   G_OBJECT_CLASS (gtk_action_parent_class)->finalize (object);  
485 }
486
487 static void
488 gtk_action_set_property (GObject         *object,
489                          guint            prop_id,
490                          const GValue    *value,
491                          GParamSpec      *pspec)
492 {
493   GtkAction *action;
494   
495   action = GTK_ACTION (object);
496
497   switch (prop_id)
498     {
499     case PROP_NAME:
500       action->private_data->name = g_intern_string (g_value_get_string (value));
501       break;
502     case PROP_LABEL:
503       gtk_action_set_label (action, g_value_get_string (value));
504       break;
505     case PROP_SHORT_LABEL:
506       gtk_action_set_short_label (action, g_value_get_string (value));
507       break;
508     case PROP_TOOLTIP:
509       gtk_action_set_tooltip (action, g_value_get_string (value));
510       break;
511     case PROP_STOCK_ID:
512       gtk_action_set_stock_id (action, g_value_get_string (value));
513       break;
514     case PROP_GICON:
515       gtk_action_set_gicon (action, g_value_get_object (value));
516       break;
517     case PROP_ICON_NAME:
518       gtk_action_set_icon_name (action, g_value_get_string (value));
519       break;
520     case PROP_VISIBLE_HORIZONTAL:
521       gtk_action_set_visible_horizontal (action, g_value_get_boolean (value));
522       break;
523     case PROP_VISIBLE_VERTICAL:
524       gtk_action_set_visible_vertical (action, g_value_get_boolean (value));
525       break;
526     case PROP_VISIBLE_OVERFLOWN:
527       action->private_data->visible_overflown = g_value_get_boolean (value);
528       break;
529     case PROP_IS_IMPORTANT:
530       gtk_action_set_is_important (action, g_value_get_boolean (value));
531       break;
532     case PROP_HIDE_IF_EMPTY:
533       action->private_data->hide_if_empty = g_value_get_boolean (value);
534       break;
535     case PROP_SENSITIVE:
536       gtk_action_set_sensitive (action, g_value_get_boolean (value));
537       break;
538     case PROP_VISIBLE:
539       gtk_action_set_visible (action, g_value_get_boolean (value));
540       break;
541     case PROP_ACTION_GROUP:
542       gtk_action_set_action_group (action, g_value_get_object (value));
543       break;
544     default:
545       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
546       break;
547     }
548 }
549
550 static void
551 gtk_action_get_property (GObject    *object,
552                          guint       prop_id,
553                          GValue     *value,
554                          GParamSpec *pspec)
555 {
556   GtkAction *action;
557
558   action = GTK_ACTION (object);
559
560   switch (prop_id)
561     {
562     case PROP_NAME:
563       g_value_set_static_string (value, action->private_data->name);
564       break;
565     case PROP_LABEL:
566       g_value_set_string (value, action->private_data->label);
567       break;
568     case PROP_SHORT_LABEL:
569       g_value_set_string (value, action->private_data->short_label);
570       break;
571     case PROP_TOOLTIP:
572       g_value_set_string (value, action->private_data->tooltip);
573       break;
574     case PROP_STOCK_ID:
575       g_value_set_string (value, action->private_data->stock_id);
576       break;
577     case PROP_ICON_NAME:
578       g_value_set_string (value, action->private_data->icon_name);
579       break;
580     case PROP_GICON:
581       g_value_set_object (value, action->private_data->gicon);
582       break;
583     case PROP_VISIBLE_HORIZONTAL:
584       g_value_set_boolean (value, action->private_data->visible_horizontal);
585       break;
586     case PROP_VISIBLE_VERTICAL:
587       g_value_set_boolean (value, action->private_data->visible_vertical);
588       break;
589     case PROP_VISIBLE_OVERFLOWN:
590       g_value_set_boolean (value, action->private_data->visible_overflown);
591       break;
592     case PROP_IS_IMPORTANT:
593       g_value_set_boolean (value, action->private_data->is_important);
594       break;
595     case PROP_HIDE_IF_EMPTY:
596       g_value_set_boolean (value, action->private_data->hide_if_empty);
597       break;
598     case PROP_SENSITIVE:
599       g_value_set_boolean (value, action->private_data->sensitive);
600       break;
601     case PROP_VISIBLE:
602       g_value_set_boolean (value, action->private_data->visible);
603       break;
604     case PROP_ACTION_GROUP:
605       g_value_set_object (value, action->private_data->action_group);
606       break;
607     default:
608       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
609       break;
610     }
611 }
612
613 static GtkWidget *
614 create_menu_item (GtkAction *action)
615 {
616   GType menu_item_type;
617
618   menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type;
619
620   return g_object_new (menu_item_type, NULL);
621 }
622
623 static GtkWidget *
624 create_tool_item (GtkAction *action)
625 {
626   GType toolbar_item_type;
627
628   toolbar_item_type = GTK_ACTION_GET_CLASS (action)->toolbar_item_type;
629
630   return g_object_new (toolbar_item_type, NULL);
631 }
632
633 static void
634 remove_proxy (GtkAction *action,
635               GtkWidget *proxy)
636 {
637   if (GTK_IS_MENU_ITEM (proxy))
638     gtk_action_disconnect_accelerator (action);
639   
640   action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
641 }
642
643 /**
644  * _gtk_action_sync_menu_visible:
645  * @action: a #GtkAction, or %NULL to determine the action from @proxy
646  * @proxy: a proxy menu item
647  * @empty: whether the submenu attached to @proxy is empty
648  * 
649  * Updates the visibility of @proxy from the visibility of @action
650  * according to the following rules:
651  * <itemizedlist>
652  * <listitem><para>if @action is invisible, @proxy is too
653  * </para></listitem>
654  * <listitem><para>if @empty is %TRUE, hide @proxy unless the "hide-if-empty" 
655  *   property of @action indicates otherwise
656  * </para></listitem>
657  * </itemizedlist>
658  * 
659  * This function is used in the implementation of #GtkUIManager.
660  **/
661 void
662 _gtk_action_sync_menu_visible (GtkAction *action,
663                                GtkWidget *proxy,
664                                gboolean   empty)
665 {
666   gboolean visible = TRUE;
667   gboolean hide_if_empty = TRUE;
668
669   g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
670   g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
671
672   if (action == NULL)
673     action = g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy);
674
675   if (action)
676     {
677       /* a GtkMenu for a <popup/> doesn't have to have an action */
678       visible = gtk_action_is_visible (action);
679       hide_if_empty = action->private_data->hide_if_empty;
680     }
681
682   if (visible && !(empty && hide_if_empty))
683     gtk_widget_show (proxy);
684   else
685     gtk_widget_hide (proxy);
686 }
687
688 gboolean _gtk_menu_is_empty (GtkWidget *menu);
689
690 static gboolean
691 gtk_action_create_menu_proxy (GtkToolItem *tool_item, 
692                               GtkAction   *action)
693 {
694   GtkWidget *menu_item;
695   
696   if (action->private_data->visible_overflown)
697     {
698       menu_item = gtk_action_create_menu_item (action);
699
700       g_object_ref_sink (menu_item);
701       
702       gtk_tool_item_set_proxy_menu_item (tool_item, 
703                                          "gtk-action-menu-item", menu_item);
704       g_object_unref (menu_item);
705     }
706   else
707     gtk_tool_item_set_proxy_menu_item (tool_item, 
708                                        "gtk-action-menu-item", NULL);
709
710   return TRUE;
711 }
712
713 static void
714 connect_proxy (GtkAction     *action, 
715                GtkWidget     *proxy)
716 {
717   g_object_ref (action);
718   g_object_set_qdata_full (G_OBJECT (proxy), quark_gtk_action_proxy, action,
719                            g_object_unref);
720
721   /* add this widget to the list of proxies */
722   action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
723   g_object_weak_ref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
724   
725   gtk_widget_set_sensitive (proxy, gtk_action_is_sensitive (action));
726   if (gtk_action_is_visible (action))
727     gtk_widget_show (proxy);
728   else
729     gtk_widget_hide (proxy);
730   gtk_widget_set_no_show_all (proxy, TRUE);
731
732   if (GTK_IS_MENU_ITEM (proxy))
733     {
734       GtkWidget *label;
735       /* menu item specific synchronisers ... */
736       
737       if (action->private_data->accel_quark)
738         {
739           gtk_action_connect_accelerator (action);
740           gtk_menu_item_set_accel_path (GTK_MENU_ITEM (proxy),
741                                         g_quark_to_string (action->private_data->accel_quark));
742         }
743       
744       label = GTK_BIN (proxy)->child;
745
746       /* make sure label is a label */
747       if (label && !GTK_IS_LABEL (label))
748         {
749           gtk_container_remove (GTK_CONTAINER (proxy), label);
750           label = NULL;
751         }
752
753       if (!label)
754         label = g_object_new (GTK_TYPE_ACCEL_LABEL,
755                               "use-underline", TRUE,
756                               "xalign", 0.0,
757                               "visible", TRUE,
758                               "parent", proxy,
759                               NULL);
760       
761       if (GTK_IS_ACCEL_LABEL (label) && action->private_data->accel_quark)
762         g_object_set (label,
763                       "accel-closure", action->private_data->accel_closure,
764                       NULL);
765
766       gtk_label_set_label (GTK_LABEL (label), action->private_data->label);
767
768       if (GTK_IS_IMAGE_MENU_ITEM (proxy))
769         {
770           GtkWidget *image;
771
772           image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
773           if (image && !GTK_IS_IMAGE (image))
774             {
775               gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy), NULL);
776               image = NULL;
777             }
778           if (!image)
779             {
780               image = gtk_image_new ();
781               gtk_widget_show (image);
782               gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),
783                                              image);
784             }
785           
786           if (action->private_data->stock_id &&
787               gtk_icon_factory_lookup_default (action->private_data->stock_id))
788             gtk_image_set_from_stock (GTK_IMAGE (image),
789                                       action->private_data->stock_id, GTK_ICON_SIZE_MENU);
790           else if (action->private_data->gicon)
791             gtk_image_set_from_gicon (GTK_IMAGE (image),
792                                       action->private_data->gicon, GTK_ICON_SIZE_MENU);
793           else if (action->private_data->icon_name)
794             gtk_image_set_from_icon_name (GTK_IMAGE (image),
795                                           action->private_data->icon_name, GTK_ICON_SIZE_MENU);
796           else
797             gtk_image_clear (GTK_IMAGE (image));
798         }
799       
800       if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)) == NULL)
801         g_signal_connect_object (proxy, "activate",
802                                  G_CALLBACK (gtk_action_activate), action,
803                                  G_CONNECT_SWAPPED);
804
805     }
806   else if (GTK_IS_TOOL_ITEM (proxy))
807     {
808       /* toolbar button specific synchronisers ... */
809       if (GTK_IS_TOOL_BUTTON (proxy))
810         {
811           GtkWidget *image;
812           GtkIconSize icon_size;
813
814           g_object_set (proxy,
815                         "visible-horizontal", action->private_data->visible_horizontal,
816                         "visible-vertical", action->private_data->visible_vertical,
817                         "is-important", action->private_data->is_important,
818                         "label", action->private_data->short_label,
819                         "use-underline", TRUE,
820                         "stock-id", action->private_data->stock_id,
821                         "icon-name", action->private_data->icon_name,
822                         NULL);
823            
824           if (action->private_data->stock_id &&
825               gtk_icon_factory_lookup_default (action->private_data->stock_id))
826             {
827               /* use the stock icon */
828               gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), NULL);
829             }
830           else if (action->private_data->gicon)
831             {
832               icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (proxy));
833               image = gtk_tool_button_get_icon_widget (GTK_TOOL_BUTTON (proxy));
834               if (!image)
835                 {
836                   image = gtk_image_new ();
837                   gtk_widget_show (image);
838                   gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), 
839                                                    image);
840                 }
841
842               gtk_image_set_from_gicon (GTK_IMAGE (image),
843                                         action->private_data->gicon, 
844                                         icon_size);
845             }
846
847           g_signal_connect_object (proxy, "clicked",
848                                    G_CALLBACK (gtk_action_activate), action,
849                                    G_CONNECT_SWAPPED);
850         }
851       else 
852         {
853            g_object_set (proxy,
854                          "visible-horizontal", action->private_data->visible_horizontal,
855                          "visible-vertical", action->private_data->visible_vertical,
856                          "is-important", action->private_data->is_important,
857                          NULL);
858        }
859
860       gtk_action_sync_tooltip (action, proxy);
861
862       g_signal_connect_object (proxy, "create-menu-proxy",
863                                G_CALLBACK (gtk_action_create_menu_proxy),
864                                action, 0);
865
866       gtk_tool_item_rebuild_menu (GTK_TOOL_ITEM (proxy));
867     }
868   else if (GTK_IS_BUTTON (proxy))
869     {
870       /* button specific synchronisers ... */
871       if (gtk_button_get_use_stock (GTK_BUTTON (proxy)))
872         {
873           /* synchronise stock-id */
874           g_object_set (proxy,
875                         "label", action->private_data->stock_id,
876                         NULL);
877         }
878       else 
879         {
880           GtkWidget *image;
881
882           image = gtk_button_get_image (GTK_BUTTON (proxy));
883
884           if (GTK_IS_IMAGE (image) ||
885               GTK_BIN (proxy)->child == NULL || 
886               GTK_IS_LABEL (GTK_BIN (proxy)->child))
887             {
888               /* synchronise the label */
889               g_object_set (proxy,
890                             "label", action->private_data->short_label,
891                             "use-underline", TRUE,
892                             NULL);
893             }
894
895           if (GTK_IS_IMAGE (image) &&
896               (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
897                gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
898             gtk_image_set_from_gicon (GTK_IMAGE (image),
899                                       action->private_data->gicon, GTK_ICON_SIZE_MENU);
900           else if (GTK_IS_IMAGE (image) &&
901                    (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
902                     gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
903             gtk_image_set_from_icon_name (GTK_IMAGE (image),
904                                           action->private_data->icon_name, GTK_ICON_SIZE_MENU);
905         }
906       /* we leave the button alone if there is a custom child */
907       g_signal_connect_object (proxy, "clicked",
908                                G_CALLBACK (gtk_action_activate), action,
909                                G_CONNECT_SWAPPED);
910     }
911
912   if (action->private_data->action_group)
913     _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
914 }
915
916 static void
917 disconnect_proxy (GtkAction *action, 
918                   GtkWidget *proxy)
919 {
920   g_object_set_qdata (G_OBJECT (proxy), quark_gtk_action_proxy, NULL);
921
922   g_object_weak_unref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
923   remove_proxy (action, proxy);
924
925   /* disconnect the activate handler */
926   g_signal_handlers_disconnect_by_func (proxy,
927                                         G_CALLBACK (gtk_action_activate),
928                                         action);
929
930   /* toolbar button specific synchronisers ... */
931   g_signal_handlers_disconnect_by_func (proxy,
932                                         G_CALLBACK (gtk_action_create_menu_proxy),
933                                         action);
934
935   if (action->private_data->action_group)
936     _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
937 }
938
939 void
940 _gtk_action_emit_activate (GtkAction *action)
941 {
942   GtkActionGroup *group = action->private_data->action_group;
943
944   if (group != NULL) 
945     {
946       g_object_ref (group);
947       _gtk_action_group_emit_pre_activate (group, action);
948     }
949
950     g_signal_emit (action, action_signals[ACTIVATE], 0);
951
952   if (group != NULL) 
953     {
954       _gtk_action_group_emit_post_activate (group, action);
955       g_object_unref (group);
956     }
957 }
958
959 /**
960  * gtk_action_activate:
961  * @action: the action object
962  *
963  * Emits the "activate" signal on the specified action, if it isn't 
964  * insensitive. This gets called by the proxy widgets when they get 
965  * activated.
966  *
967  * It can also be used to manually activate an action.
968  *
969  * Since: 2.4
970  */
971 void
972 gtk_action_activate (GtkAction *action)
973 {
974   g_return_if_fail (GTK_IS_ACTION (action));
975   
976   if (gtk_action_is_sensitive (action))
977     _gtk_action_emit_activate (action);
978 }
979
980 /**
981  * gtk_action_create_icon:
982  * @action: the action object
983  * @icon_size: the size of the icon that should be created.
984  *
985  * This function is intended for use by action implementations to
986  * create icons displayed in the proxy widgets.
987  *
988  * Returns: a widget that displays the icon for this action.
989  *
990  * Since: 2.4
991  */
992 GtkWidget *
993 gtk_action_create_icon (GtkAction *action, GtkIconSize icon_size)
994 {
995   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
996
997   if (action->private_data->stock_id &&
998       gtk_icon_factory_lookup_default (action->private_data->stock_id))
999     return gtk_image_new_from_stock (action->private_data->stock_id, icon_size);
1000   else if (action->private_data->gicon)
1001     return gtk_image_new_from_gicon (action->private_data->gicon, icon_size);
1002   else if (action->private_data->icon_name)
1003     return gtk_image_new_from_icon_name (action->private_data->icon_name, icon_size);
1004   else
1005     return NULL;
1006 }
1007
1008 /**
1009  * gtk_action_create_menu_item:
1010  * @action: the action object
1011  *
1012  * Creates a menu item widget that proxies for the given action.
1013  *
1014  * Returns: a menu item connected to the action.
1015  *
1016  * Since: 2.4
1017  */
1018 GtkWidget *
1019 gtk_action_create_menu_item (GtkAction *action)
1020 {
1021   GtkWidget *menu_item;
1022
1023   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1024
1025   menu_item = GTK_ACTION_GET_CLASS (action)->create_menu_item (action);
1026
1027   GTK_ACTION_GET_CLASS (action)->connect_proxy (action, menu_item);
1028
1029   return menu_item;
1030 }
1031
1032 /**
1033  * gtk_action_create_tool_item:
1034  * @action: the action object
1035  *
1036  * Creates a toolbar item widget that proxies for the given action.
1037  *
1038  * Returns: a toolbar item connected to the action.
1039  *
1040  * Since: 2.4
1041  */
1042 GtkWidget *
1043 gtk_action_create_tool_item (GtkAction *action)
1044 {
1045   GtkWidget *button;
1046
1047   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1048
1049   button = GTK_ACTION_GET_CLASS (action)->create_tool_item (action);
1050
1051   GTK_ACTION_GET_CLASS (action)->connect_proxy (action, button);
1052
1053   return button;
1054 }
1055
1056 /**
1057  * gtk_action_connect_proxy:
1058  * @action: the action object
1059  * @proxy: the proxy widget
1060  *
1061  * Connects a widget to an action object as a proxy.  Synchronises 
1062  * various properties of the action with the widget (such as label 
1063  * text, icon, tooltip, etc), and attaches a callback so that the 
1064  * action gets activated when the proxy widget does.
1065  *
1066  * If the widget is already connected to an action, it is disconnected
1067  * first.
1068  *
1069  * Since: 2.4
1070  */
1071 void
1072 gtk_action_connect_proxy (GtkAction *action,
1073                           GtkWidget *proxy)
1074 {
1075   GtkAction *prev_action;
1076
1077   g_return_if_fail (GTK_IS_ACTION (action));
1078   g_return_if_fail (GTK_IS_WIDGET (proxy));
1079
1080   prev_action = g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy);
1081
1082   if (prev_action)
1083     GTK_ACTION_GET_CLASS (action)->disconnect_proxy (prev_action, proxy);
1084
1085   GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
1086 }
1087
1088 /**
1089  * gtk_action_disconnect_proxy:
1090  * @action: the action object
1091  * @proxy: the proxy widget
1092  *
1093  * Disconnects a proxy widget from an action.  
1094  * Does <emphasis>not</emphasis> destroy the widget, however.
1095  *
1096  * Since: 2.4
1097  */
1098 void
1099 gtk_action_disconnect_proxy (GtkAction *action,
1100                              GtkWidget *proxy)
1101 {
1102   g_return_if_fail (GTK_IS_ACTION (action));
1103   g_return_if_fail (GTK_IS_WIDGET (proxy));
1104
1105   g_return_if_fail (g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy) == action);
1106
1107   GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
1108 }
1109
1110 /**
1111  * gtk_action_get_proxies:
1112  * @action: the action object
1113  * 
1114  * Returns the proxy widgets for an action.
1115  * See also gtk_widget_get_action().
1116  * 
1117  * Return value: a #GSList of proxy widgets. The list is owned by GTK+
1118  * and must not be modified.
1119  *
1120  * Since: 2.4
1121  **/
1122 GSList*
1123 gtk_action_get_proxies (GtkAction *action)
1124 {
1125   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1126
1127   return action->private_data->proxies;
1128 }
1129
1130
1131 /**
1132  * gtk_widget_get_action:
1133  * @widget: a #GtkWidget
1134  *
1135  * Returns the #GtkAction that @widget is a proxy for. 
1136  * See also gtk_action_get_proxies().
1137  *
1138  * Returns: the action that a widget is a proxy for, or
1139  *  %NULL, if it is not attached to an action.
1140  *
1141  * Since: 2.10
1142  */
1143 GtkAction*
1144 gtk_widget_get_action (GtkWidget *widget)
1145 {
1146   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
1147   
1148   return g_object_get_qdata (G_OBJECT (widget), quark_gtk_action_proxy);
1149 }
1150
1151
1152 /**
1153  * gtk_action_get_name:
1154  * @action: the action object
1155  * 
1156  * Returns the name of the action.
1157  * 
1158  * Return value: the name of the action. The string belongs to GTK+ and should not
1159  *   be freed.
1160  *
1161  * Since: 2.4
1162  **/
1163 G_CONST_RETURN gchar *
1164 gtk_action_get_name (GtkAction *action)
1165 {
1166   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1167
1168   return action->private_data->name;
1169 }
1170
1171 /**
1172  * gtk_action_is_sensitive:
1173  * @action: the action object
1174  * 
1175  * Returns whether the action is effectively sensitive.
1176  *
1177  * Return value: %TRUE if the action and its associated action group 
1178  * are both sensitive.
1179  *
1180  * Since: 2.4
1181  **/
1182 gboolean
1183 gtk_action_is_sensitive (GtkAction *action)
1184 {
1185   GtkActionPrivate *priv;
1186   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1187
1188   priv = action->private_data;
1189   return priv->sensitive &&
1190     (priv->action_group == NULL ||
1191      gtk_action_group_get_sensitive (priv->action_group));
1192 }
1193
1194 /**
1195  * gtk_action_get_sensitive:
1196  * @action: the action object
1197  * 
1198  * Returns whether the action itself is sensitive. Note that this doesn't 
1199  * necessarily mean effective sensitivity. See gtk_action_is_sensitive() 
1200  * for that.
1201  *
1202  * Return value: %TRUE if the action itself is sensitive.
1203  *
1204  * Since: 2.4
1205  **/
1206 gboolean
1207 gtk_action_get_sensitive (GtkAction *action)
1208 {
1209   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1210
1211   return action->private_data->sensitive;
1212 }
1213
1214 void
1215 _gtk_action_sync_sensitive (GtkAction *action)
1216 {
1217   GSList *p;
1218   GtkWidget *proxy;
1219   gboolean sensitive;
1220
1221   sensitive = gtk_action_is_sensitive (action);
1222
1223   for (p = action->private_data->proxies; p; p = p->next)
1224     {
1225       proxy = (GtkWidget *)p->data;
1226       gtk_widget_set_sensitive (proxy, sensitive);
1227     }      
1228 }
1229
1230 /**
1231  * gtk_action_set_sensitive:
1232  * @action: the action object
1233  * @sensitive: %TRUE to make the action sensitive
1234  * 
1235  * Sets the ::sensitive property of the action to @sensitive. Note that 
1236  * this doesn't necessarily mean effective sensitivity. See 
1237  * gtk_action_is_sensitive() 
1238  * for that.
1239  *
1240  * Since: 2.6
1241  **/
1242 void
1243 gtk_action_set_sensitive (GtkAction *action,
1244                           gboolean   sensitive)
1245 {
1246   g_return_if_fail (GTK_IS_ACTION (action));
1247
1248   sensitive = sensitive != FALSE;
1249   
1250   if (action->private_data->sensitive != sensitive)
1251     {
1252       action->private_data->sensitive = sensitive;
1253
1254       _gtk_action_sync_sensitive (action);
1255
1256       g_object_notify (G_OBJECT (action), "sensitive");
1257     }
1258 }
1259
1260 /**
1261  * gtk_action_is_visible:
1262  * @action: the action object
1263  * 
1264  * Returns whether the action is effectively visible.
1265  *
1266  * Return value: %TRUE if the action and its associated action group 
1267  * are both visible.
1268  *
1269  * Since: 2.4
1270  **/
1271 gboolean
1272 gtk_action_is_visible (GtkAction *action)
1273 {
1274   GtkActionPrivate *priv;
1275   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1276
1277   priv = action->private_data;
1278   return priv->visible &&
1279     (priv->action_group == NULL ||
1280      gtk_action_group_get_visible (priv->action_group));
1281 }
1282
1283 /**
1284  * gtk_action_get_visible:
1285  * @action: the action object
1286  * 
1287  * Returns whether the action itself is visible. Note that this doesn't 
1288  * necessarily mean effective visibility. See gtk_action_is_sensitive() 
1289  * for that.
1290  *
1291  * Return value: %TRUE if the action itself is visible.
1292  *
1293  * Since: 2.4
1294  **/
1295 gboolean
1296 gtk_action_get_visible (GtkAction *action)
1297 {
1298   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1299
1300   return action->private_data->visible;
1301 }
1302
1303 void
1304 _gtk_action_sync_visible (GtkAction *action)
1305 {
1306   GSList *p;
1307   GtkWidget *proxy;
1308   GtkWidget *menu;
1309   gboolean visible;
1310
1311   visible = gtk_action_is_visible (action);
1312     
1313   for (p = action->private_data->proxies; p; p = p->next)
1314     {
1315       proxy = (GtkWidget *)p->data;
1316
1317       if (GTK_IS_MENU_ITEM (proxy))
1318         {
1319           menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
1320           
1321           _gtk_action_sync_menu_visible (action, proxy, _gtk_menu_is_empty (menu));
1322         }
1323       else
1324         {
1325           if (visible)
1326             gtk_widget_show (proxy);
1327           else
1328             gtk_widget_hide (proxy);
1329         }
1330     } 
1331 }
1332
1333 /**
1334  * gtk_action_set_visible:
1335  * @action: the action object
1336  * @visible: %TRUE to make the action visible
1337  * 
1338  * Sets the ::visible property of the action to @visible. Note that 
1339  * this doesn't necessarily mean effective visibility. See 
1340  * gtk_action_is_visible() 
1341  * for that.
1342  *
1343  * Since: 2.6
1344  **/
1345 void
1346 gtk_action_set_visible (GtkAction *action,
1347                         gboolean   visible)
1348 {
1349   g_return_if_fail (GTK_IS_ACTION (action));
1350
1351   visible = visible != FALSE;
1352   
1353   if (action->private_data->visible != visible)
1354     {
1355       action->private_data->visible = visible;
1356
1357       _gtk_action_sync_visible (action);
1358
1359       g_object_notify (G_OBJECT (action), "visible");
1360     }
1361 }
1362 /**
1363  * gtk_action_set_is_important:
1364  * @action: the action object
1365  * @is_important: %TRUE to make the action important
1366  *
1367  * Sets whether the action is important, this attribute is used
1368  * primarily by toolbar items to decide whether to show a label
1369  * or not.
1370  *
1371  * Since: 2.16
1372  */
1373 void 
1374 gtk_action_set_is_important (GtkAction *action,
1375                              gboolean   is_important)
1376 {
1377   GSList *p;
1378   GtkWidget *proxy;
1379
1380   g_return_if_fail (GTK_IS_ACTION (action));
1381
1382   is_important = is_important != FALSE;
1383   
1384   if (action->private_data->is_important != is_important)
1385     {
1386       action->private_data->is_important = is_important;
1387
1388       for (p = action->private_data->proxies; p; p = p->next)
1389         {
1390           proxy = (GtkWidget *)p->data;
1391
1392           if (GTK_IS_TOOL_ITEM (proxy))
1393             gtk_tool_item_set_is_important (GTK_TOOL_ITEM (proxy),
1394                                             is_important);
1395         }
1396       
1397       g_object_notify (G_OBJECT (action), "is-important");
1398     }  
1399 }
1400
1401 /**
1402  * gtk_action_get_is_important:
1403  * @action: a #GtkAction
1404  *
1405  * Checks whether @action is important or not
1406  *
1407  * Returns: whether @action is important
1408  *
1409  * Since: 2.16
1410  */
1411 gboolean
1412 gtk_action_get_is_important (GtkAction *action)
1413 {
1414   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1415
1416   return action->private_data->is_important;
1417 }
1418
1419 /**
1420  * gtk_action_set_label:
1421  * @action: a #GtkAction
1422  * @label: the label text to set
1423  *
1424  * Sets the label of @action.
1425  *
1426  * Since: 2.16
1427  */
1428 void 
1429 gtk_action_set_label (GtkAction   *action,
1430                       const gchar *label)
1431 {
1432   GSList *p;
1433   GtkWidget *proxy, *child;
1434   gchar *tmp;
1435   
1436   g_return_if_fail (GTK_IS_ACTION (action));
1437   
1438   tmp = action->private_data->label;
1439   action->private_data->label = g_strdup (label);
1440   g_free (tmp);
1441   action->private_data->label_set = (action->private_data->label != NULL);
1442   /* if label is unset, then use the label from the stock item */
1443   if (!action->private_data->label_set && action->private_data->stock_id)
1444     {
1445       GtkStockItem stock_item;
1446       
1447       if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1448         action->private_data->label = g_strdup (stock_item.label);
1449     }
1450   
1451   for (p = action->private_data->proxies; p; p = p->next)
1452     {
1453       proxy = (GtkWidget *)p->data;
1454       
1455       if (GTK_IS_MENU_ITEM (proxy))
1456         {
1457           child = GTK_BIN (proxy)->child;
1458           
1459           if (GTK_IS_LABEL (child))
1460             gtk_label_set_label (GTK_LABEL (child), 
1461                                  action->private_data->label);
1462         }
1463     }
1464   
1465   g_object_notify (G_OBJECT (action), "label");
1466   
1467   /* if short_label is unset, set short_label=label */
1468   if (!action->private_data->short_label_set)
1469     {
1470       gtk_action_set_short_label (action, action->private_data->label);
1471       action->private_data->short_label_set = FALSE;
1472     }
1473 }
1474
1475 /**
1476  * gtk_action_get_label:
1477  * @action: a #GtkAction
1478  *
1479  * Gets the label text of @action.
1480  *
1481  * Returns: the label text
1482  *
1483  * Since: 2.16
1484  */
1485 G_CONST_RETURN gchar *
1486 gtk_action_get_label (GtkAction *action)
1487 {
1488   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1489
1490   return action->private_data->label;
1491 }
1492
1493 /**
1494  * gtk_action_set_short_label:
1495  * @action: a #GtkAction
1496  * @label: the label text to set
1497  *
1498  * Sets a shorter label on @action.
1499  *
1500  * Since: 2.16
1501  */
1502 void 
1503 gtk_action_set_short_label (GtkAction   *action,
1504                             const gchar *label)
1505 {
1506   GSList *p;
1507   GtkWidget *proxy, *child;
1508   gchar *tmp;
1509
1510   g_return_if_fail (GTK_IS_ACTION (action));
1511
1512   tmp = action->private_data->short_label;
1513   action->private_data->short_label = g_strdup (label);
1514   g_free (tmp);
1515   action->private_data->short_label_set = (action->private_data->short_label != NULL);
1516   /* if short_label is unset, then use the value of label */
1517   if (!action->private_data->short_label_set)
1518     action->private_data->short_label = g_strdup (action->private_data->label);
1519
1520   for (p = action->private_data->proxies; p; p = p->next)
1521     {
1522       proxy = (GtkWidget *)p->data;
1523
1524       if (GTK_IS_TOOL_BUTTON (proxy))
1525         gtk_tool_button_set_label (GTK_TOOL_BUTTON (proxy),
1526                                    action->private_data->short_label);
1527       else if (GTK_IS_BUTTON (proxy) &&
1528                !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
1529         {
1530           GtkWidget *image;
1531
1532           child = GTK_BIN (proxy)->child;
1533
1534           image = gtk_button_get_image (GTK_BUTTON (proxy));
1535
1536           if (GTK_IS_IMAGE (image) ||
1537               child == NULL || GTK_IS_LABEL (child))
1538             gtk_button_set_label (GTK_BUTTON (proxy),
1539                                   action->private_data->short_label);
1540         }
1541     }
1542
1543   g_object_notify (G_OBJECT (action), "short-label");
1544 }
1545
1546 /**
1547  * gtk_action_get_short_label:
1548  * @action: a #GtkAction
1549  * @label: the label text to set
1550  *
1551  * Sets a shorter label on @action.
1552  *
1553  * Since: 2.16
1554  */
1555 G_CONST_RETURN gchar *
1556 gtk_action_get_short_label (GtkAction *action)
1557 {
1558   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1559
1560   g_object_notify (G_OBJECT (action), "short-label");
1561   return action->private_data->short_label;
1562 }
1563
1564 /**
1565  * gtk_action_set_visible_horizontal:
1566  * @action: a #GtkAction
1567  * @visible_horizontal: whether the action is visible horizontally
1568  *
1569  * Sets whether @action is visible when horizontal
1570  *
1571  * Since: 2.16
1572  */
1573 void 
1574 gtk_action_set_visible_horizontal (GtkAction *action,
1575                                    gboolean   visible_horizontal)
1576 {
1577   GSList *p;
1578   GtkWidget *proxy;
1579
1580   g_return_if_fail (GTK_IS_ACTION (action));
1581
1582   visible_horizontal = visible_horizontal != FALSE;
1583   
1584   if (action->private_data->visible_horizontal != visible_horizontal)
1585     {
1586       action->private_data->visible_horizontal = visible_horizontal;
1587
1588       for (p = action->private_data->proxies; p; p = p->next)
1589         {
1590           proxy = (GtkWidget *)p->data;
1591
1592           if (GTK_IS_TOOL_ITEM (proxy))
1593             gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (proxy),
1594                                                   visible_horizontal);
1595         }
1596       
1597       g_object_notify (G_OBJECT (action), "visible-horizontal");
1598     }  
1599 }
1600
1601 /**
1602  * gtk_action_get_visible_horizontal:
1603  * @action: a #GtkAction
1604  *
1605  * Checks whether @action is visible when horizontal
1606  *
1607  * Returns: whether @action is visible when horizontal
1608  *
1609  * Since: 2.16
1610  */
1611 gboolean
1612 gtk_action_get_visible_horizontal (GtkAction *action)
1613 {
1614   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1615
1616   return action->private_data->visible_horizontal;
1617 }
1618
1619 /**
1620  * gtk_action_set_visible_vertical:
1621  * @action: a #GtkAction
1622  * @visible_vertical: whether the action is visible vertically
1623  *
1624  * Sets whether @action is visible when vertical
1625  *
1626  * Since: 2.16
1627  */
1628 void 
1629 gtk_action_set_visible_vertical (GtkAction *action,
1630                                  gboolean   visible_vertical)
1631 {
1632   GSList *p;
1633   GtkWidget *proxy;
1634
1635   g_return_if_fail (GTK_IS_ACTION (action));
1636
1637   visible_vertical = visible_vertical != FALSE;
1638   
1639   if (action->private_data->visible_vertical != visible_vertical)
1640     {
1641       action->private_data->visible_vertical = visible_vertical;
1642
1643       for (p = action->private_data->proxies; p; p = p->next)
1644         {
1645           proxy = (GtkWidget *)p->data;
1646
1647           if (GTK_IS_TOOL_ITEM (proxy))
1648             gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (proxy),
1649                                                 visible_vertical);
1650         }
1651       
1652       g_object_notify (G_OBJECT (action), "visible-vertical");
1653     }  
1654 }
1655
1656 /**
1657  * gtk_action_get_visible_vertical:
1658  * @action: a #GtkAction
1659  *
1660  * Checks whether @action is visible when horizontal
1661  *
1662  * Returns: whether @action is visible when horizontal
1663  *
1664  * Since: 2.16
1665  */
1666 gboolean
1667 gtk_action_get_visible_vertical (GtkAction *action)
1668 {
1669   g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1670
1671   return action->private_data->visible_vertical;
1672 }
1673
1674 static void 
1675 gtk_action_sync_tooltip (GtkAction *action,
1676                          GtkWidget *proxy)
1677 {
1678   gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (proxy),
1679                                   action->private_data->tooltip);
1680 }
1681
1682 /**
1683  * gtk_action_set_tooltip:
1684  * @action: a #GtkAction
1685  * @tooltip: the tooltip text
1686  *
1687  * Sets the tooltip text on @action
1688  *
1689  * Since: 2.16
1690  */
1691 void 
1692 gtk_action_set_tooltip (GtkAction   *action,
1693                         const gchar *tooltip)
1694 {
1695   GSList *p;
1696   GtkWidget *proxy;
1697   gchar *tmp;
1698
1699   g_return_if_fail (GTK_IS_ACTION (action));
1700
1701   tmp = action->private_data->tooltip;
1702   action->private_data->tooltip = g_strdup (tooltip);
1703   g_free (tmp);
1704
1705   for (p = action->private_data->proxies; p; p = p->next)
1706     {
1707       proxy = (GtkWidget *)p->data;
1708
1709       if (GTK_IS_TOOL_ITEM (proxy))
1710         gtk_action_sync_tooltip (action, proxy);
1711     }
1712
1713   g_object_notify (G_OBJECT (action), "tooltip");
1714 }
1715
1716 /**
1717  * gtk_action_get_tooltip:
1718  * @action: a #GtkAction
1719  *
1720  * Gets the tooltip text of @action.
1721  *
1722 * Returns: the tooltip text
1723  *
1724  * Since: 2.16
1725  */
1726 G_CONST_RETURN gchar *
1727 gtk_action_get_tooltip (GtkAction *action)
1728 {
1729   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1730
1731   return action->private_data->tooltip;
1732 }
1733
1734 /**
1735  * gtk_action_set_stock_id:
1736  * @action: a #GtkAction
1737  * @tooltip: the tooltip text
1738  *
1739  * Sets the stock id on @action
1740  *
1741  * Since: 2.16
1742  */
1743 void 
1744 gtk_action_set_stock_id (GtkAction   *action,
1745                          const gchar *stock_id)
1746 {
1747   GSList *p;
1748   GtkWidget *proxy, *image;
1749   gchar *tmp;
1750   
1751   g_return_if_fail (GTK_IS_ACTION (action));
1752
1753   tmp = action->private_data->stock_id;
1754   action->private_data->stock_id = g_strdup (stock_id);
1755   g_free (tmp);
1756
1757   for (p = action->private_data->proxies; p; p = p->next)
1758     {
1759       proxy = (GtkWidget *)p->data;
1760       
1761       if (GTK_IS_IMAGE_MENU_ITEM (proxy))
1762         {
1763           image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
1764           
1765           if (GTK_IS_IMAGE (image))
1766             gtk_image_set_from_stock (GTK_IMAGE (image),
1767                                       action->private_data->stock_id, GTK_ICON_SIZE_MENU);
1768         } 
1769       else if (GTK_IS_TOOL_BUTTON (proxy))
1770         {
1771           gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), NULL);
1772           gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (proxy),
1773                                         action->private_data->stock_id);
1774         }
1775       else if (GTK_IS_BUTTON (proxy) &&
1776                gtk_button_get_use_stock (GTK_BUTTON (proxy)))
1777         {
1778           gtk_button_set_label (GTK_BUTTON (proxy),
1779                                 action->private_data->stock_id);
1780         }
1781     }
1782
1783   g_object_notify (G_OBJECT (action), "stock-id");
1784   
1785   /* update label and short_label if appropriate */
1786   if (!action->private_data->label_set)
1787     {
1788       GtkStockItem stock_item;
1789       
1790       if (action->private_data->stock_id &&
1791           gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1792         gtk_action_set_label (action, stock_item.label);
1793       else 
1794         gtk_action_set_label (action, NULL);
1795       
1796       action->private_data->label_set = FALSE;
1797     }
1798 }
1799
1800 /**
1801  * gtk_action_get_stock_id:
1802  * @action: a #GtkAction
1803  *
1804  * Gets the stock id of @action.
1805  *
1806  * Returns: the stock id
1807  *
1808  * Since: 2.16
1809  */
1810 G_CONST_RETURN gchar *
1811 gtk_action_get_stock_id (GtkAction *action)
1812 {
1813   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1814
1815   return action->private_data->stock_id;
1816 }
1817
1818 /**
1819  * gtk_action_set_icon_name:
1820  * @action: a #GtkAction
1821  * @tooltip: the icon name to set
1822  *
1823  * Sets the icon name on @action
1824  *
1825  * Since: 2.16
1826  */
1827 void 
1828 gtk_action_set_icon_name (GtkAction   *action,
1829                           const gchar *icon_name)
1830 {
1831   GSList *p;
1832   GtkWidget *proxy, *image;
1833   gchar *tmp;
1834   
1835   g_return_if_fail (GTK_IS_ACTION (action));
1836
1837   tmp = action->private_data->icon_name;
1838   action->private_data->icon_name = g_strdup (icon_name);
1839   g_free (tmp);
1840
1841   for (p = action->private_data->proxies; p; p = p->next)
1842     {
1843       proxy = (GtkWidget *)p->data;
1844       
1845       if (GTK_IS_IMAGE_MENU_ITEM (proxy))
1846         {
1847           image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
1848           
1849           if (GTK_IS_IMAGE (image) &&
1850               (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
1851                gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
1852             gtk_image_set_from_icon_name (GTK_IMAGE (image),
1853                                           action->private_data->icon_name, GTK_ICON_SIZE_MENU);
1854         } 
1855       else if (GTK_IS_TOOL_BUTTON (proxy))
1856         {
1857           gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (proxy),
1858                                          action->private_data->icon_name);
1859         }
1860       else if (GTK_IS_BUTTON (proxy) &&
1861                !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
1862         {
1863           image = gtk_button_get_image (GTK_BUTTON (proxy));
1864           
1865           if (GTK_IS_IMAGE (image) &&
1866               (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
1867                gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
1868             gtk_image_set_from_icon_name (GTK_IMAGE (image),
1869                                           action->private_data->icon_name, GTK_ICON_SIZE_MENU);
1870         }
1871     }
1872   
1873   g_object_notify (G_OBJECT (action), "icon-name");
1874 }
1875
1876 /**
1877  * gtk_action_get_icon_name:
1878  * @action: a #GtkAction
1879  *
1880  * Gets the icon name of @action.
1881  *
1882  * Returns: the icon name
1883  *
1884  * Since: 2.16
1885  */
1886 G_CONST_RETURN gchar *
1887 gtk_action_get_icon_name (GtkAction *action)
1888 {
1889   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1890
1891   return action->private_data->icon_name;
1892 }
1893
1894 /**
1895  * gtk_action_set_gicon:
1896  * @action: a #GtkAction
1897  * @icon: the #GIcon to set
1898  *
1899  * Sets the icon of @action.
1900  *
1901  * Since: 2.16
1902  */
1903 void
1904 gtk_action_set_gicon (GtkAction *action,
1905                       GIcon     *icon)
1906 {
1907   GSList *p;
1908   GtkWidget *proxy, *image;
1909   GtkIconSize icon_size;
1910   gboolean has_stock_icon;
1911   
1912   g_return_if_fail (GTK_IS_ACTION (action));
1913
1914   if (action->private_data->gicon)
1915     g_object_unref (action->private_data->gicon);
1916
1917   action->private_data->gicon = icon;
1918
1919   if (action->private_data->gicon)
1920     g_object_ref (action->private_data->gicon);
1921
1922   if (action->private_data->stock_id &&
1923       gtk_icon_factory_lookup_default (action->private_data->stock_id))
1924     has_stock_icon = TRUE;
1925   else
1926     has_stock_icon = FALSE;
1927
1928   for (p = action->private_data->proxies; p; p = p->next)
1929     {
1930       proxy = (GtkWidget *)p->data;
1931   
1932       if (GTK_IS_IMAGE_MENU_ITEM (proxy) && !has_stock_icon)
1933         {
1934           image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
1935           gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU);
1936         } 
1937       else if (GTK_IS_TOOL_BUTTON (proxy))
1938         {
1939           if (has_stock_icon || !icon)
1940             image = NULL;
1941           else 
1942             {   
1943               image = gtk_tool_button_get_icon_widget (GTK_TOOL_BUTTON (proxy));
1944               icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (proxy));
1945
1946               if (!image)
1947                 image = gtk_image_new ();
1948             }
1949
1950           gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), image);
1951           gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
1952         }
1953       else if (GTK_IS_BUTTON (proxy) && 
1954                !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
1955         {
1956           image = gtk_button_get_image (GTK_BUTTON (proxy));
1957           if (GTK_IS_IMAGE (image) &&
1958               (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
1959                gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
1960             gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_BUTTON);
1961         }
1962     }
1963   
1964   g_object_notify (G_OBJECT (action), "gicon");
1965 }
1966
1967 /**
1968  * gtk_action_get_gicon:
1969  * @action: a #GtkAction
1970  *
1971  * Gets the gicon of @action.
1972  *
1973  * Returns: The action's #GIcon if one is set.
1974  *
1975  * Since: 2.16
1976  */
1977 GIcon *
1978 gtk_action_get_gicon (GtkAction *action)
1979 {
1980   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1981
1982   return action->private_data->gicon;
1983 }
1984
1985 /**
1986  * gtk_action_block_activate_from:
1987  * @action: the action object
1988  * @proxy: a proxy widget
1989  *
1990  * Disables calls to the gtk_action_activate()
1991  * function by signals on the given proxy widget.  This is used to
1992  * break notification loops for things like check or radio actions.
1993  *
1994  * This function is intended for use by action implementations.
1995  * 
1996  * Since: 2.4
1997  */
1998 void
1999 gtk_action_block_activate_from (GtkAction *action, 
2000                                 GtkWidget *proxy)
2001 {
2002   g_return_if_fail (GTK_IS_ACTION (action));
2003   
2004   g_signal_handlers_block_by_func (proxy, G_CALLBACK (gtk_action_activate),
2005                                    action);
2006 }
2007
2008 /**
2009  * gtk_action_unblock_activate_from:
2010  * @action: the action object
2011  * @proxy: a proxy widget
2012  *
2013  * Re-enables calls to the gtk_action_activate()
2014  * function by signals on the given proxy widget.  This undoes the
2015  * blocking done by gtk_action_block_activate_from().
2016  *
2017  * This function is intended for use by action implementations.
2018  * 
2019  * Since: 2.4
2020  */
2021 void
2022 gtk_action_unblock_activate_from (GtkAction *action, 
2023                                   GtkWidget *proxy)
2024 {
2025   g_return_if_fail (GTK_IS_ACTION (action));
2026
2027   g_signal_handlers_unblock_by_func (proxy, G_CALLBACK (gtk_action_activate),
2028                                      action);
2029 }
2030
2031 static void
2032 closure_accel_activate (GClosure     *closure,
2033                         GValue       *return_value,
2034                         guint         n_param_values,
2035                         const GValue *param_values,
2036                         gpointer      invocation_hint,
2037                         gpointer      marshal_data)
2038 {
2039   if (gtk_action_is_sensitive (GTK_ACTION (closure->data)))
2040     {
2041       _gtk_action_emit_activate (GTK_ACTION (closure->data));
2042       
2043       /* we handled the accelerator */
2044       g_value_set_boolean (return_value, TRUE);
2045     }
2046 }
2047
2048 static void
2049 gtk_action_set_action_group (GtkAction      *action,
2050                              GtkActionGroup *action_group)
2051 {
2052   if (action->private_data->action_group == NULL)
2053     g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
2054   else
2055     g_return_if_fail (action_group == NULL);
2056
2057   action->private_data->action_group = action_group;
2058 }
2059
2060 /**
2061  * gtk_action_set_accel_path:
2062  * @action: the action object
2063  * @accel_path: the accelerator path
2064  *
2065  * Sets the accel path for this action.  All proxy widgets associated
2066  * with the action will have this accel path, so that their
2067  * accelerators are consistent.
2068  *
2069  * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
2070  * pass a static string, you can save some memory by interning it first with 
2071  * g_intern_static_string().
2072  *
2073  * Since: 2.4
2074  */
2075 void
2076 gtk_action_set_accel_path (GtkAction   *action, 
2077                            const gchar *accel_path)
2078 {
2079   g_return_if_fail (GTK_IS_ACTION (action));
2080
2081   action->private_data->accel_quark = g_quark_from_string (accel_path);
2082 }
2083
2084 /**
2085  * gtk_action_get_accel_path:
2086  * @action: the action object
2087  *
2088  * Returns the accel path for this action.  
2089  *
2090  * Since: 2.6
2091  *
2092  * Returns: the accel path for this action, or %NULL
2093  *   if none is set. The returned string is owned by GTK+ 
2094  *   and must not be freed or modified.
2095  */
2096 G_CONST_RETURN gchar *
2097 gtk_action_get_accel_path (GtkAction *action)
2098 {
2099   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
2100
2101   if (action->private_data->accel_quark)
2102     return g_quark_to_string (action->private_data->accel_quark);
2103   else
2104     return NULL;
2105 }
2106
2107 /**
2108  * gtk_action_get_accel_closure:
2109  * @action: the action object
2110  *
2111  * Returns the accel closure for this action.
2112  *
2113  * Since: 2.8
2114  *
2115  * Returns: the accel closure for this action. The returned closure is
2116  *          owned by GTK+ and must not be unreffed or modified.
2117  */
2118 GClosure *
2119 gtk_action_get_accel_closure (GtkAction *action)
2120 {
2121   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
2122
2123   return action->private_data->accel_closure;
2124 }
2125
2126
2127 /**
2128  * gtk_action_set_accel_group:
2129  * @action: the action object
2130  * @accel_group: a #GtkAccelGroup or %NULL
2131  * 
2132  * Sets the #GtkAccelGroup in which the accelerator for this action
2133  * will be installed.
2134  *
2135  * Since: 2.4
2136  **/
2137 void
2138 gtk_action_set_accel_group (GtkAction     *action,
2139                             GtkAccelGroup *accel_group)
2140 {
2141   g_return_if_fail (GTK_IS_ACTION (action));
2142   g_return_if_fail (accel_group == NULL || GTK_IS_ACCEL_GROUP (accel_group));
2143   
2144   if (accel_group)
2145     g_object_ref (accel_group);
2146   if (action->private_data->accel_group)
2147     g_object_unref (action->private_data->accel_group);
2148
2149   action->private_data->accel_group = accel_group;
2150 }
2151
2152 /**
2153  * gtk_action_connect_accelerator:
2154  * @action: a #GtkAction
2155  * 
2156  * Installs the accelerator for @action if @action has an
2157  * accel path and group. See gtk_action_set_accel_path() and 
2158  * gtk_action_set_accel_group()
2159  *
2160  * Since multiple proxies may independently trigger the installation
2161  * of the accelerator, the @action counts the number of times this
2162  * function has been called and doesn't remove the accelerator until
2163  * gtk_action_disconnect_accelerator() has been called as many times.
2164  *
2165  * Since: 2.4
2166  **/
2167 void 
2168 gtk_action_connect_accelerator (GtkAction *action)
2169 {
2170   g_return_if_fail (GTK_IS_ACTION (action));
2171
2172   if (!action->private_data->accel_quark ||
2173       !action->private_data->accel_group)
2174     return;
2175
2176   if (action->private_data->accel_count == 0)
2177     {
2178       const gchar *accel_path = 
2179         g_quark_to_string (action->private_data->accel_quark);
2180       
2181       gtk_accel_group_connect_by_path (action->private_data->accel_group,
2182                                        accel_path,
2183                                        action->private_data->accel_closure);
2184     }
2185
2186   action->private_data->accel_count++;
2187 }
2188
2189 /**
2190  * gtk_action_disconnect_accelerator:
2191  * @action: a #GtkAction
2192  * 
2193  * Undoes the effect of one call to gtk_action_connect_accelerator().
2194  *
2195  * Since: 2.4
2196  **/
2197 void 
2198 gtk_action_disconnect_accelerator (GtkAction *action)
2199 {
2200   g_return_if_fail (GTK_IS_ACTION (action));
2201
2202   if (!action->private_data->accel_quark ||
2203       !action->private_data->accel_group)
2204     return;
2205
2206   action->private_data->accel_count--;
2207
2208   if (action->private_data->accel_count == 0)
2209     gtk_accel_group_disconnect (action->private_data->accel_group,
2210                                 action->private_data->accel_closure);
2211 }
2212
2213 /**
2214  * gtk_action_create_menu:
2215  * @action: a #GtkAction
2216  *
2217  * If @action provides a #GtkMenu widget as a submenu for the menu
2218  * item or the toolbar item it creates, this function returns an
2219  * instance of that menu.
2220  *
2221  * Return value: the menu item provided by the action, or %NULL.
2222  *
2223  * Since: 2.12
2224  */
2225 GtkWidget *
2226 gtk_action_create_menu (GtkAction *action)
2227 {
2228   g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
2229
2230   if (GTK_ACTION_GET_CLASS (action)->create_menu)
2231     return GTK_ACTION_GET_CLASS (action)->create_menu (action);
2232
2233   return NULL;
2234 }
2235
2236 #define __GTK_ACTION_C__
2237 #include "gtkaliasdef.c"