1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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/.
30 #include "gtkaccellabel.h"
32 #include "gtkmarshalers.h"
34 #include "gtkmenubar.h"
35 #include "gtkmenuprivate.h"
36 #include "gtkseparatormenuitem.h"
37 #include "gtkprivate.h"
38 #include "gtkbuildable.h"
39 #include "gtkactivatable.h"
45 gboolean use_action_appearance;
66 /* activatable properties */
67 PROP_ACTIVATABLE_RELATED_ACTION,
68 PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
72 static void gtk_menu_item_dispose (GObject *object);
73 static void gtk_menu_item_set_property (GObject *object,
77 static void gtk_menu_item_get_property (GObject *object,
81 static void gtk_menu_item_destroy (GtkWidget *widget);
82 static void gtk_menu_item_size_allocate (GtkWidget *widget,
83 GtkAllocation *allocation);
84 static void gtk_menu_item_realize (GtkWidget *widget);
85 static void gtk_menu_item_unrealize (GtkWidget *widget);
86 static void gtk_menu_item_map (GtkWidget *widget);
87 static void gtk_menu_item_unmap (GtkWidget *widget);
88 static gboolean gtk_menu_item_enter (GtkWidget *widget,
89 GdkEventCrossing *event);
90 static gboolean gtk_menu_item_leave (GtkWidget *widget,
91 GdkEventCrossing *event);
92 static gboolean gtk_menu_item_draw (GtkWidget *widget,
94 static void gtk_menu_item_parent_set (GtkWidget *widget,
95 GtkWidget *previous_parent);
98 static void gtk_real_menu_item_select (GtkMenuItem *item);
99 static void gtk_real_menu_item_deselect (GtkMenuItem *item);
100 static void gtk_real_menu_item_activate (GtkMenuItem *item);
101 static void gtk_real_menu_item_activate_item (GtkMenuItem *item);
102 static void gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
104 static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
106 static gboolean gtk_menu_item_mnemonic_activate (GtkWidget *widget,
107 gboolean group_cycling);
109 static void gtk_menu_item_ensure_label (GtkMenuItem *menu_item);
110 static gint gtk_menu_item_popup_timeout (gpointer data);
111 static void gtk_menu_item_position_menu (GtkMenu *menu,
116 static void gtk_menu_item_show_all (GtkWidget *widget);
117 static void gtk_menu_item_hide_all (GtkWidget *widget);
118 static void gtk_menu_item_forall (GtkContainer *container,
119 gboolean include_internals,
120 GtkCallback callback,
121 gpointer callback_data);
122 static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
125 static void gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
127 static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
129 static void gtk_menu_item_get_preferred_width (GtkWidget *widget,
132 static void gtk_menu_item_get_preferred_height (GtkWidget *widget,
135 static void gtk_menu_item_get_preferred_height_for_width (GtkWidget *widget,
140 static void gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface);
141 static void gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
145 static void gtk_menu_item_buildable_custom_finished(GtkBuildable *buildable,
148 const gchar *tagname,
151 static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface);
152 static void gtk_menu_item_update (GtkActivatable *activatable,
154 const gchar *property_name);
155 static void gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
157 static void gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
159 static void gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
160 gboolean use_appearance);
163 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
165 static GtkBuildableIface *parent_buildable_iface;
167 G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_BIN,
168 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
169 gtk_menu_item_buildable_interface_init)
170 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
171 gtk_menu_item_activatable_interface_init))
173 #define GET_PRIVATE(object) \
174 (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
177 gtk_menu_item_class_init (GtkMenuItemClass *klass)
179 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
180 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
181 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
183 gobject_class->dispose = gtk_menu_item_dispose;
184 gobject_class->set_property = gtk_menu_item_set_property;
185 gobject_class->get_property = gtk_menu_item_get_property;
187 widget_class->destroy = gtk_menu_item_destroy;
188 widget_class->size_allocate = gtk_menu_item_size_allocate;
189 widget_class->draw = gtk_menu_item_draw;
190 widget_class->realize = gtk_menu_item_realize;
191 widget_class->unrealize = gtk_menu_item_unrealize;
192 widget_class->map = gtk_menu_item_map;
193 widget_class->unmap = gtk_menu_item_unmap;
194 widget_class->enter_notify_event = gtk_menu_item_enter;
195 widget_class->leave_notify_event = gtk_menu_item_leave;
196 widget_class->show_all = gtk_menu_item_show_all;
197 widget_class->hide_all = gtk_menu_item_hide_all;
198 widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
199 widget_class->parent_set = gtk_menu_item_parent_set;
200 widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
201 widget_class->get_preferred_width = gtk_menu_item_get_preferred_width;
202 widget_class->get_preferred_height = gtk_menu_item_get_preferred_height;
203 widget_class->get_preferred_height_for_width = gtk_menu_item_get_preferred_height_for_width;
205 container_class->forall = gtk_menu_item_forall;
207 klass->activate = gtk_real_menu_item_activate;
208 klass->activate_item = gtk_real_menu_item_activate_item;
209 klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
210 klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
211 klass->set_label = gtk_real_menu_item_set_label;
212 klass->get_label = gtk_real_menu_item_get_label;
213 klass->select = gtk_real_menu_item_select;
214 klass->deselect = gtk_real_menu_item_deselect;
216 klass->hide_on_activate = TRUE;
218 menu_item_signals[ACTIVATE] =
219 g_signal_new (I_("activate"),
220 G_OBJECT_CLASS_TYPE (gobject_class),
221 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
222 G_STRUCT_OFFSET (GtkMenuItemClass, activate),
224 _gtk_marshal_VOID__VOID,
226 widget_class->activate_signal = menu_item_signals[ACTIVATE];
228 menu_item_signals[ACTIVATE_ITEM] =
229 g_signal_new (I_("activate-item"),
230 G_OBJECT_CLASS_TYPE (gobject_class),
232 G_STRUCT_OFFSET (GtkMenuItemClass, activate_item),
234 _gtk_marshal_VOID__VOID,
237 menu_item_signals[TOGGLE_SIZE_REQUEST] =
238 g_signal_new (I_("toggle-size-request"),
239 G_OBJECT_CLASS_TYPE (gobject_class),
241 G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_request),
243 _gtk_marshal_VOID__POINTER,
247 menu_item_signals[TOGGLE_SIZE_ALLOCATE] =
248 g_signal_new (I_("toggle-size-allocate"),
249 G_OBJECT_CLASS_TYPE (gobject_class),
251 G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_allocate),
253 _gtk_marshal_VOID__INT,
257 menu_item_signals[SELECT] =
258 g_signal_new (I_("select"),
259 G_OBJECT_CLASS_TYPE (gobject_class),
261 G_STRUCT_OFFSET (GtkMenuItemClass, select),
263 _gtk_marshal_VOID__VOID,
266 menu_item_signals[DESELECT] =
267 g_signal_new (I_("deselect"),
268 G_OBJECT_CLASS_TYPE (gobject_class),
270 G_STRUCT_OFFSET (GtkMenuItemClass, deselect),
272 _gtk_marshal_VOID__VOID,
276 * GtkMenuItem:right-justified:
278 * Sets whether the menu item appears justified at the right side of a menu bar.
282 g_object_class_install_property (gobject_class,
283 PROP_RIGHT_JUSTIFIED,
284 g_param_spec_boolean ("right-justified",
285 P_("Right Justified"),
286 P_("Sets whether the menu item appears justified at the right side of a menu bar"),
288 GTK_PARAM_READWRITE));
291 * GtkMenuItem:submenu:
293 * The submenu attached to the menu item, or NULL if it has none.
297 g_object_class_install_property (gobject_class,
299 g_param_spec_object ("submenu",
301 P_("The submenu attached to the menu item, or NULL if it has none"),
303 GTK_PARAM_READWRITE));
307 * GtkMenuItem:accel-path:
309 * Sets the accelerator path of the menu item, through which runtime
310 * changes of the menu item's accelerator caused by the user can be
311 * identified and saved to persistant storage.
315 g_object_class_install_property (gobject_class,
317 g_param_spec_string ("accel-path",
319 P_("Sets the accelerator path of the menu item"),
321 GTK_PARAM_READWRITE));
326 * The text for the child label.
330 g_object_class_install_property (gobject_class,
332 g_param_spec_string ("label",
334 P_("The text for the child label"),
336 GTK_PARAM_READWRITE));
339 * GtkMenuItem:use-underline:
341 * %TRUE if underlines in the text indicate mnemonics
345 g_object_class_install_property (gobject_class,
347 g_param_spec_boolean ("use-underline",
349 P_("If set, an underline in the text indicates "
350 "the next character should be used for the "
351 "mnemonic accelerator key"),
353 GTK_PARAM_READWRITE));
355 g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
356 g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
358 gtk_widget_class_install_style_property_parser (widget_class,
359 g_param_spec_enum ("selected-shadow-type",
360 "Selected Shadow Type",
361 "Shadow type when item is selected",
362 GTK_TYPE_SHADOW_TYPE,
365 gtk_rc_property_parse_enum);
367 gtk_widget_class_install_style_property (widget_class,
368 g_param_spec_int ("horizontal-padding",
369 "Horizontal Padding",
370 "Padding to left and right of the menu item",
374 GTK_PARAM_READABLE));
376 gtk_widget_class_install_style_property (widget_class,
377 g_param_spec_int ("toggle-spacing",
379 "Space between icon and label",
383 GTK_PARAM_READABLE));
385 gtk_widget_class_install_style_property (widget_class,
386 g_param_spec_int ("arrow-spacing",
388 "Space between label and arrow",
392 GTK_PARAM_READABLE));
394 gtk_widget_class_install_style_property (widget_class,
395 g_param_spec_float ("arrow-scaling",
397 P_("Amount of space used up by arrow, relative to the menu item's font size"),
399 GTK_PARAM_READABLE));
402 * GtkMenuItem:width-chars:
404 * The minimum desired width of the menu item in characters.
408 gtk_widget_class_install_style_property (widget_class,
409 g_param_spec_int ("width-chars",
410 P_("Width in Characters"),
411 P_("The minimum desired width of the menu item in characters"),
413 GTK_PARAM_READABLE));
415 g_type_class_add_private (klass, sizeof (GtkMenuItemPrivate));
419 gtk_menu_item_init (GtkMenuItem *menu_item)
421 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
423 gtk_widget_set_has_window (GTK_WIDGET (menu_item), FALSE);
426 priv->use_action_appearance = TRUE;
428 menu_item->submenu = NULL;
429 menu_item->toggle_size = 0;
430 menu_item->accelerator_width = 0;
431 menu_item->show_submenu_indicator = FALSE;
432 if (gtk_widget_get_direction (GTK_WIDGET (menu_item)) == GTK_TEXT_DIR_RTL)
433 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
435 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
436 menu_item->submenu_placement = GTK_TOP_BOTTOM;
437 menu_item->right_justify = FALSE;
439 menu_item->timer = 0;
443 gtk_menu_item_new (void)
445 return g_object_new (GTK_TYPE_MENU_ITEM, NULL);
449 gtk_menu_item_new_with_label (const gchar *label)
451 return g_object_new (GTK_TYPE_MENU_ITEM,
458 * gtk_menu_item_new_with_mnemonic:
459 * @label: The text of the button, with an underscore in front of the
461 * @returns: a new #GtkMenuItem
463 * Creates a new #GtkMenuItem containing a label. The label
464 * will be created using gtk_label_new_with_mnemonic(), so underscores
465 * in @label indicate the mnemonic for the menu item.
468 gtk_menu_item_new_with_mnemonic (const gchar *label)
470 return g_object_new (GTK_TYPE_MENU_ITEM,
471 "use-underline", TRUE,
477 gtk_menu_item_dispose (GObject *object)
479 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
480 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
484 gtk_action_disconnect_accelerator (priv->action);
485 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
489 G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
493 gtk_menu_item_set_property (GObject *object,
498 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
502 case PROP_RIGHT_JUSTIFIED:
503 gtk_menu_item_set_right_justified (menu_item, g_value_get_boolean (value));
506 gtk_menu_item_set_submenu (menu_item, g_value_get_object (value));
508 case PROP_ACCEL_PATH:
509 gtk_menu_item_set_accel_path (menu_item, g_value_get_string (value));
512 gtk_menu_item_set_label (menu_item, g_value_get_string (value));
514 case PROP_USE_UNDERLINE:
515 gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
517 case PROP_ACTIVATABLE_RELATED_ACTION:
518 gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
520 case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
521 gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
524 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
530 gtk_menu_item_get_property (GObject *object,
535 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
536 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
540 case PROP_RIGHT_JUSTIFIED:
541 g_value_set_boolean (value, gtk_menu_item_get_right_justified (menu_item));
544 g_value_set_object (value, gtk_menu_item_get_submenu (menu_item));
546 case PROP_ACCEL_PATH:
547 g_value_set_string (value, gtk_menu_item_get_accel_path (menu_item));
550 g_value_set_string (value, gtk_menu_item_get_label (menu_item));
552 case PROP_USE_UNDERLINE:
553 g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
555 case PROP_ACTIVATABLE_RELATED_ACTION:
556 g_value_set_object (value, priv->action);
558 case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
559 g_value_set_boolean (value, priv->use_action_appearance);
562 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
568 gtk_menu_item_destroy (GtkWidget *widget)
570 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
572 if (menu_item->submenu)
573 gtk_widget_destroy (menu_item->submenu);
575 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->destroy (widget);
579 gtk_menu_item_detacher (GtkWidget *widget,
582 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
584 g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
586 menu_item->submenu = NULL;
590 get_arrow_size (GtkWidget *widget,
594 PangoContext *context;
595 PangoFontMetrics *metrics;
596 gfloat arrow_scaling;
600 gtk_widget_style_get (widget,
601 "arrow-scaling", &arrow_scaling,
604 context = gtk_widget_get_pango_context (child);
605 metrics = pango_context_get_metrics (context,
606 gtk_widget_get_style (child)->font_desc,
607 pango_context_get_language (context));
609 *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
610 pango_font_metrics_get_descent (metrics)));
612 pango_font_metrics_unref (metrics);
614 *size = *size * arrow_scaling;
619 gtk_menu_item_accel_width_foreach (GtkWidget *widget,
624 if (GTK_IS_ACCEL_LABEL (widget))
628 w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
629 *width = MAX (*width, w);
631 else if (GTK_IS_CONTAINER (widget))
632 gtk_container_foreach (GTK_CONTAINER (widget),
633 gtk_menu_item_accel_width_foreach,
638 get_minimum_width (GtkWidget *widget)
640 PangoContext *context;
641 PangoFontMetrics *metrics;
645 context = gtk_widget_get_pango_context (widget);
646 metrics = pango_context_get_metrics (context,
647 gtk_widget_get_style (widget)->font_desc,
648 pango_context_get_language (context));
650 width = pango_font_metrics_get_approximate_char_width (metrics);
652 pango_font_metrics_unref (metrics);
654 gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
656 return PANGO_PIXELS (width_chars * width);
660 gtk_menu_item_get_preferred_width (GtkWidget *request,
664 GtkMenuItem *menu_item;
666 GtkWidget *child, *widget = GTK_WIDGET (request);
669 guint horizontal_padding;
671 GtkPackDirection pack_dir;
672 GtkPackDirection child_pack_dir;
673 gint min_width, nat_width;
675 min_width = nat_width = 0;
677 gtk_widget_style_get (widget,
678 "horizontal-padding", &horizontal_padding,
681 bin = GTK_BIN (widget);
682 menu_item = GTK_MENU_ITEM (widget);
683 parent = gtk_widget_get_parent (widget);
685 if (GTK_IS_MENU_BAR (parent))
687 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
688 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
692 pack_dir = GTK_PACK_DIRECTION_LTR;
693 child_pack_dir = GTK_PACK_DIRECTION_LTR;
696 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
698 min_width = (border_width + gtk_widget_get_style (widget)->xthickness) * 2;
700 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
701 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
702 min_width += 2 * horizontal_padding;
704 nat_width = min_width;
706 child = gtk_bin_get_child (bin);
708 if (child != NULL && gtk_widget_get_visible (child))
710 gint child_min, child_nat;
712 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
714 if (menu_item->submenu && menu_item->show_submenu_indicator)
719 gtk_widget_style_get (widget,
720 "arrow-spacing", &arrow_spacing,
723 get_arrow_size (widget, child, &arrow_size);
725 min_width += arrow_size;
726 min_width += arrow_spacing;
728 min_width = MAX (min_width, get_minimum_width (widget));
730 nat_width = min_width;
734 min_width += child_min;
735 nat_width += child_nat;
741 gtk_container_foreach (GTK_CONTAINER (menu_item),
742 gtk_menu_item_accel_width_foreach,
744 menu_item->accelerator_width = accel_width;
747 *minimum_size = min_width;
750 *natural_size = nat_width;
754 gtk_menu_item_get_preferred_height (GtkWidget *request,
758 GtkMenuItem *menu_item;
761 GtkWidget *child, *widget = GTK_WIDGET (request);
764 guint horizontal_padding;
766 GtkPackDirection pack_dir;
767 GtkPackDirection child_pack_dir;
768 gint min_height, nat_height;
770 min_height = nat_height = 0;
772 style = gtk_widget_get_style (widget);
774 gtk_widget_style_get (widget,
775 "horizontal-padding", &horizontal_padding,
778 bin = GTK_BIN (widget);
779 menu_item = GTK_MENU_ITEM (widget);
780 parent = gtk_widget_get_parent (widget);
782 if (GTK_IS_MENU_BAR (parent))
784 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
785 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
789 pack_dir = GTK_PACK_DIRECTION_LTR;
790 child_pack_dir = GTK_PACK_DIRECTION_LTR;
793 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
794 min_height = (border_width + style->ythickness) * 2;
796 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
797 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
798 min_height += 2 * horizontal_padding;
800 nat_height = min_height;
802 child = gtk_bin_get_child (bin);
804 if (child != NULL && gtk_widget_get_visible (child))
806 gint child_min, child_nat;
808 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
810 min_height += child_min;
811 nat_height += child_nat;
813 if (menu_item->submenu && menu_item->show_submenu_indicator)
817 get_arrow_size (widget, child, &arrow_size);
819 min_height = MAX (min_height, arrow_size);
820 nat_height = MAX (nat_height, arrow_size);
823 else /* separator item */
825 gboolean wide_separators;
826 gint separator_height;
828 gtk_widget_style_get (widget,
829 "wide-separators", &wide_separators,
830 "separator-height", &separator_height,
834 min_height += separator_height + style->ythickness;
836 min_height += style->ythickness * 2;
838 nat_height = min_height;
842 gtk_container_foreach (GTK_CONTAINER (menu_item),
843 gtk_menu_item_accel_width_foreach,
845 menu_item->accelerator_width = accel_width;
848 *minimum_size = min_height;
851 *natural_size = nat_height;
855 gtk_menu_item_get_preferred_height_for_width (GtkWidget *request,
860 GtkMenuItem *menu_item;
863 GtkWidget *child, *widget = GTK_WIDGET (request);
865 guint horizontal_padding;
867 GtkPackDirection pack_dir;
868 GtkPackDirection child_pack_dir;
869 gint min_height, nat_height;
872 min_height = nat_height = 0;
874 style = gtk_widget_get_style (widget);
876 gtk_widget_style_get (widget,
877 "horizontal-padding", &horizontal_padding,
880 bin = GTK_BIN (widget);
881 menu_item = GTK_MENU_ITEM (widget);
882 parent = gtk_widget_get_parent (widget);
884 if (GTK_IS_MENU_BAR (parent))
886 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
887 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
891 pack_dir = GTK_PACK_DIRECTION_LTR;
892 child_pack_dir = GTK_PACK_DIRECTION_LTR;
895 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
896 min_height = (border_width + style->ythickness) * 2;
898 avail_size = for_size;
899 avail_size -= (border_width + style->xthickness) * 2;
901 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
902 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
903 min_height += 2 * horizontal_padding;
905 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
906 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
907 avail_size -= 2 * horizontal_padding;
909 nat_height = min_height;
911 child = gtk_bin_get_child (bin);
913 if (child != NULL && gtk_widget_get_visible (child))
915 gint child_min, child_nat;
918 if (menu_item->submenu && menu_item->show_submenu_indicator)
923 gtk_widget_style_get (widget,
924 "arrow-spacing", &arrow_spacing,
927 get_arrow_size (widget, child, &arrow_size);
929 avail_size -= arrow_size;
930 avail_size -= arrow_spacing;
933 gtk_widget_get_preferred_height_for_width (child,
938 min_height += child_min;
939 nat_height += child_nat;
941 if (menu_item->submenu && menu_item->show_submenu_indicator)
943 min_height = MAX (min_height, arrow_size);
944 nat_height = MAX (nat_height, arrow_size);
947 else /* separator item */
949 gboolean wide_separators;
950 gint separator_height;
952 gtk_widget_style_get (widget,
953 "wide-separators", &wide_separators,
954 "separator-height", &separator_height,
958 min_height += separator_height + style->ythickness;
960 min_height += style->ythickness * 2;
962 nat_height = min_height;
966 *minimum_size = min_height;
969 *natural_size = nat_height;
973 gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
975 parent_buildable_iface = g_type_interface_peek_parent (iface);
976 iface->add_child = gtk_menu_item_buildable_add_child;
977 iface->custom_finished = gtk_menu_item_buildable_custom_finished;
981 gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
986 if (type && strcmp (type, "submenu") == 0)
987 gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
990 parent_buildable_iface->add_child (buildable, builder, child, type);
995 gtk_menu_item_buildable_custom_finished (GtkBuildable *buildable,
998 const gchar *tagname,
1001 GtkWidget *toplevel;
1003 if (strcmp (tagname, "accelerator") == 0)
1005 GtkMenuShell *menu_shell;
1008 menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (buildable)));
1011 while (GTK_IS_MENU (menu_shell) &&
1012 (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
1013 menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (attach));
1015 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
1019 /* Fall back to something ... */
1020 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (buildable));
1022 g_warning ("found a GtkMenuItem '%s' without a parent GtkMenuShell, assigned accelerators wont work.",
1023 gtk_buildable_get_name (buildable));
1026 /* Feed the correct toplevel to the GtkWidget accelerator parsing code */
1027 _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
1030 parent_buildable_iface->custom_finished (buildable, builder, child, tagname, user_data);
1035 gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
1037 iface->update = gtk_menu_item_update;
1038 iface->sync_action_properties = gtk_menu_item_sync_action_properties;
1042 activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
1046 child = gtk_bin_get_child (GTK_BIN (menu_item));
1048 if (GTK_IS_LABEL (child))
1052 label = gtk_action_get_label (action);
1053 gtk_menu_item_set_label (menu_item, label);
1057 gboolean _gtk_menu_is_empty (GtkWidget *menu);
1060 gtk_menu_item_update (GtkActivatable *activatable,
1062 const gchar *property_name)
1064 GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
1065 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1067 if (strcmp (property_name, "visible") == 0)
1068 _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
1069 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
1070 else if (strcmp (property_name, "sensitive") == 0)
1071 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
1072 else if (priv->use_action_appearance)
1074 if (strcmp (property_name, "label") == 0)
1075 activatable_update_label (menu_item, action);
1080 gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
1083 GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
1084 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1087 if (!priv->use_action_appearance || !action)
1089 label = gtk_bin_get_child (GTK_BIN (menu_item));
1091 if (GTK_IS_ACCEL_LABEL (label))
1092 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), GTK_WIDGET (menu_item));
1098 _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
1099 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
1101 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
1103 if (priv->use_action_appearance)
1105 label = gtk_bin_get_child (GTK_BIN (menu_item));
1107 /* make sure label is a label */
1108 if (label && !GTK_IS_LABEL (label))
1110 gtk_container_remove (GTK_CONTAINER (menu_item), label);
1114 gtk_menu_item_ensure_label (menu_item);
1115 gtk_menu_item_set_use_underline (menu_item, TRUE);
1117 if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
1119 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), NULL);
1120 gtk_accel_label_set_accel_closure (GTK_ACCEL_LABEL (label),
1121 gtk_action_get_accel_closure (action));
1124 activatable_update_label (menu_item, action);
1129 gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
1132 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1134 if (priv->action == action)
1139 gtk_action_disconnect_accelerator (priv->action);
1144 const gchar *accel_path;
1146 accel_path = gtk_action_get_accel_path (action);
1149 gtk_action_connect_accelerator (action);
1150 gtk_menu_item_set_accel_path (menu_item, accel_path);
1154 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
1156 priv->action = action;
1160 gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
1161 gboolean use_appearance)
1163 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1165 if (priv->use_action_appearance != use_appearance)
1167 priv->use_action_appearance = use_appearance;
1169 gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (menu_item), priv->action);
1175 * gtk_menu_item_set_submenu:
1176 * @menu_item: a #GtkMenuItem
1177 * @submenu: (allow-none): the submenu, or %NULL
1179 * Sets or replaces the menu item's submenu, or removes it when a %NULL
1180 * submenu is passed.
1183 gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
1186 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1187 g_return_if_fail (submenu == NULL || GTK_IS_MENU (submenu));
1189 if (menu_item->submenu != submenu)
1191 if (menu_item->submenu)
1192 gtk_menu_detach (GTK_MENU (menu_item->submenu));
1196 menu_item->submenu = submenu;
1197 gtk_menu_attach_to_widget (GTK_MENU (submenu),
1198 GTK_WIDGET (menu_item),
1199 gtk_menu_item_detacher);
1202 if (gtk_widget_get_parent (GTK_WIDGET (menu_item)))
1203 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
1205 g_object_notify (G_OBJECT (menu_item), "submenu");
1210 * gtk_menu_item_get_submenu:
1211 * @menu_item: a #GtkMenuItem
1213 * Gets the submenu underneath this menu item, if any.
1214 * See gtk_menu_item_set_submenu().
1216 * Return value: (transfer none): submenu for this menu item, or %NULL if none.
1219 gtk_menu_item_get_submenu (GtkMenuItem *menu_item)
1221 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
1223 return menu_item->submenu;
1226 void _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
1227 GtkSubmenuPlacement placement);
1230 _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
1231 GtkSubmenuPlacement placement)
1233 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1235 menu_item->submenu_placement = placement;
1239 gtk_menu_item_select (GtkMenuItem *menu_item)
1243 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1245 g_signal_emit (menu_item, menu_item_signals[SELECT], 0);
1247 /* Enable themeing of the parent menu item depending on whether
1248 * something is selected in its submenu
1250 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1251 if (GTK_IS_MENU (parent))
1253 GtkMenu *menu = GTK_MENU (parent);
1255 if (menu->parent_menu_item)
1256 gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
1261 gtk_menu_item_deselect (GtkMenuItem *menu_item)
1265 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1267 g_signal_emit (menu_item, menu_item_signals[DESELECT], 0);
1269 /* Enable themeing of the parent menu item depending on whether
1270 * something is selected in its submenu
1272 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1273 if (GTK_IS_MENU (parent))
1275 GtkMenu *menu = GTK_MENU (parent);
1277 if (menu->parent_menu_item)
1278 gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
1283 gtk_menu_item_activate (GtkMenuItem *menu_item)
1285 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1287 g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
1291 gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1294 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1296 g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
1300 gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1303 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1305 g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
1309 gtk_menu_item_size_allocate (GtkWidget *widget,
1310 GtkAllocation *allocation)
1312 GtkMenuItem *menu_item;
1314 GtkAllocation child_allocation;
1315 GtkTextDirection direction;
1316 GtkPackDirection pack_dir;
1317 GtkPackDirection child_pack_dir;
1321 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1322 g_return_if_fail (allocation != NULL);
1324 menu_item = GTK_MENU_ITEM (widget);
1325 bin = GTK_BIN (widget);
1327 direction = gtk_widget_get_direction (widget);
1329 parent = gtk_widget_get_parent (widget);
1330 if (GTK_IS_MENU_BAR (parent))
1332 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
1333 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
1337 pack_dir = GTK_PACK_DIRECTION_LTR;
1338 child_pack_dir = GTK_PACK_DIRECTION_LTR;
1341 gtk_widget_set_allocation (widget, allocation);
1343 child = gtk_bin_get_child (bin);
1346 GtkRequisition child_requisition;
1348 guint horizontal_padding;
1351 style = gtk_widget_get_style (widget);
1352 gtk_widget_style_get (widget,
1353 "horizontal-padding", &horizontal_padding,
1356 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1357 child_allocation.x = border_width + style->xthickness;
1358 child_allocation.y = border_width + style->ythickness;
1360 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
1361 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
1362 child_allocation.x += horizontal_padding;
1363 else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
1364 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
1365 child_allocation.y += horizontal_padding;
1367 child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
1368 child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
1370 if (child_pack_dir == GTK_PACK_DIRECTION_LTR ||
1371 child_pack_dir == GTK_PACK_DIRECTION_RTL)
1373 if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL))
1374 child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
1375 child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size;
1379 if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT))
1380 child_allocation.y += GTK_MENU_ITEM (widget)->toggle_size;
1381 child_allocation.height -= GTK_MENU_ITEM (widget)->toggle_size;
1384 child_allocation.x += allocation->x;
1385 child_allocation.y += allocation->y;
1387 gtk_widget_get_preferred_size (child, &child_requisition, NULL);
1388 if (menu_item->submenu && menu_item->show_submenu_indicator)
1390 if (direction == GTK_TEXT_DIR_RTL)
1391 child_allocation.x += child_requisition.height;
1392 child_allocation.width -= child_requisition.height;
1395 if (child_allocation.width < 1)
1396 child_allocation.width = 1;
1398 gtk_widget_size_allocate (child, &child_allocation);
1401 if (gtk_widget_get_realized (widget))
1402 gdk_window_move_resize (menu_item->event_window,
1403 allocation->x, allocation->y,
1404 allocation->width, allocation->height);
1406 if (menu_item->submenu)
1407 gtk_menu_reposition (GTK_MENU (menu_item->submenu));
1411 gtk_menu_item_realize (GtkWidget *widget)
1413 GtkAllocation allocation;
1414 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1416 GdkWindowAttr attributes;
1417 gint attributes_mask;
1419 gtk_widget_set_realized (widget, TRUE);
1421 window = gtk_widget_get_parent_window (widget);
1422 gtk_widget_set_window (widget, window);
1423 g_object_ref (window);
1425 gtk_widget_get_allocation (widget, &allocation);
1427 attributes.x = allocation.x;
1428 attributes.y = allocation.y;
1429 attributes.width = allocation.width;
1430 attributes.height = allocation.height;
1431 attributes.window_type = GDK_WINDOW_CHILD;
1432 attributes.wclass = GDK_INPUT_ONLY;
1433 attributes.event_mask = (gtk_widget_get_events (widget) |
1434 GDK_BUTTON_PRESS_MASK |
1435 GDK_BUTTON_RELEASE_MASK |
1436 GDK_ENTER_NOTIFY_MASK |
1437 GDK_LEAVE_NOTIFY_MASK |
1438 GDK_POINTER_MOTION_MASK);
1440 attributes_mask = GDK_WA_X | GDK_WA_Y;
1442 menu_item->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1443 &attributes, attributes_mask);
1444 gdk_window_set_user_data (menu_item->event_window, widget);
1446 gtk_widget_style_attach (widget);
1450 gtk_menu_item_unrealize (GtkWidget *widget)
1452 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1454 gdk_window_set_user_data (menu_item->event_window, NULL);
1455 gdk_window_destroy (menu_item->event_window);
1456 menu_item->event_window = NULL;
1458 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize (widget);
1462 gtk_menu_item_map (GtkWidget *widget)
1464 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1466 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->map (widget);
1468 gdk_window_show (menu_item->event_window);
1472 gtk_menu_item_unmap (GtkWidget *widget)
1474 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1476 gdk_window_hide (menu_item->event_window);
1478 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unmap (widget);
1482 gtk_menu_item_enter (GtkWidget *widget,
1483 GdkEventCrossing *event)
1485 g_return_val_if_fail (event != NULL, FALSE);
1487 return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
1491 gtk_menu_item_leave (GtkWidget *widget,
1492 GdkEventCrossing *event)
1494 g_return_val_if_fail (event != NULL, FALSE);
1496 return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent*) event);
1500 gtk_menu_item_draw (GtkWidget *widget,
1503 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1504 GtkStateType state_type;
1505 GtkShadowType shadow_type, selected_shadow_type;
1509 gint x, y, w, h, width, height;
1510 guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1512 state_type = gtk_widget_get_state (widget);
1513 style = gtk_widget_get_style (widget);
1514 window = gtk_widget_get_window (widget);
1515 width = gtk_widget_get_allocated_width (widget);
1516 height = gtk_widget_get_allocated_height (widget);
1520 w = width - border_width * 2;
1521 h = height - border_width * 2;
1523 child = gtk_bin_get_child (GTK_BIN (menu_item));
1525 if (child && state_type == GTK_STATE_PRELIGHT)
1527 gtk_widget_style_get (widget,
1528 "selected-shadow-type", &selected_shadow_type,
1530 gtk_paint_box (style,
1533 selected_shadow_type,
1538 if (menu_item->submenu && menu_item->show_submenu_indicator)
1540 gint arrow_x, arrow_y;
1542 guint horizontal_padding;
1543 GtkTextDirection direction;
1544 GtkArrowType arrow_type;
1546 direction = gtk_widget_get_direction (widget);
1548 gtk_widget_style_get (widget,
1549 "horizontal-padding", &horizontal_padding,
1552 get_arrow_size (widget, child, &arrow_size);
1554 shadow_type = GTK_SHADOW_OUT;
1555 if (state_type == GTK_STATE_PRELIGHT)
1556 shadow_type = GTK_SHADOW_IN;
1558 if (direction == GTK_TEXT_DIR_LTR)
1560 arrow_x = x + w - horizontal_padding - arrow_size;
1561 arrow_type = GTK_ARROW_RIGHT;
1565 arrow_x = x + horizontal_padding;
1566 arrow_type = GTK_ARROW_LEFT;
1569 arrow_y = y + (h - arrow_size) / 2;
1571 gtk_paint_arrow (style, cr,
1572 state_type, shadow_type,
1576 arrow_size, arrow_size);
1580 gboolean wide_separators;
1581 gint separator_height;
1582 guint horizontal_padding;
1584 gtk_widget_style_get (widget,
1585 "wide-separators", &wide_separators,
1586 "separator-height", &separator_height,
1587 "horizontal-padding", &horizontal_padding,
1590 if (wide_separators)
1591 gtk_paint_box (style, cr,
1592 GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
1593 widget, "hseparator",
1594 horizontal_padding + style->xthickness,
1595 (height - separator_height - style->ythickness) / 2,
1596 width - 2 * (horizontal_padding + style->xthickness),
1599 gtk_paint_hline (style, cr,
1600 GTK_STATE_NORMAL, widget, "menuitem",
1601 horizontal_padding + style->xthickness,
1602 width - horizontal_padding - style->xthickness - 1,
1603 (height - style->ythickness) / 2);
1606 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->draw (widget, cr);
1612 gtk_real_menu_item_select (GtkMenuItem *menu_item)
1614 gboolean touchscreen_mode;
1616 g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_item)),
1617 "gtk-touchscreen-mode", &touchscreen_mode,
1620 if (!touchscreen_mode &&
1621 menu_item->submenu &&
1622 (!gtk_widget_get_mapped (menu_item->submenu) ||
1623 GTK_MENU (menu_item->submenu)->tearoff_active))
1625 _gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1628 gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
1629 gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1633 gtk_real_menu_item_deselect (GtkMenuItem *menu_item)
1635 if (menu_item->submenu)
1636 _gtk_menu_item_popdown_submenu (GTK_WIDGET (menu_item));
1638 gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
1639 gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1643 gtk_menu_item_mnemonic_activate (GtkWidget *widget,
1644 gboolean group_cycling)
1648 parent = gtk_widget_get_parent (widget);
1650 if (GTK_IS_MENU_SHELL (parent))
1651 _gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (parent), TRUE);
1653 if (group_cycling &&
1655 GTK_IS_MENU_SHELL (parent) &&
1656 GTK_MENU_SHELL (parent)->active)
1658 gtk_menu_shell_select_item (GTK_MENU_SHELL (parent),
1662 g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0);
1668 gtk_real_menu_item_activate (GtkMenuItem *menu_item)
1670 GtkMenuItemPrivate *priv;
1672 priv = GET_PRIVATE (menu_item);
1675 gtk_action_activate (priv->action);
1680 gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
1682 GtkMenuItemPrivate *priv;
1686 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1688 priv = GET_PRIVATE (menu_item);
1689 widget = GTK_WIDGET (menu_item);
1690 parent = gtk_widget_get_parent (widget);
1692 if (parent && GTK_IS_MENU_SHELL (parent))
1694 GtkMenuShell *menu_shell = GTK_MENU_SHELL (parent);
1696 if (menu_item->submenu == NULL)
1697 gtk_menu_shell_activate_item (menu_shell,
1701 _gtk_menu_shell_activate (menu_shell);
1703 gtk_menu_shell_select_item (menu_shell, widget);
1704 _gtk_menu_item_popup_submenu (widget, FALSE);
1706 gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
1712 gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1715 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1721 gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1724 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1726 menu_item->toggle_size = allocation;
1730 gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
1735 gtk_menu_item_ensure_label (menu_item);
1737 child = gtk_bin_get_child (GTK_BIN (menu_item));
1738 if (GTK_IS_LABEL (child))
1740 gtk_label_set_label (GTK_LABEL (child), label ? label : "");
1742 g_object_notify (G_OBJECT (menu_item), "label");
1746 static G_CONST_RETURN gchar *
1747 gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
1751 gtk_menu_item_ensure_label (menu_item);
1753 child = gtk_bin_get_child (GTK_BIN (menu_item));
1754 if (GTK_IS_LABEL (child))
1755 return gtk_label_get_label (GTK_LABEL (child));
1761 free_timeval (GTimeVal *val)
1763 g_slice_free (GTimeVal, val);
1767 gtk_menu_item_real_popup_submenu (GtkWidget *widget,
1768 gboolean remember_exact_time)
1770 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1773 parent = gtk_widget_get_parent (widget);
1775 if (gtk_widget_is_sensitive (menu_item->submenu) && parent)
1777 gboolean take_focus;
1778 GtkMenuPositionFunc menu_position_func;
1780 take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent));
1781 gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (menu_item->submenu),
1784 if (remember_exact_time)
1786 GTimeVal *popup_time = g_slice_new0 (GTimeVal);
1788 g_get_current_time (popup_time);
1790 g_object_set_data_full (G_OBJECT (menu_item->submenu),
1791 "gtk-menu-exact-popup-time", popup_time,
1792 (GDestroyNotify) free_timeval);
1796 g_object_set_data (G_OBJECT (menu_item->submenu),
1797 "gtk-menu-exact-popup-time", NULL);
1800 /* gtk_menu_item_position_menu positions the submenu from the
1801 * menuitems position. If the menuitem doesn't have a window,
1802 * that doesn't work. In that case we use the default
1803 * positioning function instead which places the submenu at the
1806 if (gtk_widget_get_window (widget))
1807 menu_position_func = gtk_menu_item_position_menu;
1809 menu_position_func = NULL;
1811 gtk_menu_popup (GTK_MENU (menu_item->submenu),
1816 GTK_MENU_SHELL (parent)->button,
1820 /* Enable themeing of the parent menu item depending on whether
1821 * its submenu is shown or not.
1823 gtk_widget_queue_draw (widget);
1827 gtk_menu_item_popup_timeout (gpointer data)
1829 GtkMenuItem *menu_item;
1832 menu_item = GTK_MENU_ITEM (data);
1834 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1836 if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active) ||
1837 (GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off))
1839 gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1840 if (menu_item->timer_from_keypress && menu_item->submenu)
1841 GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
1844 menu_item->timer = 0;
1850 get_popup_delay (GtkWidget *widget)
1854 parent = gtk_widget_get_parent (widget);
1855 if (GTK_IS_MENU_SHELL (parent))
1857 return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (parent));
1863 g_object_get (gtk_widget_get_settings (widget),
1864 "gtk-menu-popup-delay", &popup_delay,
1872 _gtk_menu_item_popup_submenu (GtkWidget *widget,
1873 gboolean with_delay)
1875 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1877 if (menu_item->timer)
1879 g_source_remove (menu_item->timer);
1880 menu_item->timer = 0;
1886 gint popup_delay = get_popup_delay (widget);
1888 if (popup_delay > 0)
1890 GdkEvent *event = gtk_get_current_event ();
1892 menu_item->timer = gdk_threads_add_timeout (popup_delay,
1893 gtk_menu_item_popup_timeout,
1897 event->type != GDK_BUTTON_PRESS &&
1898 event->type != GDK_ENTER_NOTIFY)
1899 menu_item->timer_from_keypress = TRUE;
1901 menu_item->timer_from_keypress = FALSE;
1904 gdk_event_free (event);
1910 gtk_menu_item_real_popup_submenu (widget, FALSE);
1914 _gtk_menu_item_popdown_submenu (GtkWidget *widget)
1916 GtkMenuItem *menu_item;
1918 menu_item = GTK_MENU_ITEM (widget);
1920 if (menu_item->submenu)
1922 g_object_set_data (G_OBJECT (menu_item->submenu),
1923 "gtk-menu-exact-popup-time", NULL);
1925 if (menu_item->timer)
1927 g_source_remove (menu_item->timer);
1928 menu_item->timer = 0;
1931 gtk_menu_popdown (GTK_MENU (menu_item->submenu));
1933 gtk_widget_queue_draw (widget);
1938 get_offsets (GtkMenu *menu,
1939 gint *horizontal_offset,
1940 gint *vertical_offset)
1942 gint vertical_padding;
1943 gint horizontal_padding;
1945 gtk_widget_style_get (GTK_WIDGET (menu),
1946 "horizontal-offset", horizontal_offset,
1947 "vertical-offset", vertical_offset,
1948 "horizontal-padding", &horizontal_padding,
1949 "vertical-padding", &vertical_padding,
1952 *vertical_offset -= gtk_widget_get_style (GTK_WIDGET (menu))->ythickness;
1953 *vertical_offset -= vertical_padding;
1954 *horizontal_offset += horizontal_padding;
1958 gtk_menu_item_position_menu (GtkMenu *menu,
1964 GtkAllocation allocation;
1965 GtkMenuItem *menu_item;
1967 GtkMenuItem *parent_menu_item;
1968 GtkRequisition requisition;
1971 gint twidth, theight;
1973 GtkTextDirection direction;
1974 GdkRectangle monitor;
1976 gint horizontal_offset;
1977 gint vertical_offset;
1978 gint parent_xthickness;
1979 gint available_left, available_right;
1981 g_return_if_fail (menu != NULL);
1982 g_return_if_fail (x != NULL);
1983 g_return_if_fail (y != NULL);
1985 menu_item = GTK_MENU_ITEM (user_data);
1986 widget = GTK_WIDGET (user_data);
1991 direction = gtk_widget_get_direction (widget);
1993 gtk_widget_get_preferred_size (GTK_WIDGET (menu), &requisition, NULL);
1994 twidth = requisition.width;
1995 theight = requisition.height;
1997 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
1998 monitor_num = gdk_screen_get_monitor_at_window (screen, menu_item->event_window);
1999 if (monitor_num < 0)
2001 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
2003 if (!gdk_window_get_origin (gtk_widget_get_window (widget),
2006 g_warning ("Menu not on screen");
2010 gtk_widget_get_allocation (widget, &allocation);
2015 get_offsets (menu, &horizontal_offset, &vertical_offset);
2017 available_left = tx - monitor.x;
2018 available_right = monitor.x + monitor.width - (tx + allocation.width);
2020 parent = gtk_widget_get_parent (widget);
2021 if (GTK_IS_MENU_BAR (parent))
2023 menu_item->from_menubar = TRUE;
2025 else if (GTK_IS_MENU (parent))
2027 if (GTK_MENU (parent)->parent_menu_item)
2028 menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (parent)->parent_menu_item)->from_menubar;
2030 menu_item->from_menubar = FALSE;
2034 menu_item->from_menubar = FALSE;
2037 switch (menu_item->submenu_placement)
2039 case GTK_TOP_BOTTOM:
2040 if (direction == GTK_TEXT_DIR_LTR)
2041 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
2044 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
2045 tx += allocation.width - twidth;
2047 if ((ty + allocation.height + theight) <= monitor.y + monitor.height)
2048 ty += allocation.height;
2049 else if ((ty - theight) >= monitor.y)
2051 else if (monitor.y + monitor.height - (ty + allocation.height) > ty)
2052 ty += allocation.height;
2057 case GTK_LEFT_RIGHT:
2058 if (GTK_IS_MENU (parent))
2059 parent_menu_item = GTK_MENU_ITEM (GTK_MENU (parent)->parent_menu_item);
2061 parent_menu_item = NULL;
2063 parent_xthickness = gtk_widget_get_style (parent)->xthickness;
2065 if (parent_menu_item && !GTK_MENU (parent)->torn_off)
2067 menu_item->submenu_direction = parent_menu_item->submenu_direction;
2071 if (direction == GTK_TEXT_DIR_LTR)
2072 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
2074 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
2077 switch (menu_item->submenu_direction)
2079 case GTK_DIRECTION_LEFT:
2080 if (tx - twidth - parent_xthickness - horizontal_offset >= monitor.x ||
2081 available_left >= available_right)
2082 tx -= twidth + parent_xthickness + horizontal_offset;
2085 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
2086 tx += allocation.width + parent_xthickness + horizontal_offset;
2090 case GTK_DIRECTION_RIGHT:
2091 if (tx + allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
2092 available_right >= available_left)
2093 tx += allocation.width + parent_xthickness + horizontal_offset;
2096 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
2097 tx -= twidth + parent_xthickness + horizontal_offset;
2102 ty += vertical_offset;
2104 /* If the height of the menu doesn't fit we move it upward. */
2105 ty = CLAMP (ty, monitor.y, MAX (monitor.y, monitor.y + monitor.height - theight));
2109 /* If we have negative, tx, here it is because we can't get
2110 * the menu all the way on screen. Favor the left portion.
2112 *x = CLAMP (tx, monitor.x, MAX (monitor.x, monitor.x + monitor.width - twidth));
2115 gtk_menu_set_monitor (menu, monitor_num);
2117 if (!gtk_widget_get_visible (menu->toplevel))
2119 gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar?
2120 GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
2125 * gtk_menu_item_set_right_justified:
2126 * @menu_item: a #GtkMenuItem.
2127 * @right_justified: if %TRUE the menu item will appear at the
2128 * far right if added to a menu bar.
2130 * Sets whether the menu item appears justified at the right
2131 * side of a menu bar. This was traditionally done for "Help" menu
2132 * items, but is now considered a bad idea. (If the widget
2133 * layout is reversed for a right-to-left language like Hebrew
2134 * or Arabic, right-justified-menu-items appear at the left.)
2137 gtk_menu_item_set_right_justified (GtkMenuItem *menu_item,
2138 gboolean right_justified)
2140 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2142 right_justified = right_justified != FALSE;
2144 if (right_justified != menu_item->right_justify)
2146 menu_item->right_justify = right_justified;
2147 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
2152 * gtk_menu_item_get_right_justified:
2153 * @menu_item: a #GtkMenuItem
2155 * Gets whether the menu item appears justified at the right
2156 * side of the menu bar.
2158 * Return value: %TRUE if the menu item will appear at the
2159 * far right if added to a menu bar.
2162 gtk_menu_item_get_right_justified (GtkMenuItem *menu_item)
2164 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2166 return menu_item->right_justify;
2171 gtk_menu_item_show_all (GtkWidget *widget)
2173 GtkMenuItem *menu_item;
2175 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
2177 menu_item = GTK_MENU_ITEM (widget);
2179 /* show children including submenu */
2180 if (menu_item->submenu)
2181 gtk_widget_show_all (menu_item->submenu);
2182 gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_show_all, NULL);
2184 gtk_widget_show (widget);
2188 gtk_menu_item_hide_all (GtkWidget *widget)
2190 GtkMenuItem *menu_item;
2192 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
2194 gtk_widget_hide (widget);
2196 menu_item = GTK_MENU_ITEM (widget);
2198 /* hide children including submenu */
2199 gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_hide_all, NULL);
2200 if (menu_item->submenu)
2201 gtk_widget_hide_all (menu_item->submenu);
2205 gtk_menu_item_can_activate_accel (GtkWidget *widget,
2210 parent = gtk_widget_get_parent (widget);
2211 /* Chain to the parent GtkMenu for further checks */
2212 return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) &&
2213 parent && gtk_widget_can_activate_accel (parent, signal_id));
2217 gtk_menu_item_accel_name_foreach (GtkWidget *widget,
2220 const gchar **path_p = data;
2224 if (GTK_IS_LABEL (widget))
2226 *path_p = gtk_label_get_text (GTK_LABEL (widget));
2227 if (*path_p && (*path_p)[0] == 0)
2230 else if (GTK_IS_CONTAINER (widget))
2231 gtk_container_foreach (GTK_CONTAINER (widget),
2232 gtk_menu_item_accel_name_foreach,
2238 gtk_menu_item_parent_set (GtkWidget *widget,
2239 GtkWidget *previous_parent)
2241 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
2245 parent = gtk_widget_get_parent (widget);
2246 menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
2249 _gtk_menu_item_refresh_accel_path (menu_item,
2254 if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set)
2255 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent);
2259 _gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item,
2260 const gchar *prefix,
2261 GtkAccelGroup *accel_group,
2262 gboolean group_changed)
2267 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2268 g_return_if_fail (!accel_group || GTK_IS_ACCEL_GROUP (accel_group));
2270 widget = GTK_WIDGET (menu_item);
2274 gtk_widget_set_accel_path (widget, NULL, NULL);
2278 path = _gtk_widget_get_accel_path (widget, NULL);
2279 if (!path) /* no active accel_path yet */
2281 path = menu_item->accel_path;
2282 if (!path && prefix)
2284 const gchar *postfix = NULL;
2287 /* try to construct one from label text */
2288 gtk_container_foreach (GTK_CONTAINER (menu_item),
2289 gtk_menu_item_accel_name_foreach,
2293 new_path = g_strconcat (prefix, "/", postfix, NULL);
2294 path = menu_item->accel_path = (char*)g_intern_string (new_path);
2299 gtk_widget_set_accel_path (widget, path, accel_group);
2301 else if (group_changed) /* reinstall accelerators */
2302 gtk_widget_set_accel_path (widget, path, accel_group);
2306 * gtk_menu_item_set_accel_path
2307 * @menu_item: a valid #GtkMenuItem
2308 * @accel_path: (allow-none): accelerator path, corresponding to this menu item's
2309 * functionality, or %NULL to unset the current path.
2311 * Set the accelerator path on @menu_item, through which runtime changes of the
2312 * menu item's accelerator caused by the user can be identified and saved to
2313 * persistant storage (see gtk_accel_map_save() on this).
2314 * To setup a default accelerator for this menu item, call
2315 * gtk_accel_map_add_entry() with the same @accel_path.
2316 * See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
2317 * and gtk_menu_set_accel_path() for a more convenient variant of this function.
2319 * This function is basically a convenience wrapper that handles calling
2320 * gtk_widget_set_accel_path() with the appropriate accelerator group for
2323 * Note that you do need to set an accelerator on the parent menu with
2324 * gtk_menu_set_accel_group() for this to work.
2326 * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
2327 * pass a static string, you can save some memory by interning it first with
2328 * g_intern_static_string().
2331 gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
2332 const gchar *accel_path)
2337 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2338 g_return_if_fail (accel_path == NULL ||
2339 (accel_path[0] == '<' && strchr (accel_path, '/')));
2341 widget = GTK_WIDGET (menu_item);
2343 /* store new path */
2344 menu_item->accel_path = (char*)g_intern_string (accel_path);
2346 /* forget accelerators associated with old path */
2347 gtk_widget_set_accel_path (widget, NULL, NULL);
2349 /* install accelerators associated with new path */
2350 parent = gtk_widget_get_parent (widget);
2351 if (GTK_IS_MENU (parent))
2353 GtkMenu *menu = GTK_MENU (parent);
2355 if (menu->accel_group)
2356 _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
2364 * gtk_menu_item_get_accel_path
2365 * @menu_item: a valid #GtkMenuItem
2367 * Retrieve the accelerator path that was previously set on @menu_item.
2369 * See gtk_menu_item_set_accel_path() for details.
2371 * Returns: the accelerator path corresponding to this menu item's
2372 * functionality, or %NULL if not set
2376 G_CONST_RETURN gchar *
2377 gtk_menu_item_get_accel_path (GtkMenuItem *menu_item)
2379 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2381 return menu_item->accel_path;
2385 gtk_menu_item_forall (GtkContainer *container,
2386 gboolean include_internals,
2387 GtkCallback callback,
2388 gpointer callback_data)
2392 g_return_if_fail (GTK_IS_MENU_ITEM (container));
2393 g_return_if_fail (callback != NULL);
2395 child = gtk_bin_get_child (GTK_BIN (container));
2397 callback (child, callback_data);
2401 _gtk_menu_item_is_selectable (GtkWidget *menu_item)
2403 if ((!gtk_bin_get_child (GTK_BIN (menu_item)) &&
2404 G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
2405 GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
2406 !gtk_widget_is_sensitive (menu_item) ||
2407 !gtk_widget_get_visible (menu_item))
2414 gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
2416 GtkWidget *accel_label;
2418 if (!gtk_bin_get_child (GTK_BIN (menu_item)))
2420 accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
2421 gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
2423 gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
2424 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label),
2425 GTK_WIDGET (menu_item));
2426 gtk_widget_show (accel_label);
2431 * gtk_menu_item_set_label:
2432 * @menu_item: a #GtkMenuItem
2433 * @label: the text you want to set
2435 * Sets @text on the @menu_item label
2440 gtk_menu_item_set_label (GtkMenuItem *menu_item,
2443 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2445 GTK_MENU_ITEM_GET_CLASS (menu_item)->set_label (menu_item, label);
2449 * gtk_menu_item_get_label:
2450 * @menu_item: a #GtkMenuItem
2452 * Sets @text on the @menu_item label
2454 * Returns: The text in the @menu_item label. This is the internal
2455 * string used by the label, and must not be modified.
2459 G_CONST_RETURN gchar *
2460 gtk_menu_item_get_label (GtkMenuItem *menu_item)
2462 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2464 return GTK_MENU_ITEM_GET_CLASS (menu_item)->get_label (menu_item);
2468 * gtk_menu_item_set_use_underline:
2469 * @menu_item: a #GtkMenuItem
2470 * @setting: %TRUE if underlines in the text indicate mnemonics
2472 * If true, an underline in the text indicates the next character should be
2473 * used for the mnemonic accelerator key.
2478 gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
2483 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2485 gtk_menu_item_ensure_label (menu_item);
2487 child = gtk_bin_get_child (GTK_BIN (menu_item));
2488 if (GTK_IS_LABEL (child))
2490 gtk_label_set_use_underline (GTK_LABEL (child), setting);
2492 g_object_notify (G_OBJECT (menu_item), "use-underline");
2497 * gtk_menu_item_get_use_underline:
2498 * @menu_item: a #GtkMenuItem
2500 * Checks if an underline in the text indicates the next character should be
2501 * used for the mnemonic accelerator key.
2503 * Return value: %TRUE if an embedded underline in the label indicates
2504 * the mnemonic accelerator key.
2509 gtk_menu_item_get_use_underline (GtkMenuItem *menu_item)
2513 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2515 gtk_menu_item_ensure_label (menu_item);
2517 child = gtk_bin_get_child (GTK_BIN (menu_item));
2518 if (GTK_IS_LABEL (child))
2519 return gtk_label_get_use_underline (GTK_LABEL (child));