2 * GTK - The GIMP Toolkit
3 * Copyright (C) 1998, 1999 Red Hat, Inc.
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.
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.
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.
23 * Author: James Henstridge <james@daa.com.au>
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/.
33 #include "gtkaction.h"
34 #include "gtkactiongroup.h"
35 #include "gtkaccellabel.h"
36 #include "gtkbutton.h"
38 #include "gtkimagemenuitem.h"
41 #include "gtkmarshalers.h"
42 #include "gtkmenuitem.h"
44 #include "gtktearoffmenuitem.h"
45 #include "gtktoolbutton.h"
46 #include "gtktoolbar.h"
47 #include "gtkprivate.h"
51 #define GTK_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION, GtkActionPrivate))
53 struct _GtkActionPrivate
59 gchar *stock_id; /* icon */
63 guint label_set : 1; /* these two used so we can set label */
64 guint short_label_set : 1; /* based on stock id */
65 guint visible_horizontal : 1;
66 guint visible_vertical : 1;
67 guint is_important : 1;
68 guint hide_if_empty : 1;
69 guint visible_overflown : 1;
73 GtkAccelGroup *accel_group;
74 GClosure *accel_closure;
77 GtkActionGroup *action_group;
79 /* list of proxy widgets */
97 PROP_VISIBLE_HORIZONTAL,
98 PROP_VISIBLE_VERTICAL,
99 PROP_VISIBLE_OVERFLOWN,
107 static void gtk_action_init (GtkAction *action);
108 static void gtk_action_class_init (GtkActionClass *class);
110 static GQuark accel_path_id = 0;
111 static const gchar accel_path_key[] = "GtkAction::accel_path";
114 gtk_action_get_type (void)
116 static GtkType type = 0;
120 static const GTypeInfo type_info =
122 sizeof (GtkActionClass),
123 (GBaseInitFunc) NULL,
124 (GBaseFinalizeFunc) NULL,
125 (GClassInitFunc) gtk_action_class_init,
126 (GClassFinalizeFunc) NULL,
131 (GInstanceInitFunc) gtk_action_init,
134 type = g_type_register_static (G_TYPE_OBJECT,
141 static void gtk_action_finalize (GObject *object);
142 static void gtk_action_set_property (GObject *object,
146 static void gtk_action_get_property (GObject *object,
150 static void gtk_action_set_action_group (GtkAction *action,
151 GtkActionGroup *action_group);
152 static void gtk_action_set_is_important (GtkAction *action,
153 gboolean is_important);
154 static void gtk_action_set_label (GtkAction *action,
156 static void gtk_action_set_short_label (GtkAction *action,
158 static void gtk_action_set_visible_horizontal (GtkAction *action,
159 gboolean visible_horizontal);
160 static void gtk_action_set_visible_vertical (GtkAction *action,
161 gboolean visible_vertical);
162 static void gtk_action_set_tooltip (GtkAction *action,
163 const gchar *tooltip);
164 static void gtk_action_set_stock_id (GtkAction *action,
165 const gchar *stock_id);
166 static void gtk_action_sync_tooltip (GtkAction *action,
169 static GtkWidget *create_menu_item (GtkAction *action);
170 static GtkWidget *create_tool_item (GtkAction *action);
171 static void connect_proxy (GtkAction *action,
173 static void disconnect_proxy (GtkAction *action,
175 static void closure_accel_activate (GClosure *closure,
176 GValue *return_value,
177 guint n_param_values,
178 const GValue *param_values,
179 gpointer invocation_hint,
180 gpointer marshal_data);
182 static GObjectClass *parent_class = NULL;
183 static guint action_signals[LAST_SIGNAL] = { 0 };
187 gtk_action_class_init (GtkActionClass *klass)
189 GObjectClass *gobject_class;
191 accel_path_id = g_quark_from_static_string (accel_path_key);
193 parent_class = g_type_class_peek_parent (klass);
194 gobject_class = G_OBJECT_CLASS (klass);
196 gobject_class->finalize = gtk_action_finalize;
197 gobject_class->set_property = gtk_action_set_property;
198 gobject_class->get_property = gtk_action_get_property;
200 klass->activate = NULL;
202 klass->create_menu_item = create_menu_item;
203 klass->create_tool_item = create_tool_item;
204 klass->connect_proxy = connect_proxy;
205 klass->disconnect_proxy = disconnect_proxy;
207 klass->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
208 klass->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
210 g_object_class_install_property (gobject_class,
212 g_param_spec_string ("name",
214 P_("A unique name for the action."),
216 GTK_PARAM_READWRITE |
217 G_PARAM_CONSTRUCT_ONLY));
218 g_object_class_install_property (gobject_class,
220 g_param_spec_string ("label",
222 P_("The label used for menu items and buttons "
223 "that activate this action."),
225 GTK_PARAM_READWRITE));
226 g_object_class_install_property (gobject_class,
228 g_param_spec_string ("short-label",
230 P_("A shorter label that may be used on toolbar buttons."),
232 GTK_PARAM_READWRITE));
233 g_object_class_install_property (gobject_class,
235 g_param_spec_string ("tooltip",
237 P_("A tooltip for this action."),
239 GTK_PARAM_READWRITE));
240 g_object_class_install_property (gobject_class,
242 g_param_spec_string ("stock-id",
244 P_("The stock icon displayed in widgets representing "
247 GTK_PARAM_READWRITE));
248 g_object_class_install_property (gobject_class,
249 PROP_VISIBLE_HORIZONTAL,
250 g_param_spec_boolean ("visible-horizontal",
251 P_("Visible when horizontal"),
252 P_("Whether the toolbar item is visible when the toolbar "
253 "is in a horizontal orientation."),
255 GTK_PARAM_READWRITE));
257 * GtkAction:visible-overflown:
259 * When %TRUE, toolitem proxies for this action are represented in the
260 * toolbar overflow menu.
264 g_object_class_install_property (gobject_class,
265 PROP_VISIBLE_OVERFLOWN,
266 g_param_spec_boolean ("visible-overflown",
267 P_("Visible when overflown"),
268 P_("When TRUE, toolitem proxies for this action "
269 "are represented in the toolbar overflow menu."),
271 GTK_PARAM_READWRITE));
272 g_object_class_install_property (gobject_class,
273 PROP_VISIBLE_VERTICAL,
274 g_param_spec_boolean ("visible-vertical",
275 P_("Visible when vertical"),
276 P_("Whether the toolbar item is visible when the toolbar "
277 "is in a vertical orientation."),
279 GTK_PARAM_READWRITE));
280 g_object_class_install_property (gobject_class,
282 g_param_spec_boolean ("is-important",
284 P_("Whether the action is considered important. "
285 "When TRUE, toolitem proxies for this action "
286 "show text in GTK_TOOLBAR_BOTH_HORIZ mode."),
288 GTK_PARAM_READWRITE));
289 g_object_class_install_property (gobject_class,
291 g_param_spec_boolean ("hide-if-empty",
293 P_("When TRUE, empty menu proxies for this action are hidden."),
295 GTK_PARAM_READWRITE));
296 g_object_class_install_property (gobject_class,
298 g_param_spec_boolean ("sensitive",
300 P_("Whether the action is enabled."),
302 GTK_PARAM_READWRITE));
303 g_object_class_install_property (gobject_class,
305 g_param_spec_boolean ("visible",
307 P_("Whether the action is visible."),
309 GTK_PARAM_READWRITE));
310 g_object_class_install_property (gobject_class,
312 g_param_spec_object ("action-group",
314 P_("The GtkActionGroup this GtkAction is associated with, or NULL (for internal use)."),
315 GTK_TYPE_ACTION_GROUP,
316 GTK_PARAM_READWRITE));
319 * GtkAction::activate:
320 * @action: the #GtkAction
322 * The "activate" signal is emitted when the action is activated.
326 action_signals[ACTIVATE] =
327 g_signal_new (I_("activate"),
328 G_OBJECT_CLASS_TYPE (klass),
329 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
330 G_STRUCT_OFFSET (GtkActionClass, activate), NULL, NULL,
331 g_cclosure_marshal_VOID__VOID,
334 g_type_class_add_private (gobject_class, sizeof (GtkActionPrivate));
339 gtk_action_init (GtkAction *action)
341 action->private_data = GTK_ACTION_GET_PRIVATE (action);
343 action->private_data->name = NULL;
344 action->private_data->label = NULL;
345 action->private_data->short_label = NULL;
346 action->private_data->tooltip = NULL;
347 action->private_data->stock_id = NULL;
348 action->private_data->visible_horizontal = TRUE;
349 action->private_data->visible_vertical = TRUE;
350 action->private_data->visible_overflown = TRUE;
351 action->private_data->is_important = FALSE;
352 action->private_data->hide_if_empty = TRUE;
354 action->private_data->sensitive = TRUE;
355 action->private_data->visible = TRUE;
357 action->private_data->label_set = FALSE;
358 action->private_data->short_label_set = FALSE;
360 action->private_data->accel_count = 0;
361 action->private_data->accel_group = NULL;
362 action->private_data->accel_quark = 0;
363 action->private_data->accel_closure =
364 g_closure_new_object (sizeof (GClosure), G_OBJECT (action));
365 g_closure_set_marshal (action->private_data->accel_closure,
366 closure_accel_activate);
367 g_closure_ref (action->private_data->accel_closure);
368 g_closure_sink (action->private_data->accel_closure);
370 action->private_data->action_group = NULL;
372 action->private_data->proxies = NULL;
377 * @name: A unique name for the action
378 * @label: the label displayed in menu items and on buttons
379 * @tooltip: a tooltip for the action
380 * @stock_id: the stock icon to display in widgets representing the action
382 * Creates a new #GtkAction object. To add the action to a
383 * #GtkActionGroup and set the accelerator for the action,
384 * call gtk_action_group_add_action_with_accel().
385 * See <xref linkend="XML-UI"/> for information on allowed action
388 * Return value: a new #GtkAction
393 gtk_action_new (const gchar *name,
395 const gchar *tooltip,
396 const gchar *stock_id)
400 action = g_object_new (GTK_TYPE_ACTION,
404 "stock_id", stock_id,
411 gtk_action_finalize (GObject *object)
414 action = GTK_ACTION (object);
416 g_free (action->private_data->name);
417 g_free (action->private_data->label);
418 g_free (action->private_data->short_label);
419 g_free (action->private_data->tooltip);
420 g_free (action->private_data->stock_id);
422 g_closure_unref (action->private_data->accel_closure);
423 if (action->private_data->accel_group)
424 g_object_unref (action->private_data->accel_group);
426 G_OBJECT_CLASS (parent_class)->finalize (object);
430 gtk_action_set_property (GObject *object,
438 action = GTK_ACTION (object);
443 tmp = action->private_data->name;
444 action->private_data->name = g_value_dup_string (value);
448 gtk_action_set_label (action, g_value_get_string (value));
450 case PROP_SHORT_LABEL:
451 gtk_action_set_short_label (action, g_value_get_string (value));
454 gtk_action_set_tooltip (action, g_value_get_string (value));
457 gtk_action_set_stock_id (action, g_value_get_string (value));
459 case PROP_VISIBLE_HORIZONTAL:
460 gtk_action_set_visible_horizontal (action, g_value_get_boolean (value));
462 case PROP_VISIBLE_VERTICAL:
463 gtk_action_set_visible_vertical (action, g_value_get_boolean (value));
465 case PROP_VISIBLE_OVERFLOWN:
466 action->private_data->visible_overflown = g_value_get_boolean (value);
468 case PROP_IS_IMPORTANT:
469 gtk_action_set_is_important (action, g_value_get_boolean (value));
471 case PROP_HIDE_IF_EMPTY:
472 action->private_data->hide_if_empty = g_value_get_boolean (value);
475 gtk_action_set_sensitive (action, g_value_get_boolean (value));
478 gtk_action_set_visible (action, g_value_get_boolean (value));
480 case PROP_ACTION_GROUP:
481 gtk_action_set_action_group (action, g_value_get_object (value));
484 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
490 gtk_action_get_property (GObject *object,
497 action = GTK_ACTION (object);
502 g_value_set_string (value, action->private_data->name);
505 g_value_set_string (value, action->private_data->label);
507 case PROP_SHORT_LABEL:
508 g_value_set_string (value, action->private_data->short_label);
511 g_value_set_string (value, action->private_data->tooltip);
514 g_value_set_string (value, action->private_data->stock_id);
516 case PROP_VISIBLE_HORIZONTAL:
517 g_value_set_boolean (value, action->private_data->visible_horizontal);
519 case PROP_VISIBLE_VERTICAL:
520 g_value_set_boolean (value, action->private_data->visible_vertical);
522 case PROP_VISIBLE_OVERFLOWN:
523 g_value_set_boolean (value, action->private_data->visible_overflown);
525 case PROP_IS_IMPORTANT:
526 g_value_set_boolean (value, action->private_data->is_important);
528 case PROP_HIDE_IF_EMPTY:
529 g_value_set_boolean (value, action->private_data->hide_if_empty);
532 g_value_set_boolean (value, action->private_data->sensitive);
535 g_value_set_boolean (value, action->private_data->visible);
537 case PROP_ACTION_GROUP:
538 g_value_set_object (value, action->private_data->action_group);
541 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
547 create_menu_item (GtkAction *action)
549 GType menu_item_type;
551 menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type;
553 return g_object_new (menu_item_type, NULL);
557 create_tool_item (GtkAction *action)
559 GType toolbar_item_type;
561 toolbar_item_type = GTK_ACTION_GET_CLASS (action)->toolbar_item_type;
563 return g_object_new (toolbar_item_type, NULL);
567 remove_proxy (GtkWidget *proxy,
570 if (GTK_IS_MENU_ITEM (proxy))
571 gtk_action_disconnect_accelerator (action);
573 action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
577 gtk_action_sync_property (GtkAction *action,
581 const gchar *property;
582 GValue value = { 0, };
584 property = g_param_spec_get_name (pspec);
586 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
587 g_object_get_property (G_OBJECT (action), property, &value);
589 g_object_set_property (G_OBJECT (proxy), property, &value);
590 g_value_unset (&value);
594 * _gtk_action_sync_menu_visible:
595 * @action: a #GtkAction, or %NULL to determine the action from @proxy
596 * @proxy: a proxy menu item
597 * @empty: whether the submenu attached to @proxy is empty
599 * Updates the visibility of @proxy from the visibility of @action
600 * according to the following rules:
602 * <listitem><para>if @action is invisible, @proxy is too
604 * <listitem><para>if @empty is %TRUE, hide @proxy unless the "hide-if-empty"
605 * property of @action indicates otherwise
609 * This function is used in the implementation of #GtkUIManager.
612 _gtk_action_sync_menu_visible (GtkAction *action,
616 gboolean visible, hide_if_empty;
618 g_return_if_fail (GTK_IS_MENU_ITEM (proxy));
619 g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
622 action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
624 visible = gtk_action_is_visible (action);
625 hide_if_empty = action->private_data->hide_if_empty;
627 if (visible && !(empty && hide_if_empty))
628 gtk_widget_show (proxy);
630 gtk_widget_hide (proxy);
633 gboolean _gtk_menu_is_empty (GtkWidget *menu);
636 gtk_action_sync_stock_id (GtkAction *action,
640 GtkWidget *image = NULL;
642 if (GTK_IS_IMAGE_MENU_ITEM (proxy))
644 image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
646 if (GTK_IS_IMAGE (image))
647 gtk_image_set_from_stock (GTK_IMAGE (image),
648 action->private_data->stock_id, GTK_ICON_SIZE_MENU);
653 gtk_action_create_menu_proxy (GtkToolItem *tool_item,
656 GtkWidget *menu_item;
658 if (action->private_data->visible_overflown)
660 menu_item = gtk_action_create_menu_item (action);
662 g_object_ref_sink (menu_item);
664 gtk_tool_item_set_proxy_menu_item (tool_item,
665 "gtk-action-menu-item", menu_item);
666 g_object_unref (menu_item);
669 gtk_tool_item_set_proxy_menu_item (tool_item,
670 "gtk-action-menu-item", NULL);
676 connect_proxy (GtkAction *action,
679 g_object_ref (action);
680 g_object_set_data_full (G_OBJECT (proxy), I_("gtk-action"), action,
683 /* add this widget to the list of proxies */
684 action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
685 g_signal_connect (proxy, "destroy",
686 G_CALLBACK (remove_proxy), action);
688 gtk_widget_set_sensitive (proxy, gtk_action_is_sensitive (action));
689 if (gtk_action_is_visible (action))
690 gtk_widget_show (proxy);
692 gtk_widget_hide (proxy);
693 gtk_widget_set_no_show_all (proxy, TRUE);
695 if (GTK_IS_MENU_ITEM (proxy))
698 /* menu item specific synchronisers ... */
700 if (action->private_data->accel_quark)
702 gtk_action_connect_accelerator (action);
703 gtk_menu_item_set_accel_path (GTK_MENU_ITEM (proxy),
704 g_quark_to_string (action->private_data->accel_quark));
707 label = GTK_BIN (proxy)->child;
709 /* make sure label is a label */
710 if (label && !GTK_IS_LABEL (label))
712 gtk_container_remove (GTK_CONTAINER (proxy), label);
717 label = g_object_new (GTK_TYPE_ACCEL_LABEL,
718 "use_underline", TRUE,
724 if (GTK_IS_ACCEL_LABEL (label) && action->private_data->accel_quark)
726 "accel_closure", action->private_data->accel_closure,
729 gtk_label_set_label (GTK_LABEL (label), action->private_data->label);
731 if (GTK_IS_IMAGE_MENU_ITEM (proxy))
735 image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
736 if (image && !GTK_IS_IMAGE (image))
738 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy), NULL);
743 image = gtk_image_new_from_stock (NULL,
745 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),
747 gtk_widget_show (image);
749 gtk_image_set_from_stock (GTK_IMAGE (image),
750 action->private_data->stock_id, GTK_ICON_SIZE_MENU);
753 if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)) == NULL)
754 g_signal_connect_object (proxy, "activate",
755 G_CALLBACK (gtk_action_activate), action,
759 else if (GTK_IS_TOOL_ITEM (proxy))
761 /* toolbar item specific synchronisers ... */
764 "visible_horizontal", action->private_data->visible_horizontal,
765 "visible_vertical", action->private_data->visible_vertical,
766 "is_important", action->private_data->is_important,
769 gtk_action_sync_tooltip (action, proxy);
771 g_signal_connect_object (proxy, "create_menu_proxy",
772 G_CALLBACK (gtk_action_create_menu_proxy),
775 gtk_tool_item_rebuild_menu (GTK_TOOL_ITEM (proxy));
777 /* toolbar button specific synchronisers ... */
778 if (GTK_IS_TOOL_BUTTON (proxy))
781 "label", action->private_data->short_label,
782 "use_underline", TRUE,
783 "stock_id", action->private_data->stock_id,
786 g_signal_connect_object (proxy, "clicked",
787 G_CALLBACK (gtk_action_activate), action,
791 else if (GTK_IS_BUTTON (proxy))
793 /* button specific synchronisers ... */
794 if (gtk_button_get_use_stock (GTK_BUTTON (proxy)))
796 /* synchronise stock-id */
798 "label", action->private_data->stock_id,
801 else if (GTK_BIN (proxy)->child == NULL ||
802 GTK_IS_LABEL (GTK_BIN (proxy)->child))
804 /* synchronise the label */
806 "label", action->private_data->short_label,
807 "use_underline", TRUE,
811 /* we leave the button alone if there is a custom child */
812 g_signal_connect_object (proxy, "clicked",
813 G_CALLBACK (gtk_action_activate), action,
817 if (action->private_data->action_group)
818 _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
822 disconnect_proxy (GtkAction *action,
825 g_object_set_data (G_OBJECT (proxy), I_("gtk-action"), NULL);
827 /* remove proxy from list of proxies */
828 g_signal_handlers_disconnect_by_func (proxy,
829 G_CALLBACK (remove_proxy),
831 remove_proxy (proxy, action);
833 /* disconnect the activate handler */
834 g_signal_handlers_disconnect_by_func (proxy,
835 G_CALLBACK (gtk_action_activate),
838 /* disconnect handlers for notify::* signals */
839 g_signal_handlers_disconnect_by_func (action,
840 G_CALLBACK (gtk_action_sync_property),
843 g_signal_handlers_disconnect_by_func (action,
844 G_CALLBACK (gtk_action_sync_stock_id), proxy);
846 /* toolbar button specific synchronisers ... */
847 g_signal_handlers_disconnect_by_func (proxy,
848 G_CALLBACK (gtk_action_create_menu_proxy),
851 if (action->private_data->action_group)
852 _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
856 _gtk_action_emit_activate (GtkAction *action)
858 GtkActionGroup *group = action->private_data->action_group;
862 g_object_ref (group);
863 _gtk_action_group_emit_pre_activate (group, action);
866 g_signal_emit (action, action_signals[ACTIVATE], 0);
870 _gtk_action_group_emit_post_activate (group, action);
871 g_object_unref (group);
876 * gtk_action_activate:
877 * @action: the action object
879 * Emits the "activate" signal on the specified action, if it isn't
880 * insensitive. This gets called by the proxy widgets when they get
883 * It can also be used to manually activate an action.
888 gtk_action_activate (GtkAction *action)
890 g_return_if_fail (GTK_IS_ACTION (action));
892 if (gtk_action_is_sensitive (action))
893 _gtk_action_emit_activate (action);
897 * gtk_action_create_icon:
898 * @action: the action object
899 * @icon_size: the size of the icon that should be created.
901 * This function is intended for use by action implementations to
902 * create icons displayed in the proxy widgets.
904 * Returns: a widget that displays the icon for this action.
909 gtk_action_create_icon (GtkAction *action, GtkIconSize icon_size)
911 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
913 if (action->private_data->stock_id)
914 return gtk_image_new_from_stock (action->private_data->stock_id, icon_size);
920 * gtk_action_create_menu_item:
921 * @action: the action object
923 * Creates a menu item widget that proxies for the given action.
925 * Returns: a menu item connected to the action.
930 gtk_action_create_menu_item (GtkAction *action)
932 GtkWidget *menu_item;
934 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
936 menu_item = (* GTK_ACTION_GET_CLASS (action)->create_menu_item) (action);
938 (* GTK_ACTION_GET_CLASS (action)->connect_proxy) (action, menu_item);
944 * gtk_action_create_tool_item:
945 * @action: the action object
947 * Creates a toolbar item widget that proxies for the given action.
949 * Returns: a toolbar item connected to the action.
954 gtk_action_create_tool_item (GtkAction *action)
958 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
960 button = (* GTK_ACTION_GET_CLASS (action)->create_tool_item) (action);
962 (* GTK_ACTION_GET_CLASS (action)->connect_proxy) (action, button);
968 * gtk_action_connect_proxy:
969 * @action: the action object
970 * @proxy: the proxy widget
972 * Connects a widget to an action object as a proxy. Synchronises
973 * various properties of the action with the widget (such as label
974 * text, icon, tooltip, etc), and attaches a callback so that the
975 * action gets activated when the proxy widget does.
977 * If the widget is already connected to an action, it is disconnected
983 gtk_action_connect_proxy (GtkAction *action,
986 GtkAction *prev_action;
988 g_return_if_fail (GTK_IS_ACTION (action));
989 g_return_if_fail (GTK_IS_WIDGET (proxy));
991 prev_action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
994 (* GTK_ACTION_GET_CLASS (action)->disconnect_proxy) (prev_action, proxy);
996 (* GTK_ACTION_GET_CLASS (action)->connect_proxy) (action, proxy);
1000 * gtk_action_disconnect_proxy:
1001 * @action: the action object
1002 * @proxy: the proxy widget
1004 * Disconnects a proxy widget from an action.
1005 * Does <emphasis>not</emphasis> destroy the widget, however.
1010 gtk_action_disconnect_proxy (GtkAction *action,
1013 g_return_if_fail (GTK_IS_ACTION (action));
1014 g_return_if_fail (GTK_IS_WIDGET (proxy));
1016 g_return_if_fail (g_object_get_data (G_OBJECT (proxy), "gtk-action") == action);
1018 (* GTK_ACTION_GET_CLASS (action)->disconnect_proxy) (action, proxy);
1022 * gtk_action_get_proxies:
1023 * @action: the action object
1025 * Returns the proxy widgets for an action.
1027 * Return value: a #GSList of proxy widgets. The list is owned by the action and
1028 * must not be modified.
1033 gtk_action_get_proxies (GtkAction *action)
1035 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1037 return action->private_data->proxies;
1042 * gtk_action_get_name:
1043 * @action: the action object
1045 * Returns the name of the action.
1047 * Return value: the name of the action. The string belongs to GTK+ and should not
1052 G_CONST_RETURN gchar *
1053 gtk_action_get_name (GtkAction *action)
1055 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1057 return action->private_data->name;
1061 * gtk_action_is_sensitive:
1062 * @action: the action object
1064 * Returns whether the action is effectively sensitive.
1066 * Return value: %TRUE if the action and its associated action group
1067 * are both sensitive.
1072 gtk_action_is_sensitive (GtkAction *action)
1074 GtkActionPrivate *priv;
1075 g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1077 priv = action->private_data;
1078 return priv->sensitive &&
1079 (priv->action_group == NULL ||
1080 gtk_action_group_get_sensitive (priv->action_group));
1084 * gtk_action_get_sensitive:
1085 * @action: the action object
1087 * Returns whether the action itself is sensitive. Note that this doesn't
1088 * necessarily mean effective sensitivity. See gtk_action_is_sensitive()
1091 * Return value: %TRUE if the action itself is sensitive.
1096 gtk_action_get_sensitive (GtkAction *action)
1098 g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1100 return action->private_data->sensitive;
1104 * gtk_action_set_sensitive:
1105 * @action: the action object
1106 * @sensitive: %TRUE to make the action sensitive
1108 * Sets the ::sensitive property of the action to @sensitive. Note that
1109 * this doesn't necessarily mean effective sensitivity. See
1110 * gtk_action_is_sensitive()
1116 gtk_action_set_sensitive (GtkAction *action,
1122 g_return_if_fail (GTK_IS_ACTION (action));
1124 sensitive = sensitive != FALSE;
1126 if (action->private_data->sensitive != sensitive)
1128 action->private_data->sensitive = sensitive;
1130 for (p = action->private_data->proxies; p; p = p->next)
1132 proxy = (GtkWidget *)p->data;
1133 gtk_widget_set_sensitive (proxy, sensitive);
1136 g_object_notify (G_OBJECT (action), "sensitive");
1141 * gtk_action_is_visible:
1142 * @action: the action object
1144 * Returns whether the action is effectively visible.
1146 * Return value: %TRUE if the action and its associated action group
1152 gtk_action_is_visible (GtkAction *action)
1154 GtkActionPrivate *priv;
1155 g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1157 priv = action->private_data;
1158 return priv->visible &&
1159 (priv->action_group == NULL ||
1160 gtk_action_group_get_visible (priv->action_group));
1164 * gtk_action_get_visible:
1165 * @action: the action object
1167 * Returns whether the action itself is visible. Note that this doesn't
1168 * necessarily mean effective visibility. See gtk_action_is_sensitive()
1171 * Return value: %TRUE if the action itself is visible.
1176 gtk_action_get_visible (GtkAction *action)
1178 g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
1180 return action->private_data->visible;
1184 * gtk_action_set_visible:
1185 * @action: the action object
1186 * @visible: %TRUE to make the action visible
1188 * Sets the ::visible property of the action to @visible. Note that
1189 * this doesn't necessarily mean effective visibility. See
1190 * gtk_action_is_visible()
1196 gtk_action_set_visible (GtkAction *action,
1202 g_return_if_fail (GTK_IS_ACTION (action));
1204 visible = visible != FALSE;
1206 if (action->private_data->visible != visible)
1208 action->private_data->visible = visible;
1210 for (p = action->private_data->proxies; p; p = p->next)
1212 proxy = (GtkWidget *)p->data;
1214 if (GTK_IS_MENU_ITEM (proxy))
1216 GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
1218 _gtk_action_sync_menu_visible (action, proxy, _gtk_menu_is_empty (menu));
1223 gtk_widget_show (proxy);
1225 gtk_widget_hide (proxy);
1229 g_object_notify (G_OBJECT (action), "visible");
1234 gtk_action_set_is_important (GtkAction *action,
1235 gboolean is_important)
1240 is_important = is_important != FALSE;
1242 if (action->private_data->is_important != is_important)
1244 action->private_data->is_important = is_important;
1246 for (p = action->private_data->proxies; p; p = p->next)
1248 proxy = (GtkWidget *)p->data;
1250 if (GTK_IS_TOOL_ITEM (proxy))
1251 gtk_tool_item_set_is_important (GTK_TOOL_ITEM (proxy),
1255 g_object_notify (G_OBJECT (action), "is-important");
1260 gtk_action_set_label (GtkAction *action,
1264 GtkWidget *proxy, *child;
1267 tmp = action->private_data->label;
1268 action->private_data->label = g_strdup (label);
1270 action->private_data->label_set = (action->private_data->label != NULL);
1271 /* if label is unset, then use the label from the stock item */
1272 if (!action->private_data->label_set && action->private_data->stock_id)
1274 GtkStockItem stock_item;
1276 if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1277 action->private_data->label = g_strdup (stock_item.label);
1280 for (p = action->private_data->proxies; p; p = p->next)
1282 proxy = (GtkWidget *)p->data;
1284 if (GTK_IS_MENU_ITEM (proxy))
1286 child = GTK_BIN (proxy)->child;
1288 if (GTK_IS_LABEL (child))
1289 gtk_label_set_label (GTK_LABEL (child),
1290 action->private_data->label);
1294 g_object_notify (G_OBJECT (action), "label");
1296 /* if short_label is unset, set short_label=label */
1297 if (!action->private_data->short_label_set)
1299 gtk_action_set_short_label (action, action->private_data->label);
1300 action->private_data->short_label_set = FALSE;
1305 gtk_action_set_short_label (GtkAction *action,
1309 GtkWidget *proxy, *child;
1312 tmp = action->private_data->short_label;
1313 action->private_data->short_label = g_strdup (label);
1315 action->private_data->short_label_set = (action->private_data->short_label != NULL);
1316 /* if short_label is unset, then use the value of label */
1317 if (!action->private_data->short_label_set)
1318 action->private_data->short_label = g_strdup (action->private_data->label);
1320 for (p = action->private_data->proxies; p; p = p->next)
1322 proxy = (GtkWidget *)p->data;
1324 if (GTK_IS_TOOL_BUTTON (proxy))
1325 gtk_tool_button_set_label (GTK_TOOL_BUTTON (proxy),
1326 action->private_data->label);
1327 else if (GTK_IS_BUTTON (proxy) &&
1328 !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
1330 child = GTK_BIN (proxy)->child;
1332 if (child == NULL || GTK_IS_LABEL (child))
1333 gtk_button_set_label (GTK_BUTTON (proxy),
1334 action->private_data->label);
1338 g_object_notify (G_OBJECT (action), "short-label");
1342 gtk_action_set_visible_horizontal (GtkAction *action,
1343 gboolean visible_horizontal)
1348 visible_horizontal = visible_horizontal != FALSE;
1350 if (action->private_data->visible_horizontal != visible_horizontal)
1352 action->private_data->visible_horizontal = visible_horizontal;
1354 for (p = action->private_data->proxies; p; p = p->next)
1356 proxy = (GtkWidget *)p->data;
1358 if (GTK_IS_TOOL_ITEM (proxy))
1359 gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (proxy),
1360 visible_horizontal);
1363 g_object_notify (G_OBJECT (action), "visible-horizontal");
1368 gtk_action_set_visible_vertical (GtkAction *action,
1369 gboolean visible_vertical)
1374 visible_vertical = visible_vertical != FALSE;
1376 if (action->private_data->visible_vertical != visible_vertical)
1378 action->private_data->visible_vertical = visible_vertical;
1380 for (p = action->private_data->proxies; p; p = p->next)
1382 proxy = (GtkWidget *)p->data;
1384 if (GTK_IS_TOOL_ITEM (proxy))
1385 gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (proxy),
1389 g_object_notify (G_OBJECT (action), "visible-vertical");
1394 gtk_action_sync_tooltip (GtkAction *action,
1399 parent = gtk_widget_get_parent (proxy);
1401 if (GTK_IS_TOOL_ITEM (proxy) && GTK_IS_TOOLBAR (parent))
1402 gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (proxy),
1403 GTK_TOOLBAR (parent)->tooltips,
1404 action->private_data->tooltip,
1409 gtk_action_set_tooltip (GtkAction *action,
1410 const gchar *tooltip)
1416 tmp = action->private_data->tooltip;
1417 action->private_data->tooltip = g_strdup (tooltip);
1420 for (p = action->private_data->proxies; p; p = p->next)
1422 proxy = (GtkWidget *)p->data;
1424 gtk_action_sync_tooltip (action, proxy);
1427 g_object_notify (G_OBJECT (action), "tooltip");
1431 gtk_action_set_stock_id (GtkAction *action,
1432 const gchar *stock_id)
1435 GtkWidget *proxy, *image;
1438 tmp = action->private_data->stock_id;
1439 action->private_data->stock_id = g_strdup (stock_id);
1442 for (p = action->private_data->proxies; p; p = p->next)
1444 proxy = (GtkWidget *)p->data;
1446 if (GTK_IS_IMAGE_MENU_ITEM (proxy))
1448 image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
1450 if (GTK_IS_IMAGE (image))
1451 gtk_image_set_from_stock (GTK_IMAGE (image),
1452 action->private_data->stock_id, GTK_ICON_SIZE_MENU);
1454 else if (GTK_IS_TOOL_BUTTON (proxy))
1456 gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (proxy),
1457 action->private_data->stock_id);
1459 else if (GTK_IS_BUTTON (proxy) &&
1460 gtk_button_get_use_stock (GTK_BUTTON (proxy)))
1462 gtk_button_set_label (GTK_BUTTON (proxy),
1463 action->private_data->stock_id);
1467 g_object_notify (G_OBJECT (action), "stock-id");
1469 /* update label and short_label if appropriate */
1470 if (!action->private_data->label_set)
1472 GtkStockItem stock_item;
1474 if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
1475 gtk_action_set_label (action, stock_item.label);
1477 gtk_action_set_label (action, NULL);
1479 action->private_data->label_set = FALSE;
1485 * gtk_action_block_activate_from:
1486 * @action: the action object
1487 * @proxy: a proxy widget
1489 * Disables calls to the gtk_action_activate()
1490 * function by signals on the given proxy widget. This is used to
1491 * break notification loops for things like check or radio actions.
1493 * This function is intended for use by action implementations.
1498 gtk_action_block_activate_from (GtkAction *action,
1501 g_return_if_fail (GTK_IS_ACTION (action));
1503 g_signal_handlers_block_by_func (proxy, G_CALLBACK (gtk_action_activate),
1508 * gtk_action_unblock_activate_from:
1509 * @action: the action object
1510 * @proxy: a proxy widget
1512 * Re-enables calls to the gtk_action_activate()
1513 * function by signals on the given proxy widget. This undoes the
1514 * blocking done by gtk_action_block_activate_from().
1516 * This function is intended for use by action implementations.
1521 gtk_action_unblock_activate_from (GtkAction *action,
1524 g_return_if_fail (GTK_IS_ACTION (action));
1526 g_signal_handlers_unblock_by_func (proxy, G_CALLBACK (gtk_action_activate),
1531 closure_accel_activate (GClosure *closure,
1532 GValue *return_value,
1533 guint n_param_values,
1534 const GValue *param_values,
1535 gpointer invocation_hint,
1536 gpointer marshal_data)
1538 if (gtk_action_is_sensitive (GTK_ACTION (closure->data)))
1540 _gtk_action_emit_activate (GTK_ACTION (closure->data));
1542 /* we handled the accelerator */
1543 g_value_set_boolean (return_value, TRUE);
1548 gtk_action_set_action_group (GtkAction *action,
1549 GtkActionGroup *action_group)
1551 g_return_if_fail (GTK_IS_ACTION (action));
1553 if (action->private_data->action_group == NULL)
1554 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1556 g_return_if_fail (action_group == NULL);
1558 action->private_data->action_group = action_group;
1562 * gtk_action_set_accel_path:
1563 * @action: the action object
1564 * @accel_path: the accelerator path
1566 * Sets the accel path for this action. All proxy widgets associated
1567 * with the action will have this accel path, so that their
1568 * accelerators are consistent.
1573 gtk_action_set_accel_path (GtkAction *action,
1574 const gchar *accel_path)
1576 g_return_if_fail (GTK_IS_ACTION (action));
1578 action->private_data->accel_quark = g_quark_from_string (accel_path);
1582 * gtk_action_get_accel_path:
1583 * @action: the action object
1585 * Returns the accel path for this action.
1589 * Returns: the accel path for this action, or %NULL
1590 * if none is set. The returned string is owned by GTK+
1591 * and must not be freed or modified.
1593 G_CONST_RETURN gchar *
1594 gtk_action_get_accel_path (GtkAction *action)
1596 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1598 if (action->private_data->accel_quark)
1599 return g_quark_to_string (action->private_data->accel_quark);
1605 * gtk_action_get_accel_closure:
1606 * @action: the action object
1608 * Returns the accel closure for this action.
1612 * Returns: the accel closure for this action. The returned closure is
1613 * owned by GTK+ and must not be unreffed or modified.
1616 gtk_action_get_accel_closure (GtkAction *action)
1618 g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
1620 return action->private_data->accel_closure;
1625 * gtk_action_set_accel_group:
1626 * @action: the action object
1627 * @accel_group: a #GtkAccelGroup or %NULL
1629 * Sets the #GtkAccelGroup in which the accelerator for this action
1630 * will be installed.
1635 gtk_action_set_accel_group (GtkAction *action,
1636 GtkAccelGroup *accel_group)
1638 g_return_if_fail (GTK_IS_ACTION (action));
1639 g_return_if_fail (accel_group == NULL || GTK_IS_ACCEL_GROUP (accel_group));
1642 g_object_ref (accel_group);
1643 if (action->private_data->accel_group)
1644 g_object_unref (action->private_data->accel_group);
1646 action->private_data->accel_group = accel_group;
1650 * gtk_action_connect_accelerator:
1651 * @action: a #GtkAction
1653 * Installs the accelerator for @action if @action has an
1654 * accel path and group. See gtk_action_set_accel_path() and
1655 * gtk_action_set_accel_group()
1657 * Since multiple proxies may independently trigger the installation
1658 * of the accelerator, the @action counts the number of times this
1659 * function has been called and doesn't remove the accelerator until
1660 * gtk_action_disconnect_accelerator() has been called as many times.
1665 gtk_action_connect_accelerator (GtkAction *action)
1667 g_return_if_fail (GTK_IS_ACTION (action));
1669 if (!action->private_data->accel_quark ||
1670 !action->private_data->accel_group)
1673 if (action->private_data->accel_count == 0)
1675 const gchar *accel_path =
1676 g_quark_to_string (action->private_data->accel_quark);
1678 gtk_accel_group_connect_by_path (action->private_data->accel_group,
1680 action->private_data->accel_closure);
1683 action->private_data->accel_count++;
1687 * gtk_action_disconnect_accelerator:
1688 * @action: a #GtkAction
1690 * Undoes the effect of one call to gtk_action_connect_accelerator().
1695 gtk_action_disconnect_accelerator (GtkAction *action)
1697 g_return_if_fail (GTK_IS_ACTION (action));
1699 if (!action->private_data->accel_quark ||
1700 !action->private_data->accel_group)
1703 action->private_data->accel_count--;
1705 if (action->private_data->accel_count == 0)
1706 gtk_accel_group_disconnect (action->private_data->accel_group,
1707 action->private_data->accel_closure);
1710 #define __GTK_ACTION_C__
1711 #include "gtkaliasdef.c"