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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtkimagemenuitem.h"
31 #include "gtkaccellabel.h"
33 #include "gtkiconfactory.h"
35 #include "gtkmenubar.h"
36 #include "gtkcontainer.h"
37 #include "gtkwindow.h"
38 #include "gtkactivatable.h"
41 #include "gtkprivate.h"
45 struct _GtkImageMenuItemPrivate
51 guint always_show_image : 1;
59 PROP_ALWAYS_SHOW_IMAGE
62 static GtkActivatableIface *parent_activatable_iface;
64 static void gtk_image_menu_item_destroy (GtkWidget *widget);
65 static void gtk_image_menu_item_get_preferred_width (GtkWidget *widget,
68 static void gtk_image_menu_item_get_preferred_height (GtkWidget *widget,
71 static void gtk_image_menu_item_get_preferred_height_for_width (GtkWidget *widget,
75 static void gtk_image_menu_item_size_allocate (GtkWidget *widget,
76 GtkAllocation *allocation);
77 static void gtk_image_menu_item_map (GtkWidget *widget);
78 static void gtk_image_menu_item_remove (GtkContainer *container,
80 static void gtk_image_menu_item_toggle_size_request (GtkMenuItem *menu_item,
82 static void gtk_image_menu_item_set_label (GtkMenuItem *menu_item,
84 static G_CONST_RETURN gchar *gtk_image_menu_item_get_label (GtkMenuItem *menu_item);
86 static void gtk_image_menu_item_forall (GtkContainer *container,
87 gboolean include_internals,
89 gpointer callback_data);
91 static void gtk_image_menu_item_finalize (GObject *object);
92 static void gtk_image_menu_item_set_property (GObject *object,
96 static void gtk_image_menu_item_get_property (GObject *object,
100 static void gtk_image_menu_item_screen_changed (GtkWidget *widget,
101 GdkScreen *previous_screen);
103 static void gtk_image_menu_item_recalculate (GtkImageMenuItem *image_menu_item);
105 static void gtk_image_menu_item_activatable_interface_init (GtkActivatableIface *iface);
106 static void gtk_image_menu_item_update (GtkActivatable *activatable,
108 const gchar *property_name);
109 static void gtk_image_menu_item_sync_action_properties (GtkActivatable *activatable,
113 G_DEFINE_TYPE_WITH_CODE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM,
114 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
115 gtk_image_menu_item_activatable_interface_init))
119 gtk_image_menu_item_class_init (GtkImageMenuItemClass *klass)
121 GObjectClass *gobject_class = (GObjectClass*) klass;
122 GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
123 GtkMenuItemClass *menu_item_class = (GtkMenuItemClass*) klass;
124 GtkContainerClass *container_class = (GtkContainerClass*) klass;
126 widget_class->destroy = gtk_image_menu_item_destroy;
127 widget_class->screen_changed = gtk_image_menu_item_screen_changed;
128 widget_class->get_preferred_width = gtk_image_menu_item_get_preferred_width;
129 widget_class->get_preferred_height = gtk_image_menu_item_get_preferred_height;
130 widget_class->get_preferred_height_for_width = gtk_image_menu_item_get_preferred_height_for_width;
131 widget_class->size_allocate = gtk_image_menu_item_size_allocate;
132 widget_class->map = gtk_image_menu_item_map;
134 container_class->forall = gtk_image_menu_item_forall;
135 container_class->remove = gtk_image_menu_item_remove;
137 menu_item_class->toggle_size_request = gtk_image_menu_item_toggle_size_request;
138 menu_item_class->set_label = gtk_image_menu_item_set_label;
139 menu_item_class->get_label = gtk_image_menu_item_get_label;
141 gobject_class->finalize = gtk_image_menu_item_finalize;
142 gobject_class->set_property = gtk_image_menu_item_set_property;
143 gobject_class->get_property = gtk_image_menu_item_get_property;
145 g_object_class_install_property (gobject_class,
147 g_param_spec_object ("image",
149 P_("Child widget to appear next to the menu text"),
151 GTK_PARAM_READWRITE));
153 * GtkImageMenuItem:use-stock:
155 * If %TRUE, the label set in the menuitem is used as a
156 * stock id to select the stock item for the item.
160 g_object_class_install_property (gobject_class,
162 g_param_spec_boolean ("use-stock",
164 P_("Whether to use the label text to create a stock menu item"),
166 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
169 * GtkImageMenuItem:always-show-image:
171 * If %TRUE, the menu item will ignore the #GtkSettings:gtk-menu-images
172 * setting and always show the image, if available.
174 * Use this property if the menuitem would be useless or hard to use
179 g_object_class_install_property (gobject_class,
180 PROP_ALWAYS_SHOW_IMAGE,
181 g_param_spec_boolean ("always-show-image",
182 P_("Always show image"),
183 P_("Whether the image will always be shown"),
185 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
188 * GtkImageMenuItem:accel-group:
190 * The Accel Group to use for stock accelerator keys
194 g_object_class_install_property (gobject_class,
196 g_param_spec_object ("accel-group",
198 P_("The Accel Group to use for stock accelerator keys"),
199 GTK_TYPE_ACCEL_GROUP,
200 GTK_PARAM_WRITABLE));
202 g_type_class_add_private (klass, sizeof (GtkImageMenuItemPrivate));
206 gtk_image_menu_item_init (GtkImageMenuItem *image_menu_item)
208 GtkImageMenuItemPrivate *priv;
210 image_menu_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (image_menu_item,
211 GTK_TYPE_IMAGE_MENU_ITEM,
212 GtkImageMenuItemPrivate);
213 priv = image_menu_item->priv;
216 priv->use_stock = FALSE;
221 gtk_image_menu_item_finalize (GObject *object)
223 GtkImageMenuItemPrivate *priv = GTK_IMAGE_MENU_ITEM (object)->priv;
225 g_free (priv->label);
228 G_OBJECT_CLASS (gtk_image_menu_item_parent_class)->finalize (object);
232 gtk_image_menu_item_set_property (GObject *object,
237 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (object);
242 gtk_image_menu_item_set_image (image_menu_item, (GtkWidget *) g_value_get_object (value));
245 gtk_image_menu_item_set_use_stock (image_menu_item, g_value_get_boolean (value));
247 case PROP_ALWAYS_SHOW_IMAGE:
248 gtk_image_menu_item_set_always_show_image (image_menu_item, g_value_get_boolean (value));
250 case PROP_ACCEL_GROUP:
251 gtk_image_menu_item_set_accel_group (image_menu_item, g_value_get_object (value));
254 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
260 gtk_image_menu_item_get_property (GObject *object,
265 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (object);
270 g_value_set_object (value, gtk_image_menu_item_get_image (image_menu_item));
273 g_value_set_boolean (value, gtk_image_menu_item_get_use_stock (image_menu_item));
275 case PROP_ALWAYS_SHOW_IMAGE:
276 g_value_set_boolean (value, gtk_image_menu_item_get_always_show_image (image_menu_item));
279 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
285 show_image (GtkImageMenuItem *image_menu_item)
287 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
288 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (image_menu_item));
291 if (priv->always_show_image)
294 g_object_get (settings, "gtk-menu-images", &show, NULL);
300 gtk_image_menu_item_map (GtkWidget *widget)
302 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
303 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
305 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->map (widget);
308 g_object_set (priv->image,
309 "visible", show_image (image_menu_item),
314 gtk_image_menu_item_destroy (GtkWidget *widget)
316 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
317 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
320 gtk_container_remove (GTK_CONTAINER (image_menu_item),
323 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->destroy (widget);
327 gtk_image_menu_item_toggle_size_request (GtkMenuItem *menu_item,
330 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item);
331 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
332 GtkPackDirection pack_dir;
334 GtkWidget *widget = GTK_WIDGET (menu_item);
336 parent = gtk_widget_get_parent (widget);
338 if (GTK_IS_MENU_BAR (parent))
339 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
341 pack_dir = GTK_PACK_DIRECTION_LTR;
345 if (priv->image && gtk_widget_get_visible (priv->image))
347 GtkRequisition image_requisition;
348 guint toggle_spacing;
350 gtk_widget_get_preferred_size (priv->image, &image_requisition, NULL);
352 gtk_widget_style_get (GTK_WIDGET (menu_item),
353 "toggle-spacing", &toggle_spacing,
356 if (pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL)
358 if (image_requisition.width > 0)
359 *requisition = image_requisition.width + toggle_spacing;
363 if (image_requisition.height > 0)
364 *requisition = image_requisition.height + toggle_spacing;
370 gtk_image_menu_item_recalculate (GtkImageMenuItem *image_menu_item)
372 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
373 GtkStockItem stock_item;
375 const gchar *resolved_label = priv->label;
377 if (priv->use_stock && priv->label)
382 image = gtk_image_new_from_stock (priv->label, GTK_ICON_SIZE_MENU);
383 gtk_image_menu_item_set_image (image_menu_item, image);
386 if (gtk_stock_lookup (priv->label, &stock_item))
387 resolved_label = stock_item.label;
389 gtk_menu_item_set_use_underline (GTK_MENU_ITEM (image_menu_item), TRUE);
393 (gtk_image_menu_item_parent_class)->set_label (GTK_MENU_ITEM (image_menu_item), resolved_label);
398 gtk_image_menu_item_set_label (GtkMenuItem *menu_item,
401 GtkImageMenuItemPrivate *priv = GTK_IMAGE_MENU_ITEM (menu_item)->priv;
403 if (priv->label != label)
405 g_free (priv->label);
406 priv->label = g_strdup (label);
408 gtk_image_menu_item_recalculate (GTK_IMAGE_MENU_ITEM (menu_item));
410 g_object_notify (G_OBJECT (menu_item), "label");
415 static G_CONST_RETURN gchar *
416 gtk_image_menu_item_get_label (GtkMenuItem *menu_item)
418 GtkImageMenuItemPrivate *priv = GTK_IMAGE_MENU_ITEM (menu_item)->priv;
424 gtk_image_menu_item_get_preferred_width (GtkWidget *widget,
428 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
429 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
430 gint child_width = 0;
431 GtkPackDirection pack_dir;
434 parent = gtk_widget_get_parent (widget);
436 if (GTK_IS_MENU_BAR (parent))
437 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
439 pack_dir = GTK_PACK_DIRECTION_LTR;
441 if (priv->image && gtk_widget_get_visible (priv->image))
443 GtkRequisition child_requisition;
445 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
447 child_width = child_requisition.width;
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 *minimum = MAX (*minimum, child_width);
455 *natural = MAX (*natural, child_width);
460 gtk_image_menu_item_get_preferred_height (GtkWidget *widget,
464 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
465 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
466 gint child_height = 0;
467 GtkPackDirection pack_dir;
470 parent = gtk_widget_get_parent (widget);
472 if (GTK_IS_MENU_BAR (parent))
473 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
475 pack_dir = GTK_PACK_DIRECTION_LTR;
477 if (priv->image && gtk_widget_get_visible (priv->image))
479 GtkRequisition child_requisition;
481 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
483 child_height = child_requisition.height;
486 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->get_preferred_height (widget, minimum, natural);
488 if (pack_dir == GTK_PACK_DIRECTION_RTL || pack_dir == GTK_PACK_DIRECTION_LTR)
490 *minimum = MAX (*minimum, child_height);
491 *natural = MAX (*natural, child_height);
496 gtk_image_menu_item_get_preferred_height_for_width (GtkWidget *widget,
501 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
502 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
503 gint child_height = 0;
504 GtkPackDirection pack_dir;
507 parent = gtk_widget_get_parent (widget);
509 if (GTK_IS_MENU_BAR (parent))
510 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
512 pack_dir = GTK_PACK_DIRECTION_LTR;
514 if (priv->image && gtk_widget_get_visible (priv->image))
516 GtkRequisition child_requisition;
518 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
520 child_height = child_requisition.height;
524 (gtk_image_menu_item_parent_class)->get_preferred_height_for_width (widget, width, minimum, natural);
526 if (pack_dir == GTK_PACK_DIRECTION_RTL || pack_dir == GTK_PACK_DIRECTION_LTR)
528 *minimum = MAX (*minimum, child_height);
529 *natural = MAX (*natural, child_height);
535 gtk_image_menu_item_size_allocate (GtkWidget *widget,
536 GtkAllocation *allocation)
538 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (widget);
539 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
540 GtkAllocation widget_allocation;
541 GtkPackDirection pack_dir;
544 parent = gtk_widget_get_parent (widget);
546 if (GTK_IS_MENU_BAR (parent))
547 pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
549 pack_dir = GTK_PACK_DIRECTION_LTR;
551 GTK_WIDGET_CLASS (gtk_image_menu_item_parent_class)->size_allocate (widget, allocation);
553 if (priv->image && gtk_widget_get_visible (priv->image))
556 GtkRequisition child_requisition;
557 GtkAllocation child_allocation;
558 guint horizontal_padding, toggle_spacing;
560 gtk_widget_style_get (widget,
561 "horizontal-padding", &horizontal_padding,
562 "toggle-spacing", &toggle_spacing,
565 /* Man this is lame hardcoding action, but I can't
566 * come up with a solution that's really better.
569 gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL);
571 gtk_widget_get_allocation (widget, &widget_allocation);
573 if (pack_dir == GTK_PACK_DIRECTION_LTR ||
574 pack_dir == GTK_PACK_DIRECTION_RTL)
576 offset = gtk_container_get_border_width (GTK_CONTAINER (image_menu_item)) +
577 gtk_widget_get_style (widget)->xthickness;
579 if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) ==
580 (pack_dir == GTK_PACK_DIRECTION_LTR))
581 x = offset + horizontal_padding +
582 (GTK_MENU_ITEM (image_menu_item)->toggle_size -
583 toggle_spacing - child_requisition.width) / 2;
585 x = widget_allocation.width - offset - horizontal_padding -
586 GTK_MENU_ITEM (image_menu_item)->toggle_size + toggle_spacing +
587 (GTK_MENU_ITEM (image_menu_item)->toggle_size -
588 toggle_spacing - child_requisition.width) / 2;
590 y = (widget_allocation.height - child_requisition.height) / 2;
594 offset = gtk_container_get_border_width (GTK_CONTAINER (image_menu_item)) +
595 gtk_widget_get_style (widget)->ythickness;
597 if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) ==
598 (pack_dir == GTK_PACK_DIRECTION_TTB))
599 y = offset + horizontal_padding +
600 (GTK_MENU_ITEM (image_menu_item)->toggle_size -
601 toggle_spacing - child_requisition.height) / 2;
603 y = widget_allocation.height - offset - horizontal_padding -
604 GTK_MENU_ITEM (image_menu_item)->toggle_size + toggle_spacing +
605 (GTK_MENU_ITEM (image_menu_item)->toggle_size -
606 toggle_spacing - child_requisition.height) / 2;
608 x = (widget_allocation.width - child_requisition.width) / 2;
611 child_allocation.width = child_requisition.width;
612 child_allocation.height = child_requisition.height;
613 child_allocation.x = widget_allocation.x + MAX (x, 0);
614 child_allocation.y = widget_allocation.y + MAX (y, 0);
616 gtk_widget_size_allocate (priv->image, &child_allocation);
621 gtk_image_menu_item_forall (GtkContainer *container,
622 gboolean include_internals,
623 GtkCallback callback,
624 gpointer callback_data)
626 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (container);
627 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
629 GTK_CONTAINER_CLASS (gtk_image_menu_item_parent_class)->forall (container,
634 if (include_internals && priv->image)
635 (* callback) (priv->image, callback_data);
640 gtk_image_menu_item_activatable_interface_init (GtkActivatableIface *iface)
642 parent_activatable_iface = g_type_interface_peek_parent (iface);
643 iface->update = gtk_image_menu_item_update;
644 iface->sync_action_properties = gtk_image_menu_item_sync_action_properties;
648 activatable_update_stock_id (GtkImageMenuItem *image_menu_item, GtkAction *action)
651 const gchar *stock_id = gtk_action_get_stock_id (action);
653 image = gtk_image_menu_item_get_image (image_menu_item);
655 if (GTK_IS_IMAGE (image) &&
656 stock_id && gtk_icon_factory_lookup_default (stock_id))
658 gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU);
666 activatable_update_gicon (GtkImageMenuItem *image_menu_item, GtkAction *action)
669 GIcon *icon = gtk_action_get_gicon (action);
670 const gchar *stock_id = gtk_action_get_stock_id (action);
672 image = gtk_image_menu_item_get_image (image_menu_item);
674 if (icon && GTK_IS_IMAGE (image) &&
675 !(stock_id && gtk_icon_factory_lookup_default (stock_id)))
677 gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU);
685 activatable_update_icon_name (GtkImageMenuItem *image_menu_item, GtkAction *action)
688 const gchar *icon_name = gtk_action_get_icon_name (action);
690 image = gtk_image_menu_item_get_image (image_menu_item);
692 if (GTK_IS_IMAGE (image) &&
693 (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
694 gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
696 gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
701 gtk_image_menu_item_update (GtkActivatable *activatable,
703 const gchar *property_name)
705 GtkImageMenuItem *image_menu_item;
706 gboolean use_appearance;
708 image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
710 parent_activatable_iface->update (activatable, action, property_name);
712 use_appearance = gtk_activatable_get_use_action_appearance (activatable);
716 if (strcmp (property_name, "stock-id") == 0)
717 activatable_update_stock_id (image_menu_item, action);
718 else if (strcmp (property_name, "gicon") == 0)
719 activatable_update_gicon (image_menu_item, action);
720 else if (strcmp (property_name, "icon-name") == 0)
721 activatable_update_icon_name (image_menu_item, action);
725 gtk_image_menu_item_sync_action_properties (GtkActivatable *activatable,
728 GtkImageMenuItem *image_menu_item;
730 gboolean use_appearance;
732 image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
734 parent_activatable_iface->sync_action_properties (activatable, action);
739 use_appearance = gtk_activatable_get_use_action_appearance (activatable);
743 image = gtk_image_menu_item_get_image (image_menu_item);
744 if (image && !GTK_IS_IMAGE (image))
746 gtk_image_menu_item_set_image (image_menu_item, NULL);
752 image = gtk_image_new ();
753 gtk_widget_show (image);
754 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable),
758 if (!activatable_update_stock_id (image_menu_item, action) &&
759 !activatable_update_gicon (image_menu_item, action))
760 activatable_update_icon_name (image_menu_item, action);
762 gtk_image_menu_item_set_always_show_image (image_menu_item,
763 gtk_action_get_always_show_image (action));
768 * gtk_image_menu_item_new:
769 * @returns: a new #GtkImageMenuItem.
771 * Creates a new #GtkImageMenuItem with an empty label.
774 gtk_image_menu_item_new (void)
776 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM, NULL);
780 * gtk_image_menu_item_new_with_label:
781 * @label: the text of the menu item.
782 * @returns: a new #GtkImageMenuItem.
784 * Creates a new #GtkImageMenuItem containing a label.
787 gtk_image_menu_item_new_with_label (const gchar *label)
789 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM,
796 * gtk_image_menu_item_new_with_mnemonic:
797 * @label: the text of the menu item, with an underscore in front of the
799 * @returns: a new #GtkImageMenuItem
801 * Creates a new #GtkImageMenuItem containing a label. The label
802 * will be created using gtk_label_new_with_mnemonic(), so underscores
803 * in @label indicate the mnemonic for the menu item.
806 gtk_image_menu_item_new_with_mnemonic (const gchar *label)
808 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM,
809 "use-underline", TRUE,
815 * gtk_image_menu_item_new_from_stock:
816 * @stock_id: the name of the stock item.
817 * @accel_group: (allow-none): the #GtkAccelGroup to add the menu items
818 * accelerator to, or %NULL.
819 * @returns: a new #GtkImageMenuItem.
821 * Creates a new #GtkImageMenuItem containing the image and text from a
822 * stock item. Some stock ids have preprocessor macros like #GTK_STOCK_OK
823 * and #GTK_STOCK_APPLY.
825 * If you want this menu item to have changeable accelerators, then pass in
826 * %NULL for accel_group. Next call gtk_menu_item_set_accel_path() with an
827 * appropriate path for the menu item, use gtk_stock_lookup() to look up the
828 * standard accelerator for the stock item, and if one is found, call
829 * gtk_accel_map_add_entry() to register it.
832 gtk_image_menu_item_new_from_stock (const gchar *stock_id,
833 GtkAccelGroup *accel_group)
835 return g_object_new (GTK_TYPE_IMAGE_MENU_ITEM,
838 "accel-group", accel_group,
843 * gtk_image_menu_item_set_use_stock:
844 * @image_menu_item: a #GtkImageMenuItem
845 * @use_stock: %TRUE if the menuitem should use a stock item
847 * If %TRUE, the label set in the menuitem is used as a
848 * stock id to select the stock item for the item.
853 gtk_image_menu_item_set_use_stock (GtkImageMenuItem *image_menu_item,
856 GtkImageMenuItemPrivate *priv;
858 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
860 priv = image_menu_item->priv;
862 if (priv->use_stock != use_stock)
864 priv->use_stock = use_stock;
866 gtk_image_menu_item_recalculate (image_menu_item);
868 g_object_notify (G_OBJECT (image_menu_item), "use-stock");
873 * gtk_image_menu_item_get_use_stock:
874 * @image_menu_item: a #GtkImageMenuItem
876 * Checks whether the label set in the menuitem is used as a
877 * stock id to select the stock item for the item.
879 * Returns: %TRUE if the label set in the menuitem is used as a
880 * stock id to select the stock item for the item
885 gtk_image_menu_item_get_use_stock (GtkImageMenuItem *image_menu_item)
887 g_return_val_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item), FALSE);
889 return image_menu_item->priv->use_stock;
893 * gtk_image_menu_item_set_always_show_image:
894 * @image_menu_item: a #GtkImageMenuItem
895 * @always_show: %TRUE if the menuitem should always show the image
897 * If %TRUE, the menu item will ignore the #GtkSettings:gtk-menu-images
898 * setting and always show the image, if available.
900 * Use this property if the menuitem would be useless or hard to use
906 gtk_image_menu_item_set_always_show_image (GtkImageMenuItem *image_menu_item,
907 gboolean always_show)
909 GtkImageMenuItemPrivate *priv;
911 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
913 priv = image_menu_item->priv;
915 if (priv->always_show_image != always_show)
917 priv->always_show_image = always_show;
921 if (show_image (image_menu_item))
922 gtk_widget_show (priv->image);
924 gtk_widget_hide (priv->image);
927 g_object_notify (G_OBJECT (image_menu_item), "always-show-image");
932 * gtk_image_menu_item_get_always_show_image:
933 * @image_menu_item: a #GtkImageMenuItem
935 * Returns whether the menu item will ignore the #GtkSettings:gtk-menu-images
936 * setting and always show the image, if available.
938 * Returns: %TRUE if the menu item will always show the image
943 gtk_image_menu_item_get_always_show_image (GtkImageMenuItem *image_menu_item)
945 g_return_val_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item), FALSE);
947 return image_menu_item->priv->always_show_image;
952 * gtk_image_menu_item_set_accel_group:
953 * @image_menu_item: a #GtkImageMenuItem
954 * @accel_group: the #GtkAccelGroup
956 * Specifies an @accel_group to add the menu items accelerator to
957 * (this only applies to stock items so a stock item must already
958 * be set, make sure to call gtk_image_menu_item_set_use_stock()
959 * and gtk_menu_item_set_label() with a valid stock item first).
961 * If you want this menu item to have changeable accelerators then
962 * you shouldnt need this (see gtk_image_menu_item_new_from_stock()).
967 gtk_image_menu_item_set_accel_group (GtkImageMenuItem *image_menu_item,
968 GtkAccelGroup *accel_group)
970 GtkImageMenuItemPrivate *priv;
971 GtkStockItem stock_item;
973 /* Silent return for the constructor */
977 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
978 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
980 priv = image_menu_item->priv;
982 if (priv->use_stock && priv->label && gtk_stock_lookup (priv->label, &stock_item))
983 if (stock_item.keyval)
985 gtk_widget_add_accelerator (GTK_WIDGET (image_menu_item),
992 g_object_notify (G_OBJECT (image_menu_item), "accel-group");
997 * gtk_image_menu_item_set_image:
998 * @image_menu_item: a #GtkImageMenuItem.
999 * @image: (allow-none): a widget to set as the image for the menu item.
1001 * Sets the image of @image_menu_item to the given widget.
1002 * Note that it depends on the show-menu-images setting whether
1003 * the image will be displayed or not.
1006 gtk_image_menu_item_set_image (GtkImageMenuItem *image_menu_item,
1009 GtkImageMenuItemPrivate *priv;
1011 g_return_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item));
1013 priv = image_menu_item->priv;
1015 if (image == priv->image)
1019 gtk_container_remove (GTK_CONTAINER (image_menu_item),
1022 priv->image = image;
1027 gtk_widget_set_parent (image, GTK_WIDGET (image_menu_item));
1028 g_object_set (image,
1029 "visible", show_image (image_menu_item),
1030 "no-show-all", TRUE,
1033 g_object_notify (G_OBJECT (image_menu_item), "image");
1037 * gtk_image_menu_item_get_image:
1038 * @image_menu_item: a #GtkImageMenuItem
1040 * Gets the widget that is currently set as the image of @image_menu_item.
1041 * See gtk_image_menu_item_set_image().
1043 * Return value: (transfer none): the widget set as image of @image_menu_item
1046 gtk_image_menu_item_get_image (GtkImageMenuItem *image_menu_item)
1048 g_return_val_if_fail (GTK_IS_IMAGE_MENU_ITEM (image_menu_item), NULL);
1050 return image_menu_item->priv->image;
1054 gtk_image_menu_item_remove (GtkContainer *container,
1057 GtkImageMenuItem *image_menu_item = GTK_IMAGE_MENU_ITEM (container);
1058 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
1060 if (child == priv->image)
1062 gboolean widget_was_visible;
1064 widget_was_visible = gtk_widget_get_visible (child);
1066 gtk_widget_unparent (child);
1069 if (widget_was_visible &&
1070 gtk_widget_get_visible (GTK_WIDGET (container)))
1071 gtk_widget_queue_resize (GTK_WIDGET (container));
1073 g_object_notify (G_OBJECT (image_menu_item), "image");
1077 GTK_CONTAINER_CLASS (gtk_image_menu_item_parent_class)->remove (container, child);
1082 show_image_change_notify (GtkImageMenuItem *image_menu_item)
1084 GtkImageMenuItemPrivate *priv = image_menu_item->priv;
1088 if (show_image (image_menu_item))
1089 gtk_widget_show (priv->image);
1091 gtk_widget_hide (priv->image);
1096 traverse_container (GtkWidget *widget,
1099 if (GTK_IS_IMAGE_MENU_ITEM (widget))
1100 show_image_change_notify (GTK_IMAGE_MENU_ITEM (widget));
1101 else if (GTK_IS_CONTAINER (widget))
1102 gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL);
1106 gtk_image_menu_item_setting_changed (GtkSettings *settings)
1110 list = gtk_window_list_toplevels ();
1112 for (l = list; l; l = l->next)
1113 gtk_container_forall (GTK_CONTAINER (l->data),
1114 traverse_container, NULL);
1120 gtk_image_menu_item_screen_changed (GtkWidget *widget,
1121 GdkScreen *previous_screen)
1123 GtkSettings *settings;
1124 gulong show_image_connection;
1126 if (!gtk_widget_has_screen (widget))
1129 settings = gtk_widget_get_settings (widget);
1131 show_image_connection =
1132 g_signal_handler_find (settings, G_SIGNAL_MATCH_FUNC, 0, 0,
1133 NULL, gtk_image_menu_item_setting_changed, NULL);
1135 if (show_image_connection)
1138 g_signal_connect (settings, "notify::gtk-menu-images",
1139 G_CALLBACK (gtk_image_menu_item_setting_changed), NULL);
1141 show_image_change_notify (GTK_IMAGE_MENU_ITEM (widget));