1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2001 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtkimagemenuitem.h"
29 #include "gtkmenuitemprivate.h"
30 #include "gtkaccellabel.h"
32 #include "gtkiconfactory.h"
34 #include "gtkmenubar.h"
35 #include "gtkcontainer.h"
36 #include "gtkwindow.h"
37 #include "gtkactivatable.h"
40 #include "gtkprivate.h"
44 * SECTION:gtkimagemenuitem
45 * @Short_description: A menu item with an icon
46 * @Title: GtkImageMenuItem
48 * A GtkImageMenuItem is a menu item which has an icon next to the text label.
50 * Note that the user can disable display of menu icons, so make sure to still
51 * fill in the text label.
55 struct _GtkImageMenuItemPrivate
61 guint always_show_image : 1;
69 PROP_ALWAYS_SHOW_IMAGE
72 static GtkActivatableIface *parent_activatable_iface;
74 static void gtk_image_menu_item_destroy (GtkWidget *widget);
75 static void gtk_image_menu_item_get_preferred_width (GtkWidget *widget,
78 static void gtk_image_menu_item_get_preferred_height (GtkWidget *widget,
81 static void gtk_image_menu_item_get_preferred_height_for_width (GtkWidget *widget,
85 static void gtk_image_menu_item_size_allocate (GtkWidget *widget,
86 GtkAllocation *allocation);
87 static void gtk_image_menu_item_map (GtkWidget *widget);
88 static void gtk_image_menu_item_remove (GtkContainer *container,
90 static void gtk_image_menu_item_toggle_size_request (GtkMenuItem *menu_item,
92 static void gtk_image_menu_item_set_label (GtkMenuItem *menu_item,
94 static const gchar * gtk_image_menu_item_get_label (GtkMenuItem *menu_item);
96 static void gtk_image_menu_item_forall (GtkContainer *container,
97 gboolean include_internals,
99 gpointer callback_data);
101 static void gtk_image_menu_item_finalize (GObject *object);
102 static void gtk_image_menu_item_set_property (GObject *object,
106 static void gtk_image_menu_item_get_property (GObject *object,
110 static void gtk_image_menu_item_screen_changed (GtkWidget *widget,
111 GdkScreen *previous_screen);
113 static void gtk_image_menu_item_recalculate (GtkImageMenuItem *image_menu_item);
115 static void gtk_image_menu_item_activatable_interface_init (GtkActivatableIface *iface);
116 static void gtk_image_menu_item_update (GtkActivatable *activatable,
118 const gchar *property_name);
119 static void gtk_image_menu_item_sync_action_properties (GtkActivatable *activatable,
123 G_DEFINE_TYPE_WITH_CODE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM,
124 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
125 gtk_image_menu_item_activatable_interface_init))
129 gtk_image_menu_item_class_init (GtkImageMenuItemClass *klass)
131 GObjectClass *gobject_class = (GObjectClass*) klass;
132 GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
133 GtkMenuItemClass *menu_item_class = (GtkMenuItemClass*) klass;
134 GtkContainerClass *container_class = (GtkContainerClass*) klass;
136 widget_class->destroy = gtk_image_menu_item_destroy;
137 widget_class->screen_changed = gtk_image_menu_item_screen_changed;
138 widget_class->get_preferred_width = gtk_image_menu_item_get_preferred_width;
139 widget_class->get_preferred_height = gtk_image_menu_item_get_preferred_height;
140 widget_class->get_preferred_height_for_width = gtk_image_menu_item_get_preferred_height_for_width;
141 widget_class->size_allocate = gtk_image_menu_item_size_allocate;
142 widget_class->map = gtk_image_menu_item_map;
144 container_class->forall = gtk_image_menu_item_forall;
145 container_class->remove = gtk_image_menu_item_remove;
147 menu_item_class->toggle_size_request = gtk_image_menu_item_toggle_size_request;
148 menu_item_class->set_label = gtk_image_menu_item_set_label;
149 menu_item_class->get_label = gtk_image_menu_item_get_label;
151 gobject_class->finalize = gtk_image_menu_item_finalize;
152 gobject_class->set_property = gtk_image_menu_item_set_property;
153 gobject_class->get_property = gtk_image_menu_item_get_property;
155 g_object_class_install_property (gobject_class,
157 g_param_spec_object ("image",
159 P_("Child widget to appear next to the menu text"),
161 GTK_PARAM_READWRITE));
163 * GtkImageMenuItem:use-stock:
165 * If %TRUE, the label set in the menuitem is used as a
166 * stock id to select the stock item for the item.
170 g_object_class_install_property (gobject_class,
172 g_param_spec_boolean ("use-stock",
174 P_("Whether to use the label text to create a stock menu item"),
176 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
179 * GtkImageMenuItem:always-show-image:
181 * If %TRUE, the menu item will ignore the #GtkSettings:gtk-menu-images
182 * setting and always show the image, if available.
184 * Use this property if the menuitem would be useless or hard to use
189 g_object_class_install_property (gobject_class,
190 PROP_ALWAYS_SHOW_IMAGE,
191 g_param_spec_boolean ("always-show-image",
192 P_("Always show image"),
193 P_("Whether the image will always be shown"),
195 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
198 * GtkImageMenuItem:accel-group:
200 * The Accel Group to use for stock accelerator keys
204 g_object_class_install_property (gobject_class,
206 g_param_spec_object ("accel-group",
208 P_("The Accel Group to use for stock accelerator keys"),
209 GTK_TYPE_ACCEL_GROUP,
210 GTK_PARAM_WRITABLE));
212 g_type_class_add_private (klass, sizeof (GtkImageMenuItemPrivate));
216 gtk_image_menu_item_init (GtkImageMenuItem *image_menu_item)
218 GtkImageMenuItemPrivate *priv;
220 image_menu_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (image_menu_item,
221 GTK_TYPE_IMAGE_MENU_ITEM,
222 GtkImageMenuItemPrivate);
223 priv = image_menu_item->priv;
226 priv->use_stock = FALSE;
231 gtk_image_menu_item_finalize (GObject *object)
233 GtkImageMenuItemPrivate *priv = GTK_IMAGE_MENU_ITEM (object)->priv;
235 g_free (priv->label);
238 G_OBJECT_CLASS (gtk_image_menu_item_parent_class)->finalize (object);
242 gtk_image_menu_item_set_property (GObject *object,
247 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (object);
252 gtk_image_menu_item_set_image (image_menu_item, (GtkWidget *) g_value_get_object (value));
255 gtk_image_menu_item_set_use_stock (image_menu_item, g_value_get_boolean (value));
257 case PROP_ALWAYS_SHOW_IMAGE:
258 gtk_image_menu_item_set_always_show_image (image_menu_item, g_value_get_boolean (value));
260 case PROP_ACCEL_GROUP:
261 gtk_image_menu_item_set_accel_group (image_menu_item, g_value_get_object (value));
264 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270 gtk_image_menu_item_get_property (GObject *object,
275 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (object);
280 g_value_set_object (value, gtk_image_menu_item_get_image (image_menu_item));
283 g_value_set_boolean (value, gtk_image_menu_item_get_use_stock (image_menu_item));
285 case PROP_ALWAYS_SHOW_IMAGE:
286 g_value_set_boolean (value, gtk_image_menu_item_get_always_show_image (image_menu_item));
289 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
295 show_image (GtkImageMenuItem *image_menu_item)
297 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
298 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (image_menu_item));
301 if (priv->always_show_image)
304 g_object_get (settings, "gtk-menu-images", &show, NULL);
310 gtk_image_menu_item_map (GtkWidget *widget)
312 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
313 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
315 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->map (widget);
318 g_object_set (priv->image,
319 "visible", show_image (image_menu_item),
324 gtk_image_menu_item_destroy (GtkWidget *widget)
326 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
327 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
330 gtk_container_remove (GTK_CONTAINER (image_menu_item),
333 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->destroy (widget);
337 gtk_image_menu_item_toggle_size_request (GtkMenuItem *menu_item,
340 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item);
341 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
342 GtkPackDirection pack_dir;
344 GtkWidget *widget = GTK_WIDGET (menu_item);
346 parent = gtk_widget_get_parent (widget);
348 if (GTK_IS_MENU_BAR (parent))
349 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
351 pack_dir = GTK_PACK_DIRECTION_LTR;
355 if (priv->image && gtk_widget_get_visible (priv->image))
357 GtkRequisition image_requisition;
358 guint toggle_spacing;
360 gtk_widget_get_preferred_size (priv->image, &image_requisition, NULL);
362 gtk_widget_style_get (GTK_WIDGET (menu_item),
363 "toggle-spacing", &toggle_spacing,
366 if (pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL)
368 if (image_requisition.width > 0)
369 *requisition = image_requisition.width + toggle_spacing;
373 if (image_requisition.height > 0)
374 *requisition = image_requisition.height + toggle_spacing;
380 gtk_image_menu_item_recalculate (GtkImageMenuItem *image_menu_item)
382 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
383 GtkStockItem stock_item;
385 const gchar *resolved_label = priv->label;
387 if (priv->use_stock && priv->label)
392 image = gtk_image_new_from_stock (priv->label, GTK_ICON_SIZE_MENU);
393 gtk_image_menu_item_set_image (image_menu_item, image);
396 if (gtk_stock_lookup (priv->label, &stock_item))
397 resolved_label = stock_item.label;
399 gtk_menu_item_set_use_underline (GTK_MENU_ITEM (image_menu_item), TRUE);
403 (gtk_image_menu_item_parent_class)->set_label (GTK_MENU_ITEM (image_menu_item), resolved_label);
408 gtk_image_menu_item_set_label (GtkMenuItem *menu_item,
411 GtkImageMenuItemPrivate *priv = GTK_IMAGE_MENU_ITEM (menu_item)->priv;
413 if (priv->label != label)
415 g_free (priv->label);
416 priv->label = g_strdup (label);
418 gtk_image_menu_item_recalculate (GTK_IMAGE_MENU_ITEM (menu_item));
420 g_object_notify (G_OBJECT (menu_item), "label");
426 gtk_image_menu_item_get_label (GtkMenuItem *menu_item)
428 GtkImageMenuItemPrivate *priv = GTK_IMAGE_MENU_ITEM (menu_item)->priv;
434 gtk_image_menu_item_get_preferred_width (GtkWidget *widget,
438 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
439 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
440 GtkPackDirection pack_dir;
443 parent = gtk_widget_get_parent (widget);
445 if (GTK_IS_MENU_BAR (parent))
446 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
448 pack_dir = GTK_PACK_DIRECTION_LTR;
450 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->get_preferred_width (widget, minimum, natural);
452 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
454 gtk_widget_get_visible (priv->image))
456 gint child_minimum, child_natural;
458 gtk_widget_get_preferred_width (priv->image, &child_minimum, &child_natural);
460 *minimum = MAX (*minimum, child_minimum);
461 *natural = MAX (*natural, child_natural);
466 gtk_image_menu_item_get_preferred_height (GtkWidget *widget,
470 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
471 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
472 gint child_height = 0;
473 GtkPackDirection pack_dir;
476 parent = gtk_widget_get_parent (widget);
478 if (GTK_IS_MENU_BAR (parent))
479 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
481 pack_dir = GTK_PACK_DIRECTION_LTR;
483 if (priv->image && gtk_widget_get_visible (priv->image))
485 GtkRequisition child_requisition;
487 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
489 child_height = child_requisition.height;
492 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->get_preferred_height (widget, minimum, natural);
494 if (pack_dir == GTK_PACK_DIRECTION_RTL || pack_dir == GTK_PACK_DIRECTION_LTR)
496 *minimum = MAX (*minimum, child_height);
497 *natural = MAX (*natural, child_height);
502 gtk_image_menu_item_get_preferred_height_for_width (GtkWidget *widget,
507 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
508 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
509 gint child_height = 0;
510 GtkPackDirection pack_dir;
513 parent = gtk_widget_get_parent (widget);
515 if (GTK_IS_MENU_BAR (parent))
516 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
518 pack_dir = GTK_PACK_DIRECTION_LTR;
520 if (priv->image && gtk_widget_get_visible (priv->image))
522 GtkRequisition child_requisition;
524 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
526 child_height = child_requisition.height;
530 (gtk_image_menu_item_parent_class)->get_preferred_height_for_width (widget, width, minimum, natural);
532 if (pack_dir == GTK_PACK_DIRECTION_RTL || pack_dir == GTK_PACK_DIRECTION_LTR)
534 *minimum = MAX (*minimum, child_height);
535 *natural = MAX (*natural, child_height);
541 gtk_image_menu_item_size_allocate (GtkWidget *widget,
542 GtkAllocation *allocation)
544 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
545 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
546 GtkAllocation widget_allocation;
547 GtkPackDirection pack_dir;
550 parent = gtk_widget_get_parent (widget);
552 if (GTK_IS_MENU_BAR (parent))
553 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
555 pack_dir = GTK_PACK_DIRECTION_LTR;
557 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->size_allocate (widget, allocation);
559 if (priv->image && gtk_widget_get_visible (priv->image))
562 GtkStyleContext *context;
565 GtkRequisition child_requisition;
566 GtkAllocation child_allocation;
567 guint horizontal_padding, toggle_spacing;
570 toggle_size = GTK_MENU_ITEM (image_menu_item)->priv->toggle_size;
571 gtk_widget_style_get (widget,
572 "horizontal-padding", &horizontal_padding,
573 "toggle-spacing", &toggle_spacing,
576 /* Man this is lame hardcoding action, but I can't
577 * come up with a solution that's really better.
580 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
582 gtk_widget_get_allocation (widget, &widget_allocation);
584 context = gtk_widget_get_style_context (widget);
585 state = gtk_widget_get_state_flags (widget);
586 gtk_style_context_get_padding (context, state, &padding);
587 offset = gtk_container_get_border_width (GTK_CONTAINER (image_menu_item));
589 if (pack_dir == GTK_PACK_DIRECTION_LTR ||
590 pack_dir == GTK_PACK_DIRECTION_RTL)
592 if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) ==
593 (pack_dir == GTK_PACK_DIRECTION_LTR))
594 x = offset + horizontal_padding + padding.left +
595 (toggle_size - toggle_spacing - child_requisition.width) / 2;
597 x = widget_allocation.width - offset - horizontal_padding - padding.right -
598 toggle_size + toggle_spacing +
599 (toggle_size - toggle_spacing - child_requisition.width) / 2;
601 y = (widget_allocation.height - child_requisition.height) / 2;
605 if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) ==
606 (pack_dir == GTK_PACK_DIRECTION_TTB))
607 y = offset + horizontal_padding + padding.top +
608 (toggle_size - toggle_spacing - child_requisition.height) / 2;
610 y = widget_allocation.height - offset - horizontal_padding - padding.bottom -
611 toggle_size + toggle_spacing +
612 (toggle_size - toggle_spacing - child_requisition.height) / 2;
614 x = (widget_allocation.width - child_requisition.width) / 2;
617 child_allocation.width = child_requisition.width;
618 child_allocation.height = child_requisition.height;
619 child_allocation.x = widget_allocation.x + MAX (x, 0);
620 child_allocation.y = widget_allocation.y + MAX (y, 0);
622 gtk_widget_size_allocate (priv->image, &child_allocation);
627 gtk_image_menu_item_forall (GtkContainer *container,
628 gboolean include_internals,
629 GtkCallback callback,
630 gpointer callback_data)
632 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (container);
633 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
635 GTK_CONTAINER_CLASS (gtk_image_menu_item_parent_class)->forall (container,
640 if (include_internals && priv->image)
641 (* callback) (priv->image, callback_data);
646 gtk_image_menu_item_activatable_interface_init (GtkActivatableIface *iface)
648 parent_activatable_iface = g_type_interface_peek_parent (iface);
649 iface->update = gtk_image_menu_item_update;
650 iface->sync_action_properties = gtk_image_menu_item_sync_action_properties;
654 activatable_update_stock_id (GtkImageMenuItem *image_menu_item, GtkAction *action)
657 const gchar *stock_id = gtk_action_get_stock_id (action);
659 image = gtk_image_menu_item_get_image (image_menu_item);
661 if (GTK_IS_IMAGE (image) &&
662 stock_id && gtk_icon_factory_lookup_default (stock_id))
664 gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU);
672 activatable_update_gicon (GtkImageMenuItem *image_menu_item, GtkAction *action)
675 GIcon *icon = gtk_action_get_gicon (action);
676 const gchar *stock_id = gtk_action_get_stock_id (action);
678 image = gtk_image_menu_item_get_image (image_menu_item);
680 if (icon && GTK_IS_IMAGE (image) &&
681 !(stock_id && gtk_icon_factory_lookup_default (stock_id)))
683 gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU);
691 activatable_update_icon_name (GtkImageMenuItem *image_menu_item, GtkAction *action)
694 const gchar *icon_name = gtk_action_get_icon_name (action);
696 image = gtk_image_menu_item_get_image (image_menu_item);
698 if (GTK_IS_IMAGE (image) &&
699 (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
700 gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
702 gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
707 gtk_image_menu_item_update (GtkActivatable *activatable,
709 const gchar *property_name)
711 GtkImageMenuItem *image_menu_item;
712 gboolean use_appearance;
714 image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
716 parent_activatable_iface->update (activatable, action, property_name);
718 use_appearance = gtk_activatable_get_use_action_appearance (activatable);
722 if (strcmp (property_name, "stock-id") == 0)
723 activatable_update_stock_id (image_menu_item, action);
724 else if (strcmp (property_name, "gicon") == 0)
725 activatable_update_gicon (image_menu_item, action);
726 else if (strcmp (property_name, "icon-name") == 0)
727 activatable_update_icon_name (image_menu_item, action);
731 gtk_image_menu_item_sync_action_properties (GtkActivatable *activatable,
734 GtkImageMenuItem *image_menu_item;
736 gboolean use_appearance;
738 image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
740 parent_activatable_iface->sync_action_properties (activatable, action);
745 use_appearance = gtk_activatable_get_use_action_appearance (activatable);
749 image = gtk_image_menu_item_get_image (image_menu_item);
750 if (image && !GTK_IS_IMAGE (image))
752 gtk_image_menu_item_set_image (image_menu_item, NULL);
758 image = gtk_image_new ();
759 gtk_widget_show (image);
760 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable),
764 if (!activatable_update_stock_id (image_menu_item, action) &&
765 !activatable_update_gicon (image_menu_item, action))
766 activatable_update_icon_name (image_menu_item, action);
768 gtk_image_menu_item_set_always_show_image (image_menu_item,
769 gtk_action_get_always_show_image (action));
774 * gtk_image_menu_item_new:
776 * Creates a new #GtkImageMenuItem with an empty label.
778 * Returns: a new #GtkImageMenuItem
781 gtk_image_menu_item_new (void)
783 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM, NULL);
787 * gtk_image_menu_item_new_with_label:
788 * @label: the text of the menu item.
790 * Creates a new #GtkImageMenuItem containing a label.
792 * Returns: a new #GtkImageMenuItem.
795 gtk_image_menu_item_new_with_label (const gchar *label)
797 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM,
803 * gtk_image_menu_item_new_with_mnemonic:
804 * @label: the text of the menu item, with an underscore in front of the
807 * Creates a new #GtkImageMenuItem containing a label. The label
808 * will be created using gtk_label_new_with_mnemonic(), so underscores
809 * in @label indicate the mnemonic for the menu item.
811 * Returns: a new #GtkImageMenuItem
814 gtk_image_menu_item_new_with_mnemonic (const gchar *label)
816 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM,
817 "use-underline", TRUE,
823 * gtk_image_menu_item_new_from_stock:
824 * @stock_id: the name of the stock item.
825 * @accel_group: (allow-none): the #GtkAccelGroup to add the menu items
826 * accelerator to, or %NULL.
828 * Creates a new #GtkImageMenuItem containing the image and text from a
829 * stock item. Some stock ids have preprocessor macros like #GTK_STOCK_OK
830 * and #GTK_STOCK_APPLY.
832 * If you want this menu item to have changeable accelerators, then pass in
833 * %NULL for accel_group. Next call gtk_menu_item_set_accel_path() with an
834 * appropriate path for the menu item, use gtk_stock_lookup() to look up the
835 * standard accelerator for the stock item, and if one is found, call
836 * gtk_accel_map_add_entry() to register it.
838 * Returns: a new #GtkImageMenuItem.
841 gtk_image_menu_item_new_from_stock (const gchar *stock_id,
842 GtkAccelGroup *accel_group)
844 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM,
847 "accel-group", accel_group,
852 * gtk_image_menu_item_set_use_stock:
853 * @image_menu_item: a #GtkImageMenuItem
854 * @use_stock: %TRUE if the menuitem should use a stock item
856 * If %TRUE, the label set in the menuitem is used as a
857 * stock id to select the stock item for the item.
862 gtk_image_menu_item_set_use_stock (GtkImageMenuItem *image_menu_item,
865 GtkImageMenuItemPrivate *priv;
867 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
869 priv = image_menu_item->priv;
871 if (priv->use_stock != use_stock)
873 priv->use_stock = use_stock;
875 gtk_image_menu_item_recalculate (image_menu_item);
877 g_object_notify (G_OBJECT (image_menu_item), "use-stock");
882 * gtk_image_menu_item_get_use_stock:
883 * @image_menu_item: a #GtkImageMenuItem
885 * Checks whether the label set in the menuitem is used as a
886 * stock id to select the stock item for the item.
888 * Returns: %TRUE if the label set in the menuitem is used as a
889 * stock id to select the stock item for the item
894 gtk_image_menu_item_get_use_stock (GtkImageMenuItem *image_menu_item)
896 g_return_val_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item), FALSE);
898 return image_menu_item->priv->use_stock;
902 * gtk_image_menu_item_set_always_show_image:
903 * @image_menu_item: a #GtkImageMenuItem
904 * @always_show: %TRUE if the menuitem should always show the image
906 * If %TRUE, the menu item will ignore the #GtkSettings:gtk-menu-images
907 * setting and always show the image, if available.
909 * Use this property if the menuitem would be useless or hard to use
915 gtk_image_menu_item_set_always_show_image (GtkImageMenuItem *image_menu_item,
916 gboolean always_show)
918 GtkImageMenuItemPrivate *priv;
920 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
922 priv = image_menu_item->priv;
924 if (priv->always_show_image != always_show)
926 priv->always_show_image = always_show;
930 if (show_image (image_menu_item))
931 gtk_widget_show (priv->image);
933 gtk_widget_hide (priv->image);
936 g_object_notify (G_OBJECT (image_menu_item), "always-show-image");
941 * gtk_image_menu_item_get_always_show_image:
942 * @image_menu_item: a #GtkImageMenuItem
944 * Returns whether the menu item will ignore the #GtkSettings:gtk-menu-images
945 * setting and always show the image, if available.
947 * Returns: %TRUE if the menu item will always show the image
952 gtk_image_menu_item_get_always_show_image (GtkImageMenuItem *image_menu_item)
954 g_return_val_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item), FALSE);
956 return image_menu_item->priv->always_show_image;
961 * gtk_image_menu_item_set_accel_group:
962 * @image_menu_item: a #GtkImageMenuItem
963 * @accel_group: the #GtkAccelGroup
965 * Specifies an @accel_group to add the menu items accelerator to
966 * (this only applies to stock items so a stock item must already
967 * be set, make sure to call gtk_image_menu_item_set_use_stock()
968 * and gtk_menu_item_set_label() with a valid stock item first).
970 * If you want this menu item to have changeable accelerators then
971 * you shouldnt need this (see gtk_image_menu_item_new_from_stock()).
976 gtk_image_menu_item_set_accel_group (GtkImageMenuItem *image_menu_item,
977 GtkAccelGroup *accel_group)
979 GtkImageMenuItemPrivate *priv;
980 GtkStockItem stock_item;
982 /* Silent return for the constructor */
986 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
987 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
989 priv = image_menu_item->priv;
991 if (priv->use_stock && priv->label && gtk_stock_lookup (priv->label, &stock_item))
992 if (stock_item.keyval)
994 gtk_widget_add_accelerator (GTK_WIDGET (image_menu_item),
1001 g_object_notify (G_OBJECT (image_menu_item), "accel-group");
1006 * gtk_image_menu_item_set_image:
1007 * @image_menu_item: a #GtkImageMenuItem.
1008 * @image: (allow-none): a widget to set as the image for the menu item.
1010 * Sets the image of @image_menu_item to the given widget.
1011 * Note that it depends on the show-menu-images setting whether
1012 * the image will be displayed or not.
1015 gtk_image_menu_item_set_image (GtkImageMenuItem *image_menu_item,
1018 GtkImageMenuItemPrivate *priv;
1020 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
1022 priv = image_menu_item->priv;
1024 if (image == priv->image)
1028 gtk_container_remove (GTK_CONTAINER (image_menu_item),
1031 priv->image = image;
1036 gtk_widget_set_parent (image, GTK_WIDGET (image_menu_item));
1037 g_object_set (image,
1038 "visible", show_image (image_menu_item),
1039 "no-show-all", TRUE,
1042 g_object_notify (G_OBJECT (image_menu_item), "image");
1046 * gtk_image_menu_item_get_image:
1047 * @image_menu_item: a #GtkImageMenuItem
1049 * Gets the widget that is currently set as the image of @image_menu_item.
1050 * See gtk_image_menu_item_set_image().
1052 * Return value: (transfer none): the widget set as image of @image_menu_item
1055 gtk_image_menu_item_get_image (GtkImageMenuItem *image_menu_item)
1057 g_return_val_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item), NULL);
1059 return image_menu_item->priv->image;
1063 gtk_image_menu_item_remove (GtkContainer *container,
1066 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (container);
1067 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
1069 if (child == priv->image)
1071 gboolean widget_was_visible;
1073 widget_was_visible = gtk_widget_get_visible (child);
1075 gtk_widget_unparent (child);
1078 if (widget_was_visible &&
1079 gtk_widget_get_visible (GTK_WIDGET (container)))
1080 gtk_widget_queue_resize (GTK_WIDGET (container));
1082 g_object_notify (G_OBJECT (image_menu_item), "image");
1086 GTK_CONTAINER_CLASS (gtk_image_menu_item_parent_class)->remove (container, child);
1091 show_image_change_notify (GtkImageMenuItem *image_menu_item)
1093 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
1097 if (show_image (image_menu_item))
1098 gtk_widget_show (priv->image);
1100 gtk_widget_hide (priv->image);
1105 traverse_container (GtkWidget *widget,
1108 if (GTK_IS_IMAGE_MENU_ITEM (widget))
1109 show_image_change_notify (GTK_IMAGE_MENU_ITEM (widget));
1110 else if (GTK_IS_CONTAINER (widget))
1111 gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL);
1115 gtk_image_menu_item_setting_changed (GtkSettings *settings)
1119 list = gtk_window_list_toplevels ();
1121 for (l = list; l; l = l->next)
1122 gtk_container_forall (GTK_CONTAINER (l->data),
1123 traverse_container, NULL);
1129 gtk_image_menu_item_screen_changed (GtkWidget *widget,
1130 GdkScreen *previous_screen)
1132 GtkSettings *settings;
1133 gulong show_image_connection;
1135 if (!gtk_widget_has_screen (widget))
1138 settings = gtk_widget_get_settings (widget);
1140 show_image_connection =
1141 g_signal_handler_find (settings, G_SIGNAL_MATCH_FUNC, 0, 0,
1142 NULL, gtk_image_menu_item_setting_changed, NULL);
1144 if (show_image_connection)
1147 g_signal_connect (settings, "notify::gtk-menu-images",
1148 G_CALLBACK (gtk_image_menu_item_setting_changed), NULL);
1150 show_image_change_notify (GTK_IMAGE_MENU_ITEM (widget));