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"
33 #include "gtkmenuprivate.h"
34 #include "gtkmenushellprivate.h"
35 #include "gtkmenuitemprivate.h"
36 #include "gtkmenubar.h"
37 #include "gtkmenuprivate.h"
38 #include "gtkseparatormenuitem.h"
39 #include "gtkprivate.h"
40 #include "gtkbuildable.h"
41 #include "gtkactivatable.h"
63 /* activatable properties */
64 PROP_ACTIVATABLE_RELATED_ACTION,
65 PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
69 static void gtk_menu_item_dispose (GObject *object);
70 static void gtk_menu_item_set_property (GObject *object,
74 static void gtk_menu_item_get_property (GObject *object,
78 static void gtk_menu_item_destroy (GtkWidget *widget);
79 static void gtk_menu_item_size_allocate (GtkWidget *widget,
80 GtkAllocation *allocation);
81 static void gtk_menu_item_realize (GtkWidget *widget);
82 static void gtk_menu_item_unrealize (GtkWidget *widget);
83 static void gtk_menu_item_map (GtkWidget *widget);
84 static void gtk_menu_item_unmap (GtkWidget *widget);
85 static gboolean gtk_menu_item_enter (GtkWidget *widget,
86 GdkEventCrossing *event);
87 static gboolean gtk_menu_item_leave (GtkWidget *widget,
88 GdkEventCrossing *event);
89 static gboolean gtk_menu_item_draw (GtkWidget *widget,
91 static void gtk_menu_item_parent_set (GtkWidget *widget,
92 GtkWidget *previous_parent);
95 static void gtk_real_menu_item_select (GtkMenuItem *item);
96 static void gtk_real_menu_item_deselect (GtkMenuItem *item);
97 static void gtk_real_menu_item_activate (GtkMenuItem *item);
98 static void gtk_real_menu_item_activate_item (GtkMenuItem *item);
99 static void gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
101 static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
103 static gboolean gtk_menu_item_mnemonic_activate (GtkWidget *widget,
104 gboolean group_cycling);
106 static void gtk_menu_item_ensure_label (GtkMenuItem *menu_item);
107 static gint gtk_menu_item_popup_timeout (gpointer data);
108 static void gtk_menu_item_position_menu (GtkMenu *menu,
113 static void gtk_menu_item_show_all (GtkWidget *widget);
114 static void gtk_menu_item_forall (GtkContainer *container,
115 gboolean include_internals,
116 GtkCallback callback,
117 gpointer callback_data);
118 static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
121 static void gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
123 static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
125 static void gtk_menu_item_get_preferred_width (GtkWidget *widget,
128 static void gtk_menu_item_get_preferred_height (GtkWidget *widget,
131 static void gtk_menu_item_get_preferred_height_for_width (GtkWidget *widget,
136 static void gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface);
137 static void gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
141 static void gtk_menu_item_buildable_custom_finished(GtkBuildable *buildable,
144 const gchar *tagname,
147 static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface);
148 static void gtk_menu_item_update (GtkActivatable *activatable,
150 const gchar *property_name);
151 static void gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
153 static void gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
155 static void gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
156 gboolean use_appearance);
159 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
161 static GtkBuildableIface *parent_buildable_iface;
163 G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_BIN,
164 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
165 gtk_menu_item_buildable_interface_init)
166 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
167 gtk_menu_item_activatable_interface_init))
171 gtk_menu_item_class_init (GtkMenuItemClass *klass)
173 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
174 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
175 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
177 gobject_class->dispose = gtk_menu_item_dispose;
178 gobject_class->set_property = gtk_menu_item_set_property;
179 gobject_class->get_property = gtk_menu_item_get_property;
181 widget_class->destroy = gtk_menu_item_destroy;
182 widget_class->size_allocate = gtk_menu_item_size_allocate;
183 widget_class->draw = gtk_menu_item_draw;
184 widget_class->realize = gtk_menu_item_realize;
185 widget_class->unrealize = gtk_menu_item_unrealize;
186 widget_class->map = gtk_menu_item_map;
187 widget_class->unmap = gtk_menu_item_unmap;
188 widget_class->enter_notify_event = gtk_menu_item_enter;
189 widget_class->leave_notify_event = gtk_menu_item_leave;
190 widget_class->show_all = gtk_menu_item_show_all;
191 widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
192 widget_class->parent_set = gtk_menu_item_parent_set;
193 widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
194 widget_class->get_preferred_width = gtk_menu_item_get_preferred_width;
195 widget_class->get_preferred_height = gtk_menu_item_get_preferred_height;
196 widget_class->get_preferred_height_for_width = gtk_menu_item_get_preferred_height_for_width;
198 container_class->forall = gtk_menu_item_forall;
200 klass->activate = gtk_real_menu_item_activate;
201 klass->activate_item = gtk_real_menu_item_activate_item;
202 klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
203 klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
204 klass->set_label = gtk_real_menu_item_set_label;
205 klass->get_label = gtk_real_menu_item_get_label;
206 klass->select = gtk_real_menu_item_select;
207 klass->deselect = gtk_real_menu_item_deselect;
209 klass->hide_on_activate = TRUE;
211 menu_item_signals[ACTIVATE] =
212 g_signal_new (I_("activate"),
213 G_OBJECT_CLASS_TYPE (gobject_class),
214 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
215 G_STRUCT_OFFSET (GtkMenuItemClass, activate),
217 _gtk_marshal_VOID__VOID,
219 widget_class->activate_signal = menu_item_signals[ACTIVATE];
221 menu_item_signals[ACTIVATE_ITEM] =
222 g_signal_new (I_("activate-item"),
223 G_OBJECT_CLASS_TYPE (gobject_class),
225 G_STRUCT_OFFSET (GtkMenuItemClass, activate_item),
227 _gtk_marshal_VOID__VOID,
230 menu_item_signals[TOGGLE_SIZE_REQUEST] =
231 g_signal_new (I_("toggle-size-request"),
232 G_OBJECT_CLASS_TYPE (gobject_class),
234 G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_request),
236 _gtk_marshal_VOID__POINTER,
240 menu_item_signals[TOGGLE_SIZE_ALLOCATE] =
241 g_signal_new (I_("toggle-size-allocate"),
242 G_OBJECT_CLASS_TYPE (gobject_class),
244 G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_allocate),
246 _gtk_marshal_VOID__INT,
250 menu_item_signals[SELECT] =
251 g_signal_new (I_("select"),
252 G_OBJECT_CLASS_TYPE (gobject_class),
254 G_STRUCT_OFFSET (GtkMenuItemClass, select),
256 _gtk_marshal_VOID__VOID,
259 menu_item_signals[DESELECT] =
260 g_signal_new (I_("deselect"),
261 G_OBJECT_CLASS_TYPE (gobject_class),
263 G_STRUCT_OFFSET (GtkMenuItemClass, deselect),
265 _gtk_marshal_VOID__VOID,
269 * GtkMenuItem:right-justified:
271 * Sets whether the menu item appears justified
272 * at the right side of a menu bar.
276 g_object_class_install_property (gobject_class,
277 PROP_RIGHT_JUSTIFIED,
278 g_param_spec_boolean ("right-justified",
279 P_("Right Justified"),
280 P_("Sets whether the menu item appears justified at the right side of a menu bar"),
282 GTK_PARAM_READWRITE));
285 * GtkMenuItem:submenu:
287 * The submenu attached to the menu item, or %NULL if it has none.
291 g_object_class_install_property (gobject_class,
293 g_param_spec_object ("submenu",
295 P_("The submenu attached to the menu item, or NULL if it has none"),
297 GTK_PARAM_READWRITE));
300 * GtkMenuItem:accel-path:
302 * Sets the accelerator path of the menu item, through which runtime
303 * changes of the menu item's accelerator caused by the user can be
304 * identified and saved to persistant storage.
308 g_object_class_install_property (gobject_class,
310 g_param_spec_string ("accel-path",
312 P_("Sets the accelerator path of the menu item"),
314 GTK_PARAM_READWRITE));
319 * The text for the child label.
323 g_object_class_install_property (gobject_class,
325 g_param_spec_string ("label",
327 P_("The text for the child label"),
329 GTK_PARAM_READWRITE));
332 * GtkMenuItem:use-underline:
334 * %TRUE if underlines in the text indicate mnemonics.
338 g_object_class_install_property (gobject_class,
340 g_param_spec_boolean ("use-underline",
342 P_("If set, an underline in the text indicates "
343 "the next character should be used for the "
344 "mnemonic accelerator key"),
346 GTK_PARAM_READWRITE));
348 g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
349 g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
351 gtk_widget_class_install_style_property_parser (widget_class,
352 g_param_spec_enum ("selected-shadow-type",
353 "Selected Shadow Type",
354 "Shadow type when item is selected",
355 GTK_TYPE_SHADOW_TYPE,
358 gtk_rc_property_parse_enum);
360 gtk_widget_class_install_style_property (widget_class,
361 g_param_spec_int ("horizontal-padding",
362 "Horizontal Padding",
363 "Padding to left and right of the menu item",
367 GTK_PARAM_READABLE));
369 gtk_widget_class_install_style_property (widget_class,
370 g_param_spec_int ("toggle-spacing",
372 "Space between icon and label",
376 GTK_PARAM_READABLE));
378 gtk_widget_class_install_style_property (widget_class,
379 g_param_spec_int ("arrow-spacing",
381 "Space between label and arrow",
385 GTK_PARAM_READABLE));
387 gtk_widget_class_install_style_property (widget_class,
388 g_param_spec_float ("arrow-scaling",
390 P_("Amount of space used up by arrow, relative to the menu item's font size"),
392 GTK_PARAM_READABLE));
395 * GtkMenuItem:width-chars:
397 * The minimum desired width of the menu item in characters.
401 gtk_widget_class_install_style_property (widget_class,
402 g_param_spec_int ("width-chars",
403 P_("Width in Characters"),
404 P_("The minimum desired width of the menu item in characters"),
406 GTK_PARAM_READABLE));
408 g_type_class_add_private (klass, sizeof (GtkMenuItemPrivate));
412 gtk_menu_item_init (GtkMenuItem *menu_item)
414 GtkMenuItemPrivate *priv;
416 priv = G_TYPE_INSTANCE_GET_PRIVATE (menu_item,
419 menu_item->priv = priv;
421 gtk_widget_set_has_window (GTK_WIDGET (menu_item), FALSE);
424 priv->use_action_appearance = TRUE;
426 menu_item->priv->submenu = NULL;
427 menu_item->priv->toggle_size = 0;
428 menu_item->priv->accelerator_width = 0;
429 if (gtk_widget_get_direction (GTK_WIDGET (menu_item)) == GTK_TEXT_DIR_RTL)
430 priv->submenu_direction = GTK_DIRECTION_LEFT;
432 priv->submenu_direction = GTK_DIRECTION_RIGHT;
433 priv->submenu_placement = GTK_TOP_BOTTOM;
434 priv->right_justify = FALSE;
435 priv->use_action_appearance = TRUE;
441 gtk_menu_item_new (void)
443 return g_object_new (GTK_TYPE_MENU_ITEM, NULL);
447 gtk_menu_item_new_with_label (const gchar *label)
449 return g_object_new (GTK_TYPE_MENU_ITEM,
456 * gtk_menu_item_new_with_mnemonic:
457 * @label: The text of the button, with an underscore in front of the
460 * Creates a new #GtkMenuItem containing a label.
462 * The label will be created using gtk_label_new_with_mnemonic(),
463 * so underscores in @label indicate the mnemonic for the menu item.
465 * Returns: a new #GtkMenuItem
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 = menu_item->priv;
484 gtk_action_disconnect_accelerator (priv->action);
485 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
488 G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
492 gtk_menu_item_set_property (GObject *object,
497 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
501 case PROP_RIGHT_JUSTIFIED:
502 gtk_menu_item_set_right_justified (menu_item, g_value_get_boolean (value));
505 gtk_menu_item_set_submenu (menu_item, g_value_get_object (value));
507 case PROP_ACCEL_PATH:
508 gtk_menu_item_set_accel_path (menu_item, g_value_get_string (value));
511 gtk_menu_item_set_label (menu_item, g_value_get_string (value));
513 case PROP_USE_UNDERLINE:
514 gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
516 case PROP_ACTIVATABLE_RELATED_ACTION:
517 gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
519 case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
520 gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
523 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
529 gtk_menu_item_get_property (GObject *object,
534 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
535 GtkMenuItemPrivate *priv = menu_item->priv;
539 case PROP_RIGHT_JUSTIFIED:
540 g_value_set_boolean (value, gtk_menu_item_get_right_justified (menu_item));
543 g_value_set_object (value, gtk_menu_item_get_submenu (menu_item));
545 case PROP_ACCEL_PATH:
546 g_value_set_string (value, gtk_menu_item_get_accel_path (menu_item));
549 g_value_set_string (value, gtk_menu_item_get_label (menu_item));
551 case PROP_USE_UNDERLINE:
552 g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
554 case PROP_ACTIVATABLE_RELATED_ACTION:
555 g_value_set_object (value, priv->action);
557 case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
558 g_value_set_boolean (value, priv->use_action_appearance);
561 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
567 gtk_menu_item_destroy (GtkWidget *widget)
569 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
570 GtkMenuItemPrivate *priv = menu_item->priv;
573 gtk_widget_destroy (priv->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);
583 GtkMenuItemPrivate *priv = menu_item->priv;
585 g_return_if_fail (priv->submenu == (GtkWidget*) menu);
587 priv->submenu = NULL;
591 get_arrow_size (GtkWidget *widget,
595 PangoContext *context;
596 PangoFontMetrics *metrics;
597 gfloat arrow_scaling;
601 gtk_widget_style_get (widget,
602 "arrow-scaling", &arrow_scaling,
605 context = gtk_widget_get_pango_context (child);
606 metrics = pango_context_get_metrics (context,
607 gtk_widget_get_style (child)->font_desc,
608 pango_context_get_language (context));
610 *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
611 pango_font_metrics_get_descent (metrics)));
613 pango_font_metrics_unref (metrics);
615 *size = *size * arrow_scaling;
620 gtk_menu_item_accel_width_foreach (GtkWidget *widget,
625 if (GTK_IS_ACCEL_LABEL (widget))
629 w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
630 *width = MAX (*width, w);
632 else if (GTK_IS_CONTAINER (widget))
633 gtk_container_foreach (GTK_CONTAINER (widget),
634 gtk_menu_item_accel_width_foreach,
639 get_minimum_width (GtkWidget *widget)
641 PangoContext *context;
642 PangoFontMetrics *metrics;
646 context = gtk_widget_get_pango_context (widget);
647 metrics = pango_context_get_metrics (context,
648 gtk_widget_get_style (widget)->font_desc,
649 pango_context_get_language (context));
651 width = pango_font_metrics_get_approximate_char_width (metrics);
653 pango_font_metrics_unref (metrics);
655 gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
657 return PANGO_PIXELS (width_chars * width);
661 gtk_menu_item_get_preferred_width (GtkWidget *widget,
665 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
666 GtkMenuItemPrivate *priv = menu_item->priv;
671 guint horizontal_padding;
673 GtkPackDirection pack_dir;
674 GtkPackDirection child_pack_dir;
675 gint min_width, nat_width;
677 min_width = nat_width = 0;
679 gtk_widget_style_get (widget,
680 "horizontal-padding", &horizontal_padding,
683 bin = GTK_BIN (widget);
684 parent = gtk_widget_get_parent (widget);
686 if (GTK_IS_MENU_BAR (parent))
688 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
689 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
693 pack_dir = GTK_PACK_DIRECTION_LTR;
694 child_pack_dir = GTK_PACK_DIRECTION_LTR;
697 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 GtkMenuItemPrivate *priv = menu_item->priv;
711 gint child_min, child_nat;
713 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
715 if ((menu_item->priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
720 gtk_widget_style_get (widget,
721 "arrow-spacing", &arrow_spacing,
724 get_arrow_size (widget, child, &arrow_size);
726 gtk_widget_style_get (widget,
727 "arrow-spacing", &arrow_spacing,
730 get_arrow_size (widget, child, &arrow_size);
732 min_width += arrow_size;
733 min_width += arrow_spacing;
735 min_width = MAX (min_width, get_minimum_width (widget));
736 nat_width = min_width;
739 min_width += child_min;
740 nat_width += child_nat;
744 gtk_container_foreach (GTK_CONTAINER (menu_item),
745 gtk_menu_item_accel_width_foreach,
747 priv->accelerator_width = accel_width;
750 *minimum_size = min_width;
753 *natural_size = nat_width;
757 gtk_menu_item_get_preferred_height (GtkWidget *widget,
761 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
762 GtkMenuItemPrivate *priv = menu_item->priv;
768 guint horizontal_padding;
770 GtkPackDirection pack_dir;
771 GtkPackDirection child_pack_dir;
772 gint min_height, nat_height;
774 min_height = nat_height = 0;
776 style = gtk_widget_get_style (widget);
778 gtk_widget_style_get (widget,
779 "horizontal-padding", &horizontal_padding,
782 bin = GTK_BIN (widget);
783 parent = gtk_widget_get_parent (widget);
785 if (GTK_IS_MENU_BAR (parent))
787 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
788 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
792 pack_dir = GTK_PACK_DIRECTION_LTR;
793 child_pack_dir = GTK_PACK_DIRECTION_LTR;
796 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
797 min_height = (border_width + style->ythickness) * 2;
799 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
800 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
801 min_height += 2 * horizontal_padding;
803 nat_height = min_height;
805 child = gtk_bin_get_child (bin);
807 if (child != NULL && gtk_widget_get_visible (child))
809 GtkMenuItemPrivate *priv = menu_item->priv;
810 gint child_min, child_nat;
812 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
814 min_height += child_min;
815 nat_height += child_nat;
817 if ((menu_item->priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
821 get_arrow_size (widget, child, &arrow_size);
823 min_height = MAX (min_height, arrow_size);
824 nat_height = MAX (nat_height, arrow_size);
827 else /* separator item */
829 gboolean wide_separators;
830 gint separator_height;
832 gtk_widget_style_get (widget,
833 "wide-separators", &wide_separators,
834 "separator-height", &separator_height,
838 min_height += separator_height + style->ythickness;
840 min_height += style->ythickness * 2;
842 nat_height = min_height;
846 gtk_container_foreach (GTK_CONTAINER (menu_item),
847 gtk_menu_item_accel_width_foreach,
849 priv->accelerator_width = accel_width;
852 *minimum_size = min_height;
855 *natural_size = nat_height;
859 gtk_menu_item_get_preferred_height_for_width (GtkWidget *widget,
864 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
865 GtkMenuItemPrivate *priv = menu_item->priv;
870 guint horizontal_padding;
872 GtkPackDirection pack_dir;
873 GtkPackDirection child_pack_dir;
874 gint min_height, nat_height;
877 min_height = nat_height = 0;
879 style = gtk_widget_get_style (widget);
881 gtk_widget_style_get (widget,
882 "horizontal-padding", &horizontal_padding,
885 bin = GTK_BIN (widget);
886 parent = gtk_widget_get_parent (widget);
888 if (GTK_IS_MENU_BAR (parent))
890 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
891 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
895 pack_dir = GTK_PACK_DIRECTION_LTR;
896 child_pack_dir = GTK_PACK_DIRECTION_LTR;
899 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
900 min_height = (border_width + style->ythickness) * 2;
902 avail_size = for_size;
903 avail_size -= (border_width + style->xthickness) * 2;
905 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
906 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
907 min_height += 2 * horizontal_padding;
909 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
910 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
911 avail_size -= 2 * horizontal_padding;
913 nat_height = min_height;
915 child = gtk_bin_get_child (bin);
917 if (child != NULL && gtk_widget_get_visible (child))
919 gint child_min, child_nat;
922 if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
926 gtk_widget_style_get (widget,
927 "arrow-spacing", &arrow_spacing,
930 get_arrow_size (widget, child, &arrow_size);
932 avail_size -= arrow_size;
933 avail_size -= arrow_spacing;
936 gtk_widget_get_preferred_height_for_width (child,
941 min_height += child_min;
942 nat_height += child_nat;
944 if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
946 min_height = MAX (min_height, arrow_size);
947 nat_height = MAX (nat_height, arrow_size);
950 else /* separator item */
952 gboolean wide_separators;
953 gint separator_height;
955 gtk_widget_style_get (widget,
956 "wide-separators", &wide_separators,
957 "separator-height", &separator_height,
961 min_height += separator_height + style->ythickness;
963 min_height += style->ythickness * 2;
965 nat_height = min_height;
969 *minimum_size = min_height;
972 *natural_size = nat_height;
976 gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
978 parent_buildable_iface = g_type_interface_peek_parent (iface);
979 iface->add_child = gtk_menu_item_buildable_add_child;
980 iface->custom_finished = gtk_menu_item_buildable_custom_finished;
984 gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
989 if (type && strcmp (type, "submenu") == 0)
990 gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
993 parent_buildable_iface->add_child (buildable, builder, child, type);
998 gtk_menu_item_buildable_custom_finished (GtkBuildable *buildable,
1001 const gchar *tagname,
1004 GtkWidget *toplevel;
1006 if (strcmp (tagname, "accelerator") == 0)
1008 GtkMenuShell *menu_shell;
1011 menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (buildable)));
1014 while (GTK_IS_MENU (menu_shell) &&
1015 (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
1016 menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (attach));
1018 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
1022 /* Fall back to something ... */
1023 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (buildable));
1025 g_warning ("found a GtkMenuItem '%s' without a parent GtkMenuShell, assigned accelerators wont work.",
1026 gtk_buildable_get_name (buildable));
1029 /* Feed the correct toplevel to the GtkWidget accelerator parsing code */
1030 _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
1033 parent_buildable_iface->custom_finished (buildable, builder, child, tagname, user_data);
1038 gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
1040 iface->update = gtk_menu_item_update;
1041 iface->sync_action_properties = gtk_menu_item_sync_action_properties;
1045 activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
1049 child = gtk_bin_get_child (GTK_BIN (menu_item));
1051 if (GTK_IS_LABEL (child))
1055 label = gtk_action_get_label (action);
1056 gtk_menu_item_set_label (menu_item, label);
1060 gboolean _gtk_menu_is_empty (GtkWidget *menu);
1063 gtk_menu_item_update (GtkActivatable *activatable,
1065 const gchar *property_name)
1067 GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
1068 GtkMenuItemPrivate *priv = menu_item->priv;
1070 if (strcmp (property_name, "visible") == 0)
1071 _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
1072 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
1073 else if (strcmp (property_name, "sensitive") == 0)
1074 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
1075 else if (priv->use_action_appearance)
1077 if (strcmp (property_name, "label") == 0)
1078 activatable_update_label (menu_item, action);
1083 gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
1086 GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
1087 GtkMenuItemPrivate *priv = menu_item->priv;
1090 if (!priv->use_action_appearance || !action)
1092 label = gtk_bin_get_child (GTK_BIN (menu_item));
1094 if (GTK_IS_ACCEL_LABEL (label))
1095 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), GTK_WIDGET (menu_item));
1101 _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
1102 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
1104 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
1106 if (priv->use_action_appearance)
1108 label = gtk_bin_get_child (GTK_BIN (menu_item));
1110 /* make sure label is a label, deleting it otherwise */
1111 if (label && !GTK_IS_LABEL (label))
1113 gtk_container_remove (GTK_CONTAINER (menu_item), label);
1116 /* Make sure that menu_item has a label and that any
1117 * accelerators are set */
1118 gtk_menu_item_ensure_label (menu_item);
1119 gtk_menu_item_set_use_underline (menu_item, TRUE);
1120 /* Make label point to the menu_item's label */
1121 label = gtk_bin_get_child (GTK_BIN (menu_item));
1123 if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
1125 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), NULL);
1126 gtk_accel_label_set_accel_closure (GTK_ACCEL_LABEL (label),
1127 gtk_action_get_accel_closure (action));
1130 activatable_update_label (menu_item, action);
1135 gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
1138 GtkMenuItemPrivate *priv = menu_item->priv;
1140 if (priv->action == action)
1145 gtk_action_disconnect_accelerator (priv->action);
1150 const gchar *accel_path;
1152 accel_path = gtk_action_get_accel_path (action);
1155 gtk_action_connect_accelerator (action);
1156 gtk_menu_item_set_accel_path (menu_item, accel_path);
1160 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
1162 priv->action = action;
1166 gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
1167 gboolean use_appearance)
1169 GtkMenuItemPrivate *priv = menu_item->priv;
1171 if (priv->use_action_appearance != use_appearance)
1173 priv->use_action_appearance = use_appearance;
1175 gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (menu_item), priv->action);
1181 * gtk_menu_item_set_submenu:
1182 * @menu_item: a #GtkMenuItem
1183 * @submenu: (allow-none): the submenu, or %NULL
1185 * Sets or replaces the menu item's submenu, or removes it when a %NULL
1186 * submenu is passed.
1189 gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
1192 GtkMenuItemPrivate *priv = menu_item->priv;
1194 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1195 g_return_if_fail (submenu == NULL || GTK_IS_MENU (submenu));
1197 if (priv->submenu != submenu)
1200 gtk_menu_detach (GTK_MENU (priv->submenu));
1204 priv->submenu = submenu;
1205 gtk_menu_attach_to_widget (GTK_MENU (submenu),
1206 GTK_WIDGET (menu_item),
1207 gtk_menu_item_detacher);
1210 if (gtk_widget_get_parent (GTK_WIDGET (menu_item)))
1211 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
1213 g_object_notify (G_OBJECT (menu_item), "submenu");
1218 * gtk_menu_item_get_submenu:
1219 * @menu_item: a #GtkMenuItem
1221 * Gets the submenu underneath this menu item, if any.
1222 * See gtk_menu_item_set_submenu().
1224 * Return value: (transfer none): submenu for this menu item, or %NULL if none
1227 gtk_menu_item_get_submenu (GtkMenuItem *menu_item)
1229 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
1231 return menu_item->priv->submenu;
1234 void _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
1235 GtkSubmenuPlacement placement);
1238 _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
1239 GtkSubmenuPlacement placement)
1241 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1243 menu_item->priv->submenu_placement = placement;
1247 gtk_menu_item_select (GtkMenuItem *menu_item)
1251 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1253 g_signal_emit (menu_item, menu_item_signals[SELECT], 0);
1255 /* Enable themeing of the parent menu item depending on whether
1256 * something is selected in its submenu
1258 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1259 if (GTK_IS_MENU (parent))
1261 GtkMenu *menu = GTK_MENU (parent);
1263 if (menu->priv->parent_menu_item)
1264 gtk_widget_queue_draw (GTK_WIDGET (menu->priv->parent_menu_item));
1269 gtk_menu_item_deselect (GtkMenuItem *menu_item)
1273 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1275 g_signal_emit (menu_item, menu_item_signals[DESELECT], 0);
1277 /* Enable themeing of the parent menu item depending on whether
1278 * something is selected in its submenu
1280 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1281 if (GTK_IS_MENU (parent))
1283 GtkMenu *menu = GTK_MENU (parent);
1285 if (menu->priv->parent_menu_item)
1286 gtk_widget_queue_draw (GTK_WIDGET (menu->priv->parent_menu_item));
1291 gtk_menu_item_activate (GtkMenuItem *menu_item)
1293 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1295 g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
1299 gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1302 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1304 g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
1308 gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1311 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1313 g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
1317 gtk_menu_item_size_allocate (GtkWidget *widget,
1318 GtkAllocation *allocation)
1320 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1321 GtkMenuItemPrivate *priv = menu_item->priv;
1323 GtkAllocation child_allocation;
1324 GtkTextDirection direction;
1325 GtkPackDirection pack_dir;
1326 GtkPackDirection child_pack_dir;
1330 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1331 g_return_if_fail (allocation != NULL);
1333 bin = GTK_BIN (widget);
1335 direction = gtk_widget_get_direction (widget);
1337 parent = gtk_widget_get_parent (widget);
1338 if (GTK_IS_MENU_BAR (parent))
1340 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
1341 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
1345 pack_dir = GTK_PACK_DIRECTION_LTR;
1346 child_pack_dir = GTK_PACK_DIRECTION_LTR;
1349 gtk_widget_set_allocation (widget, allocation);
1351 child = gtk_bin_get_child (bin);
1355 guint horizontal_padding;
1358 style = gtk_widget_get_style (widget);
1359 gtk_widget_style_get (widget,
1360 "horizontal-padding", &horizontal_padding,
1363 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1364 child_allocation.x = border_width + style->xthickness;
1365 child_allocation.y = border_width + style->ythickness;
1367 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
1368 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
1369 child_allocation.x += horizontal_padding;
1370 else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
1371 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
1372 child_allocation.y += horizontal_padding;
1374 child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
1375 child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
1377 if (child_pack_dir == GTK_PACK_DIRECTION_LTR ||
1378 child_pack_dir == GTK_PACK_DIRECTION_RTL)
1380 if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL))
1381 child_allocation.x += priv->toggle_size;
1382 child_allocation.width -= priv->toggle_size;
1386 if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT))
1387 child_allocation.y += priv->toggle_size;
1388 child_allocation.height -= priv->toggle_size;
1391 child_allocation.x += allocation->x;
1392 child_allocation.y += allocation->y;
1394 if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
1396 guint arrow_spacing;
1399 gtk_widget_style_get (widget,
1400 "arrow-spacing", &arrow_spacing,
1403 get_arrow_size (widget, child, &arrow_size);
1405 if (direction == GTK_TEXT_DIR_RTL)
1406 child_allocation.x += arrow_size + arrow_spacing;
1407 child_allocation.width -= arrow_size + arrow_spacing;
1410 if (child_allocation.width < 1)
1411 child_allocation.width = 1;
1413 gtk_widget_size_allocate (child, &child_allocation);
1416 if (gtk_widget_get_realized (widget))
1417 gdk_window_move_resize (priv->event_window,
1418 allocation->x, allocation->y,
1419 allocation->width, allocation->height);
1422 gtk_menu_reposition (GTK_MENU (priv->submenu));
1426 gtk_menu_item_realize (GtkWidget *widget)
1428 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1429 GtkMenuItemPrivate *priv = menu_item->priv;
1430 GtkAllocation allocation;
1432 GdkWindowAttr attributes;
1433 gint attributes_mask;
1435 gtk_widget_set_realized (widget, TRUE);
1437 window = gtk_widget_get_parent_window (widget);
1438 gtk_widget_set_window (widget, window);
1439 g_object_ref (window);
1441 gtk_widget_get_allocation (widget, &allocation);
1443 attributes.x = allocation.x;
1444 attributes.y = allocation.y;
1445 attributes.width = allocation.width;
1446 attributes.height = allocation.height;
1447 attributes.window_type = GDK_WINDOW_CHILD;
1448 attributes.wclass = GDK_INPUT_ONLY;
1449 attributes.event_mask = (gtk_widget_get_events (widget) |
1450 GDK_BUTTON_PRESS_MASK |
1451 GDK_BUTTON_RELEASE_MASK |
1452 GDK_ENTER_NOTIFY_MASK |
1453 GDK_LEAVE_NOTIFY_MASK |
1454 GDK_POINTER_MOTION_MASK);
1456 attributes_mask = GDK_WA_X | GDK_WA_Y;
1458 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1459 &attributes, attributes_mask);
1460 gdk_window_set_user_data (priv->event_window, widget);
1462 gtk_widget_style_attach (widget);
1466 gtk_menu_item_unrealize (GtkWidget *widget)
1468 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1469 GtkMenuItemPrivate *priv = menu_item->priv;
1471 gdk_window_set_user_data (priv->event_window, NULL);
1472 gdk_window_destroy (priv->event_window);
1473 priv->event_window = NULL;
1475 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize (widget);
1479 gtk_menu_item_map (GtkWidget *widget)
1481 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1482 GtkMenuItemPrivate *priv = menu_item->priv;
1484 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->map (widget);
1486 gdk_window_show (priv->event_window);
1490 gtk_menu_item_unmap (GtkWidget *widget)
1492 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1493 GtkMenuItemPrivate *priv = menu_item->priv;
1495 gdk_window_hide (priv->event_window);
1497 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unmap (widget);
1501 gtk_menu_item_enter (GtkWidget *widget,
1502 GdkEventCrossing *event)
1504 g_return_val_if_fail (event != NULL, FALSE);
1506 return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
1510 gtk_menu_item_leave (GtkWidget *widget,
1511 GdkEventCrossing *event)
1513 g_return_val_if_fail (event != NULL, FALSE);
1515 return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent*) event);
1519 gtk_menu_item_draw (GtkWidget *widget,
1522 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1523 GtkMenuItemPrivate *priv = menu_item->priv;
1524 GtkStateType state_type;
1525 GtkShadowType shadow_type, selected_shadow_type;
1527 GtkWidget *child, *parent;
1529 gint x, y, w, h, width, height;
1530 guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1532 state_type = gtk_widget_get_state (widget);
1533 style = gtk_widget_get_style (widget);
1534 window = gtk_widget_get_window (widget);
1535 width = gtk_widget_get_allocated_width (widget);
1536 height = gtk_widget_get_allocated_height (widget);
1540 w = width - border_width * 2;
1541 h = height - border_width * 2;
1543 child = gtk_bin_get_child (GTK_BIN (menu_item));
1544 parent = gtk_widget_get_parent (widget);
1546 if (child && state_type == GTK_STATE_PRELIGHT)
1548 gtk_widget_style_get (widget,
1549 "selected-shadow-type", &selected_shadow_type,
1551 gtk_paint_box (style,
1554 selected_shadow_type,
1559 if (priv->submenu && !GTK_IS_MENU_BAR (parent))
1561 gint arrow_x, arrow_y;
1563 guint horizontal_padding;
1564 GtkTextDirection direction;
1565 GtkArrowType arrow_type;
1567 direction = gtk_widget_get_direction (widget);
1569 gtk_widget_style_get (widget,
1570 "horizontal-padding", &horizontal_padding,
1573 get_arrow_size (widget, child, &arrow_size);
1575 shadow_type = GTK_SHADOW_OUT;
1576 if (state_type == GTK_STATE_PRELIGHT)
1577 shadow_type = GTK_SHADOW_IN;
1579 if (direction == GTK_TEXT_DIR_LTR)
1581 arrow_x = x + w - horizontal_padding - arrow_size;
1582 arrow_type = GTK_ARROW_RIGHT;
1586 arrow_x = x + horizontal_padding;
1587 arrow_type = GTK_ARROW_LEFT;
1590 arrow_y = y + (h - arrow_size) / 2;
1592 gtk_paint_arrow (style, cr,
1593 state_type, shadow_type,
1597 arrow_size, arrow_size);
1601 gboolean wide_separators;
1602 gint separator_height;
1603 guint horizontal_padding;
1605 gtk_widget_style_get (widget,
1606 "wide-separators", &wide_separators,
1607 "separator-height", &separator_height,
1608 "horizontal-padding", &horizontal_padding,
1611 if (wide_separators)
1612 gtk_paint_box (style, cr,
1613 GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
1614 widget, "hseparator",
1615 horizontal_padding + style->xthickness,
1616 (height - separator_height - style->ythickness) / 2,
1617 width - 2 * (horizontal_padding + style->xthickness),
1620 gtk_paint_hline (style, cr,
1621 GTK_STATE_NORMAL, widget, "menuitem",
1622 horizontal_padding + style->xthickness,
1623 width - horizontal_padding - style->xthickness - 1,
1624 (height - style->ythickness) / 2);
1627 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->draw (widget, cr);
1633 gtk_real_menu_item_select (GtkMenuItem *menu_item)
1635 GtkMenuItemPrivate *priv = menu_item->priv;
1636 gboolean touchscreen_mode;
1638 g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_item)),
1639 "gtk-touchscreen-mode", &touchscreen_mode,
1642 if (!touchscreen_mode && priv->submenu &&
1643 (!gtk_widget_get_mapped (priv->submenu) ||
1644 GTK_MENU (priv->submenu)->priv->tearoff_active))
1646 _gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1649 gtk_widget_set_state_flags (GTK_WIDGET (menu_item),
1650 GTK_STATE_FLAG_PRELIGHT, FALSE);
1651 gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1655 gtk_real_menu_item_deselect (GtkMenuItem *menu_item)
1657 GtkMenuItemPrivate *priv = menu_item->priv;
1660 _gtk_menu_item_popdown_submenu (GTK_WIDGET (menu_item));
1662 gtk_widget_unset_state_flags (GTK_WIDGET (menu_item),
1663 GTK_STATE_FLAG_PRELIGHT);
1664 gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1668 gtk_menu_item_mnemonic_activate (GtkWidget *widget,
1669 gboolean group_cycling)
1673 parent = gtk_widget_get_parent (widget);
1675 if (GTK_IS_MENU_SHELL (parent))
1676 _gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (parent), TRUE);
1678 if (group_cycling &&
1680 GTK_IS_MENU_SHELL (parent) &&
1681 GTK_MENU_SHELL (parent)->priv->active)
1683 gtk_menu_shell_select_item (GTK_MENU_SHELL (parent), widget);
1686 g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0);
1692 gtk_real_menu_item_activate (GtkMenuItem *menu_item)
1694 GtkMenuItemPrivate *priv = menu_item->priv;
1697 gtk_action_activate (priv->action);
1702 gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
1704 GtkMenuItemPrivate *priv = menu_item->priv;
1708 widget = GTK_WIDGET (menu_item);
1709 parent = gtk_widget_get_parent (widget);
1711 if (parent && GTK_IS_MENU_SHELL (parent))
1713 GtkMenuShell *menu_shell = GTK_MENU_SHELL (parent);
1715 if (priv->submenu == NULL)
1716 gtk_menu_shell_activate_item (menu_shell, widget, TRUE);
1719 _gtk_menu_shell_activate (menu_shell);
1721 gtk_menu_shell_select_item (menu_shell, widget);
1722 _gtk_menu_item_popup_submenu (widget, FALSE);
1724 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->submenu), TRUE);
1730 gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1733 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1739 gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1742 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1744 menu_item->priv->toggle_size = allocation;
1748 gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
1753 gtk_menu_item_ensure_label (menu_item);
1755 child = gtk_bin_get_child (GTK_BIN (menu_item));
1756 if (GTK_IS_LABEL (child))
1758 gtk_label_set_label (GTK_LABEL (child), label ? label : "");
1760 g_object_notify (G_OBJECT (menu_item), "label");
1764 static G_CONST_RETURN gchar *
1765 gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
1769 gtk_menu_item_ensure_label (menu_item);
1771 child = gtk_bin_get_child (GTK_BIN (menu_item));
1772 if (GTK_IS_LABEL (child))
1773 return gtk_label_get_label (GTK_LABEL (child));
1779 free_timeval (GTimeVal *val)
1781 g_slice_free (GTimeVal, val);
1785 gtk_menu_item_real_popup_submenu (GtkWidget *widget,
1786 gboolean remember_exact_time)
1788 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1789 GtkMenuItemPrivate *priv = menu_item->priv;
1792 parent = gtk_widget_get_parent (widget);
1794 if (gtk_widget_is_sensitive (priv->submenu) && parent)
1796 gboolean take_focus;
1797 GtkMenuPositionFunc menu_position_func;
1799 take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent));
1800 gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (priv->submenu), take_focus);
1802 if (remember_exact_time)
1804 GTimeVal *popup_time = g_slice_new0 (GTimeVal);
1806 g_get_current_time (popup_time);
1808 g_object_set_data_full (G_OBJECT (priv->submenu),
1809 "gtk-menu-exact-popup-time", popup_time,
1810 (GDestroyNotify) free_timeval);
1814 g_object_set_data (G_OBJECT (priv->submenu),
1815 "gtk-menu-exact-popup-time", NULL);
1818 /* gtk_menu_item_position_menu positions the submenu from the
1819 * menuitems position. If the menuitem doesn't have a window,
1820 * that doesn't work. In that case we use the default
1821 * positioning function instead which places the submenu at the
1824 if (gtk_widget_get_window (widget))
1825 menu_position_func = gtk_menu_item_position_menu;
1827 menu_position_func = NULL;
1829 gtk_menu_popup (GTK_MENU (priv->submenu),
1834 GTK_MENU_SHELL (parent)->priv->button,
1838 /* Enable themeing of the parent menu item depending on whether
1839 * its submenu is shown or not.
1841 gtk_widget_queue_draw (widget);
1845 gtk_menu_item_popup_timeout (gpointer data)
1847 GtkMenuItem *menu_item = GTK_MENU_ITEM (data);
1848 GtkMenuItemPrivate *priv = menu_item->priv;
1851 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1853 if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->priv->active) ||
1854 (GTK_IS_MENU (parent) && GTK_MENU (parent)->priv->torn_off))
1856 gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1857 if (priv->timer_from_keypress && priv->submenu)
1858 GTK_MENU_SHELL (priv->submenu)->priv->ignore_enter = TRUE;
1867 get_popup_delay (GtkWidget *widget)
1871 parent = gtk_widget_get_parent (widget);
1872 if (GTK_IS_MENU_SHELL (parent))
1874 return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (parent));
1880 g_object_get (gtk_widget_get_settings (widget),
1881 "gtk-menu-popup-delay", &popup_delay,
1889 _gtk_menu_item_popup_submenu (GtkWidget *widget,
1890 gboolean with_delay)
1892 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1893 GtkMenuItemPrivate *priv = menu_item->priv;
1897 g_source_remove (priv->timer);
1904 gint popup_delay = get_popup_delay (widget);
1906 if (popup_delay > 0)
1908 GdkEvent *event = gtk_get_current_event ();
1910 priv->timer = gdk_threads_add_timeout (popup_delay,
1911 gtk_menu_item_popup_timeout,
1915 event->type != GDK_BUTTON_PRESS &&
1916 event->type != GDK_ENTER_NOTIFY)
1917 priv->timer_from_keypress = TRUE;
1919 priv->timer_from_keypress = FALSE;
1922 gdk_event_free (event);
1928 gtk_menu_item_real_popup_submenu (widget, FALSE);
1932 _gtk_menu_item_popdown_submenu (GtkWidget *widget)
1934 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1935 GtkMenuItemPrivate *priv = menu_item->priv;
1939 g_object_set_data (G_OBJECT (priv->submenu),
1940 "gtk-menu-exact-popup-time", NULL);
1944 g_source_remove (priv->timer);
1948 gtk_menu_popdown (GTK_MENU (priv->submenu));
1950 gtk_widget_queue_draw (widget);
1955 get_offsets (GtkMenu *menu,
1956 gint *horizontal_offset,
1957 gint *vertical_offset)
1959 gint vertical_padding;
1960 gint horizontal_padding;
1962 gtk_widget_style_get (GTK_WIDGET (menu),
1963 "horizontal-offset", horizontal_offset,
1964 "vertical-offset", vertical_offset,
1965 "horizontal-padding", &horizontal_padding,
1966 "vertical-padding", &vertical_padding,
1969 *vertical_offset -= gtk_widget_get_style (GTK_WIDGET (menu))->ythickness;
1970 *vertical_offset -= vertical_padding;
1971 *horizontal_offset += horizontal_padding;
1975 gtk_menu_item_position_menu (GtkMenu *menu,
1981 GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data);
1982 GtkMenuItemPrivate *priv = menu_item->priv;
1983 GtkAllocation allocation;
1985 GtkMenuItem *parent_menu_item;
1986 GtkRequisition requisition;
1989 gint twidth, theight;
1991 GtkTextDirection direction;
1992 GdkRectangle monitor;
1994 gint horizontal_offset;
1995 gint vertical_offset;
1996 gint parent_xthickness;
1997 gint available_left, available_right;
1999 g_return_if_fail (menu != NULL);
2000 g_return_if_fail (x != NULL);
2001 g_return_if_fail (y != NULL);
2003 widget = GTK_WIDGET (user_data);
2008 direction = gtk_widget_get_direction (widget);
2010 gtk_widget_get_preferred_size (GTK_WIDGET (menu), &requisition, NULL);
2011 twidth = requisition.width;
2012 theight = requisition.height;
2014 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
2015 monitor_num = gdk_screen_get_monitor_at_window (screen, priv->event_window);
2016 if (monitor_num < 0)
2018 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
2020 if (!gdk_window_get_origin (gtk_widget_get_window (widget), &tx, &ty))
2022 g_warning ("Menu not on screen");
2026 gtk_widget_get_allocation (widget, &allocation);
2031 get_offsets (menu, &horizontal_offset, &vertical_offset);
2033 available_left = tx - monitor.x;
2034 available_right = monitor.x + monitor.width - (tx + allocation.width);
2036 parent = gtk_widget_get_parent (widget);
2037 if (GTK_IS_MENU_BAR (parent))
2039 priv->from_menubar = TRUE;
2041 else if (GTK_IS_MENU (parent))
2043 if (GTK_MENU (parent)->priv->parent_menu_item)
2044 priv->from_menubar = GTK_MENU_ITEM (GTK_MENU (parent)->priv->parent_menu_item)->priv->from_menubar;
2046 priv->from_menubar = FALSE;
2050 priv->from_menubar = FALSE;
2053 switch (priv->submenu_placement)
2055 case GTK_TOP_BOTTOM:
2056 if (direction == GTK_TEXT_DIR_LTR)
2057 priv->submenu_direction = GTK_DIRECTION_RIGHT;
2060 priv->submenu_direction = GTK_DIRECTION_LEFT;
2061 tx += allocation.width - twidth;
2063 if ((ty + allocation.height + theight) <= monitor.y + monitor.height)
2064 ty += allocation.height;
2065 else if ((ty - theight) >= monitor.y)
2067 else if (monitor.y + monitor.height - (ty + allocation.height) > ty)
2068 ty += allocation.height;
2073 case GTK_LEFT_RIGHT:
2074 if (GTK_IS_MENU (parent))
2075 parent_menu_item = GTK_MENU_ITEM (GTK_MENU (parent)->priv->parent_menu_item);
2077 parent_menu_item = NULL;
2079 parent_xthickness = gtk_widget_get_style (parent)->xthickness;
2081 if (parent_menu_item && !GTK_MENU (parent)->priv->torn_off)
2083 priv->submenu_direction = parent_menu_item->priv->submenu_direction;
2087 if (direction == GTK_TEXT_DIR_LTR)
2088 priv->submenu_direction = GTK_DIRECTION_RIGHT;
2090 priv->submenu_direction = GTK_DIRECTION_LEFT;
2093 switch (priv->submenu_direction)
2095 case GTK_DIRECTION_LEFT:
2096 if (tx - twidth - parent_xthickness - horizontal_offset >= monitor.x ||
2097 available_left >= available_right)
2098 tx -= twidth + parent_xthickness + horizontal_offset;
2101 priv->submenu_direction = GTK_DIRECTION_RIGHT;
2102 tx += allocation.width + parent_xthickness + horizontal_offset;
2106 case GTK_DIRECTION_RIGHT:
2107 if (tx + allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
2108 available_right >= available_left)
2109 tx += allocation.width + parent_xthickness + horizontal_offset;
2112 priv->submenu_direction = GTK_DIRECTION_LEFT;
2113 tx -= twidth + parent_xthickness + horizontal_offset;
2118 ty += vertical_offset;
2120 /* If the height of the menu doesn't fit we move it upward. */
2121 ty = CLAMP (ty, monitor.y, MAX (monitor.y, monitor.y + monitor.height - theight));
2125 /* If we have negative, tx, here it is because we can't get
2126 * the menu all the way on screen. Favor the left portion.
2128 *x = CLAMP (tx, monitor.x, MAX (monitor.x, monitor.x + monitor.width - twidth));
2131 gtk_menu_set_monitor (menu, monitor_num);
2133 if (!gtk_widget_get_visible (menu->priv->toplevel))
2135 gtk_window_set_type_hint (GTK_WINDOW (menu->priv->toplevel), priv->from_menubar?
2136 GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
2141 * gtk_menu_item_set_right_justified:
2142 * @menu_item: a #GtkMenuItem.
2143 * @right_justified: if %TRUE the menu item will appear at the
2144 * far right if added to a menu bar
2146 * Sets whether the menu item appears justified at the right
2147 * side of a menu bar. This was traditionally done for "Help"
2148 * menu items, but is now considered a bad idea. (If the widget
2149 * layout is reversed for a right-to-left language like Hebrew
2150 * or Arabic, right-justified-menu-items appear at the left.)
2153 gtk_menu_item_set_right_justified (GtkMenuItem *menu_item,
2154 gboolean right_justified)
2156 GtkMenuItemPrivate *priv = menu_item->priv;
2158 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2160 right_justified = right_justified != FALSE;
2162 if (priv->right_justify != right_justified)
2164 priv->right_justify = right_justified;
2165 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
2170 * gtk_menu_item_get_right_justified:
2171 * @menu_item: a #GtkMenuItem
2173 * Gets whether the menu item appears justified at the right
2174 * side of the menu bar.
2176 * Return value: %TRUE if the menu item will appear at the
2177 * far right if added to a menu bar.
2180 gtk_menu_item_get_right_justified (GtkMenuItem *menu_item)
2182 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2184 return menu_item->priv->right_justify;
2189 gtk_menu_item_show_all (GtkWidget *widget)
2191 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
2192 GtkMenuItemPrivate *priv = menu_item->priv;
2194 /* show children including submenu */
2196 gtk_widget_show_all (priv->submenu);
2197 gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_show_all, NULL);
2199 gtk_widget_show (widget);
2203 gtk_menu_item_can_activate_accel (GtkWidget *widget,
2208 parent = gtk_widget_get_parent (widget);
2210 /* Chain to the parent GtkMenu for further checks */
2211 return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) &&
2212 parent && gtk_widget_can_activate_accel (parent, signal_id));
2216 gtk_menu_item_accel_name_foreach (GtkWidget *widget,
2219 const gchar **path_p = data;
2223 if (GTK_IS_LABEL (widget))
2225 *path_p = gtk_label_get_text (GTK_LABEL (widget));
2226 if (*path_p && (*path_p)[0] == 0)
2229 else if (GTK_IS_CONTAINER (widget))
2230 gtk_container_foreach (GTK_CONTAINER (widget),
2231 gtk_menu_item_accel_name_foreach,
2237 gtk_menu_item_parent_set (GtkWidget *widget,
2238 GtkWidget *previous_parent)
2240 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
2244 parent = gtk_widget_get_parent (widget);
2245 menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
2248 _gtk_menu_item_refresh_accel_path (menu_item,
2249 menu->priv->accel_path,
2250 menu->priv->accel_group,
2253 if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set)
2254 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent);
2258 _gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item,
2259 const gchar *prefix,
2260 GtkAccelGroup *accel_group,
2261 gboolean group_changed)
2263 GtkMenuItemPrivate *priv = menu_item->priv;
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 = priv->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 = priv->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
2309 * item's functionality, or %NULL to unset the current path.
2311 * Set the accelerator path on @menu_item, through which runtime
2312 * changes of the menu item's accelerator caused by the user can be
2313 * identified and saved to persistent storage (see gtk_accel_map_save()
2314 * on this). To set up a default accelerator for this menu item, call
2315 * gtk_accel_map_add_entry() with the same @accel_path. See also
2316 * gtk_accel_map_add_entry() on the specifics of accelerator paths,
2317 * and gtk_menu_set_accel_path() for a more convenient variant of
2320 * This function is basically a convenience wrapper that handles
2321 * calling gtk_widget_set_accel_path() with the appropriate accelerator
2322 * group for the menu item.
2324 * Note that you do need to set an accelerator on the parent menu with
2325 * gtk_menu_set_accel_group() for this to work.
2327 * Note that @accel_path string will be stored in a #GQuark.
2328 * Therefore, if you pass a static string, you can save some memory
2329 * by interning it first with g_intern_static_string().
2332 gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
2333 const gchar *accel_path)
2335 GtkMenuItemPrivate *priv = menu_item->priv;
2339 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2340 g_return_if_fail (accel_path == NULL ||
2341 (accel_path[0] == '<' && strchr (accel_path, '/')));
2343 widget = GTK_WIDGET (menu_item);
2345 /* store new path */
2346 priv->accel_path = (char*)g_intern_string (accel_path);
2348 /* forget accelerators associated with old path */
2349 gtk_widget_set_accel_path (widget, NULL, NULL);
2351 /* install accelerators associated with new path */
2352 parent = gtk_widget_get_parent (widget);
2353 if (GTK_IS_MENU (parent))
2355 GtkMenu *menu = GTK_MENU (parent);
2357 if (menu->priv->accel_group)
2358 _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
2360 menu->priv->accel_group,
2366 * gtk_menu_item_get_accel_path
2367 * @menu_item: a valid #GtkMenuItem
2369 * Retrieve the accelerator path that was previously set on @menu_item.
2371 * See gtk_menu_item_set_accel_path() for details.
2373 * Returns: the accelerator path corresponding to this menu
2374 * item's functionality, or %NULL if not set
2378 G_CONST_RETURN gchar *
2379 gtk_menu_item_get_accel_path (GtkMenuItem *menu_item)
2381 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2383 return menu_item->priv->accel_path;
2387 gtk_menu_item_forall (GtkContainer *container,
2388 gboolean include_internals,
2389 GtkCallback callback,
2390 gpointer callback_data)
2394 g_return_if_fail (GTK_IS_MENU_ITEM (container));
2395 g_return_if_fail (callback != NULL);
2397 child = gtk_bin_get_child (GTK_BIN (container));
2399 callback (child, callback_data);
2403 _gtk_menu_item_is_selectable (GtkWidget *menu_item)
2405 if ((!gtk_bin_get_child (GTK_BIN (menu_item)) &&
2406 G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
2407 GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
2408 !gtk_widget_is_sensitive (menu_item) ||
2409 !gtk_widget_get_visible (menu_item))
2416 gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
2418 GtkWidget *accel_label;
2420 if (!gtk_bin_get_child (GTK_BIN (menu_item)))
2422 accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
2423 gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
2425 gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
2426 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label),
2427 GTK_WIDGET (menu_item));
2428 gtk_widget_show (accel_label);
2433 * gtk_menu_item_set_label:
2434 * @menu_item: a #GtkMenuItem
2435 * @label: the text you want to set
2437 * Sets @text on the @menu_item label
2442 gtk_menu_item_set_label (GtkMenuItem *menu_item,
2445 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2447 GTK_MENU_ITEM_GET_CLASS (menu_item)->set_label (menu_item, label);
2451 * gtk_menu_item_get_label:
2452 * @menu_item: a #GtkMenuItem
2454 * Sets @text on the @menu_item label
2456 * Returns: The text in the @menu_item label. This is the internal
2457 * string used by the label, and must not be modified.
2461 G_CONST_RETURN gchar *
2462 gtk_menu_item_get_label (GtkMenuItem *menu_item)
2464 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2466 return GTK_MENU_ITEM_GET_CLASS (menu_item)->get_label (menu_item);
2470 * gtk_menu_item_set_use_underline:
2471 * @menu_item: a #GtkMenuItem
2472 * @setting: %TRUE if underlines in the text indicate mnemonics
2474 * If true, an underline in the text indicates the next character
2475 * should be used for the mnemonic accelerator key.
2480 gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
2485 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2487 gtk_menu_item_ensure_label (menu_item);
2489 child = gtk_bin_get_child (GTK_BIN (menu_item));
2490 if (GTK_IS_LABEL (child))
2492 gtk_label_set_use_underline (GTK_LABEL (child), setting);
2494 g_object_notify (G_OBJECT (menu_item), "use-underline");
2499 * gtk_menu_item_get_use_underline:
2500 * @menu_item: a #GtkMenuItem
2502 * Checks if an underline in the text indicates the next character
2503 * should be used for the mnemonic accelerator key.
2505 * Return value: %TRUE if an embedded underline in the label
2506 * indicates the mnemonic accelerator key.
2511 gtk_menu_item_get_use_underline (GtkMenuItem *menu_item)
2515 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2517 gtk_menu_item_ensure_label (menu_item);
2519 child = gtk_bin_get_child (GTK_BIN (menu_item));
2520 if (GTK_IS_LABEL (child))
2521 return gtk_label_get_use_underline (GTK_LABEL (child));
2527 gtk_menu_item_set_reserve_indicator (GtkMenuItem *menu_item,
2530 GtkMenuItemPrivate *priv;
2532 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2534 priv = menu_item->priv;
2536 if (priv->reserve_indicator != reserve)
2538 priv->reserve_indicator = reserve;
2539 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
2544 gtk_menu_item_get_reserve_indicator (GtkMenuItem *menu_item)
2546 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2548 return menu_item->priv->reserve_indicator;