* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#define GTK_MENU_INTERNALS
-
#include "config.h"
#include <string.h>
#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkmenubar.h"
-#include "gtkmenuitem.h"
+#include "gtkmenuprivate.h"
#include "gtkseparatormenuitem.h"
#include "gtkprivate.h"
+#include "gtkbuildable.h"
+#include "gtkactivatable.h"
#include "gtkintl.h"
-#include "gtkalias.h"
-#define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
+
+typedef struct {
+ GtkAction *action;
+ gboolean use_action_appearance;
+} GtkMenuItemPrivate;
enum {
ACTIVATE,
ACTIVATE_ITEM,
TOGGLE_SIZE_REQUEST,
TOGGLE_SIZE_ALLOCATE,
+ SELECT,
+ DESELECT,
LAST_SIGNAL
};
PROP_0,
PROP_RIGHT_JUSTIFIED,
PROP_SUBMENU,
- PROP_ACCEL_PATH
+ PROP_ACCEL_PATH,
+ PROP_LABEL,
+ PROP_USE_UNDERLINE,
+
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
};
+static void gtk_menu_item_dispose (GObject *object);
static void gtk_menu_item_set_property (GObject *object,
guint prop_id,
const GValue *value,
guint prop_id,
GValue *value,
GParamSpec *pspec);
-static void gtk_menu_item_destroy (GtkObject *object);
-static void gtk_menu_item_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
+static void gtk_menu_item_destroy (GtkWidget *widget);
static void gtk_menu_item_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_menu_item_realize (GtkWidget *widget);
static void gtk_menu_item_unrealize (GtkWidget *widget);
static void gtk_menu_item_map (GtkWidget *widget);
static void gtk_menu_item_unmap (GtkWidget *widget);
-static void gtk_menu_item_paint (GtkWidget *widget,
- GdkRectangle *area);
-static gint gtk_menu_item_expose (GtkWidget *widget,
- GdkEventExpose *event);
+static gboolean gtk_menu_item_enter (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean gtk_menu_item_leave (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean gtk_menu_item_draw (GtkWidget *widget,
+ cairo_t *cr);
static void gtk_menu_item_parent_set (GtkWidget *widget,
GtkWidget *previous_parent);
-static void gtk_real_menu_item_select (GtkItem *item);
-static void gtk_real_menu_item_deselect (GtkItem *item);
+static void gtk_real_menu_item_select (GtkMenuItem *item);
+static void gtk_real_menu_item_deselect (GtkMenuItem *item);
+static void gtk_real_menu_item_activate (GtkMenuItem *item);
static void gtk_real_menu_item_activate_item (GtkMenuItem *item);
static void gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
gint *requisition);
static gboolean gtk_menu_item_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
+static void gtk_menu_item_ensure_label (GtkMenuItem *menu_item);
static gint gtk_menu_item_popup_timeout (gpointer data);
static void gtk_menu_item_position_menu (GtkMenu *menu,
gint *x,
static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
guint signal_id);
+static void gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
+ const gchar *label);
+static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
+
+static void gtk_menu_item_get_preferred_width (GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size);
+static void gtk_menu_item_get_preferred_height (GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size);
+static void gtk_menu_item_get_preferred_height_for_width (GtkWidget *widget,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size);
+
+static void gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface);
+static void gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type);
+static void gtk_menu_item_buildable_custom_finished(GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data);
+
+static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface);
+static void gtk_menu_item_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
+ GtkAction *action);
+static void gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
+ GtkAction *action);
+static void gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
+ gboolean use_appearance);
+
static guint menu_item_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM)
+static GtkBuildableIface *parent_buildable_iface;
+
+G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_menu_item_buildable_interface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_menu_item_activatable_interface_init))
+
+#define GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
static void
gtk_menu_item_class_init (GtkMenuItemClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
- GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
+ gobject_class->dispose = gtk_menu_item_dispose;
gobject_class->set_property = gtk_menu_item_set_property;
gobject_class->get_property = gtk_menu_item_get_property;
- object_class->destroy = gtk_menu_item_destroy;
-
- widget_class->size_request = gtk_menu_item_size_request;
+ widget_class->destroy = gtk_menu_item_destroy;
widget_class->size_allocate = gtk_menu_item_size_allocate;
- widget_class->expose_event = gtk_menu_item_expose;
+ widget_class->draw = gtk_menu_item_draw;
widget_class->realize = gtk_menu_item_realize;
widget_class->unrealize = gtk_menu_item_unrealize;
widget_class->map = gtk_menu_item_map;
widget_class->unmap = gtk_menu_item_unmap;
+ widget_class->enter_notify_event = gtk_menu_item_enter;
+ widget_class->leave_notify_event = gtk_menu_item_leave;
widget_class->show_all = gtk_menu_item_show_all;
widget_class->hide_all = gtk_menu_item_hide_all;
widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
widget_class->parent_set = gtk_menu_item_parent_set;
widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
+ widget_class->get_preferred_width = gtk_menu_item_get_preferred_width;
+ widget_class->get_preferred_height = gtk_menu_item_get_preferred_height;
+ widget_class->get_preferred_height_for_width = gtk_menu_item_get_preferred_height_for_width;
container_class->forall = gtk_menu_item_forall;
- item_class->select = gtk_real_menu_item_select;
- item_class->deselect = gtk_real_menu_item_deselect;
-
- klass->activate = NULL;
- klass->activate_item = gtk_real_menu_item_activate_item;
- klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
+ klass->activate = gtk_real_menu_item_activate;
+ klass->activate_item = gtk_real_menu_item_activate_item;
+ klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
+ klass->set_label = gtk_real_menu_item_set_label;
+ klass->get_label = gtk_real_menu_item_get_label;
+ klass->select = gtk_real_menu_item_select;
+ klass->deselect = gtk_real_menu_item_deselect;
klass->hide_on_activate = TRUE;
widget_class->activate_signal = menu_item_signals[ACTIVATE];
menu_item_signals[ACTIVATE_ITEM] =
- g_signal_new (I_("activate_item"),
+ g_signal_new (I_("activate-item"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkMenuItemClass, activate_item),
G_TYPE_NONE, 0);
menu_item_signals[TOGGLE_SIZE_REQUEST] =
- g_signal_new (I_("toggle_size_request"),
+ g_signal_new (I_("toggle-size-request"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_request),
G_TYPE_POINTER);
menu_item_signals[TOGGLE_SIZE_ALLOCATE] =
- g_signal_new (I_("toggle_size_allocate"),
+ g_signal_new (I_("toggle-size-allocate"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_allocate),
NULL, NULL,
- _gtk_marshal_NONE__INT,
+ _gtk_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
+ menu_item_signals[SELECT] =
+ g_signal_new (I_("select"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkMenuItemClass, select),
+ NULL, NULL,
+ _gtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ menu_item_signals[DESELECT] =
+ g_signal_new (I_("deselect"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkMenuItemClass, deselect),
+ NULL, NULL,
+ _gtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
/**
* GtkMenuItem:right-justified:
*
P_("The submenu attached to the menu item, or NULL if it has none"),
GTK_TYPE_MENU,
GTK_PARAM_READWRITE));
+
/**
* GtkMenuItem:accel-path:
NULL,
GTK_PARAM_READWRITE));
+ /**
+ * GtkMenuItem:label:
+ *
+ * The text for the child label.
+ *
+ * Since: 2.16
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_LABEL,
+ g_param_spec_string ("label",
+ P_("Label"),
+ P_("The text for the child label"),
+ "",
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkMenuItem:use-underline:
+ *
+ * %TRUE if underlines in the text indicate mnemonics
+ *
+ * Since: 2.16
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_USE_UNDERLINE,
+ g_param_spec_boolean ("use-underline",
+ P_("Use underline"),
+ P_("If set, an underline in the text indicates "
+ "the next character should be used for the "
+ "mnemonic accelerator key"),
+ FALSE,
+ GTK_PARAM_READWRITE));
+
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+
gtk_widget_class_install_style_property_parser (widget_class,
g_param_spec_enum ("selected-shadow-type",
"Selected Shadow Type",
P_("The minimum desired width of the menu item in characters"),
0, G_MAXINT, 12,
GTK_PARAM_READABLE));
+
+ g_type_class_add_private (klass, sizeof (GtkMenuItemPrivate));
}
static void
gtk_menu_item_init (GtkMenuItem *menu_item)
{
- GTK_WIDGET_SET_FLAGS (menu_item, GTK_NO_WINDOW);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ gtk_widget_set_has_window (GTK_WIDGET (menu_item), FALSE);
+
+ priv->action = NULL;
+ priv->use_action_appearance = TRUE;
menu_item->submenu = NULL;
menu_item->toggle_size = 0;
GtkWidget*
gtk_menu_item_new_with_label (const gchar *label)
{
- GtkWidget *menu_item;
- GtkWidget *accel_label;
-
- menu_item = gtk_menu_item_new ();
- accel_label = gtk_accel_label_new (label);
- gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
-
- gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
- gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), menu_item);
- gtk_widget_show (accel_label);
-
- return menu_item;
+ return g_object_new (GTK_TYPE_MENU_ITEM,
+ "label", label,
+ NULL);
}
GtkWidget*
gtk_menu_item_new_with_mnemonic (const gchar *label)
{
- GtkWidget *menu_item;
- GtkWidget *accel_label;
-
- menu_item = gtk_menu_item_new ();
- accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
- gtk_label_set_text_with_mnemonic (GTK_LABEL (accel_label), label);
- gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
+ return g_object_new (GTK_TYPE_MENU_ITEM,
+ "use-underline", TRUE,
+ "label", label,
+ NULL);
+}
- gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
- gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), menu_item);
- gtk_widget_show (accel_label);
+static void
+gtk_menu_item_dispose (GObject *object)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
- return menu_item;
+ if (priv->action)
+ {
+ gtk_action_disconnect_accelerator (priv->action);
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
+
+ priv->action = NULL;
+ }
+ G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
}
static void
case PROP_ACCEL_PATH:
gtk_menu_item_set_accel_path (menu_item, g_value_get_string (value));
break;
-
+ case PROP_LABEL:
+ gtk_menu_item_set_label (menu_item, g_value_get_string (value));
+ break;
+ case PROP_USE_UNDERLINE:
+ gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
+ break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
GParamSpec *pspec)
{
GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
switch (prop_id)
{
case PROP_ACCEL_PATH:
g_value_set_string (value, gtk_menu_item_get_accel_path (menu_item));
break;
-
+ case PROP_LABEL:
+ g_value_set_string (value, gtk_menu_item_get_label (menu_item));
+ break;
+ case PROP_USE_UNDERLINE:
+ g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
+ break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, priv->action);
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, priv->use_action_appearance);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
static void
-gtk_menu_item_destroy (GtkObject *object)
+gtk_menu_item_destroy (GtkWidget *widget)
{
- GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
if (menu_item->submenu)
gtk_widget_destroy (menu_item->submenu);
- GTK_OBJECT_CLASS (gtk_menu_item_parent_class)->destroy (object);
+ GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->destroy (widget);
}
static void
menu_item->submenu = NULL;
}
+static void
+get_arrow_size (GtkWidget *widget,
+ GtkWidget *child,
+ gint *size)
+{
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ gfloat arrow_scaling;
+
+ g_assert (size);
+
+ gtk_widget_style_get (widget,
+ "arrow-scaling", &arrow_scaling,
+ NULL);
+
+ context = gtk_widget_get_pango_context (child);
+ metrics = pango_context_get_metrics (context,
+ gtk_widget_get_style (child)->font_desc,
+ pango_context_get_language (context));
+
+ *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+ pango_font_metrics_get_descent (metrics)));
+
+ pango_font_metrics_unref (metrics);
+
+ *size = *size * arrow_scaling;
+}
+
+
+static void
+gtk_menu_item_accel_width_foreach (GtkWidget *widget,
+ gpointer data)
+{
+ guint *width = data;
+
+ if (GTK_IS_ACCEL_LABEL (widget))
+ {
+ guint w;
+
+ w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
+ *width = MAX (*width, w);
+ }
+ else if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_menu_item_accel_width_foreach,
+ data);
+}
+
+static gint
+get_minimum_width (GtkWidget *widget)
+{
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ gint width;
+ gint width_chars;
+
+ context = gtk_widget_get_pango_context (widget);
+ metrics = pango_context_get_metrics (context,
+ gtk_widget_get_style (widget)->font_desc,
+ pango_context_get_language (context));
+
+ width = pango_font_metrics_get_approximate_char_width (metrics);
+
+ pango_font_metrics_unref (metrics);
+
+ gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
+
+ return PANGO_PIXELS (width_chars * width);
+}
+
+static void
+gtk_menu_item_get_preferred_width (GtkWidget *request,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkMenuItem *menu_item;
+ GtkBin *bin;
+ GtkWidget *child, *widget = GTK_WIDGET (request);
+ GtkWidget *parent;
+ guint accel_width;
+ guint horizontal_padding;
+ guint border_width;
+ GtkPackDirection pack_dir;
+ GtkPackDirection child_pack_dir;
+ gint min_width, nat_width;
+
+ min_width = nat_width = 0;
+
+ gtk_widget_style_get (widget,
+ "horizontal-padding", &horizontal_padding,
+ NULL);
+
+ bin = GTK_BIN (widget);
+ menu_item = GTK_MENU_ITEM (widget);
+ parent = gtk_widget_get_parent (widget);
+
+ if (GTK_IS_MENU_BAR (parent))
+ {
+ pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
+ child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
+ }
+ else
+ {
+ pack_dir = GTK_PACK_DIRECTION_LTR;
+ child_pack_dir = GTK_PACK_DIRECTION_LTR;
+ }
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+ min_width = (border_width + gtk_widget_get_style (widget)->xthickness) * 2;
+
+ if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
+ (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
+ min_width += 2 * horizontal_padding;
+
+ nat_width = min_width;
+
+ child = gtk_bin_get_child (bin);
+
+ if (child != NULL && gtk_widget_get_visible (child))
+ {
+ gint child_min, child_nat;
+
+ gtk_widget_get_preferred_width (child, &child_min, &child_nat);
+
+ if (menu_item->submenu && menu_item->show_submenu_indicator)
+ {
+ guint arrow_spacing;
+ gint arrow_size;
+
+ gtk_widget_style_get (widget,
+ "arrow-spacing", &arrow_spacing,
+ NULL);
+
+ get_arrow_size (widget, child, &arrow_size);
+
+ min_width += arrow_size;
+ min_width += arrow_spacing;
+
+ min_width = MAX (min_width, get_minimum_width (widget));
+
+ nat_width = min_width;
+ }
+
+
+ min_width += child_min;
+ nat_width += child_nat;
+
+
+ }
+
+ accel_width = 0;
+ gtk_container_foreach (GTK_CONTAINER (menu_item),
+ gtk_menu_item_accel_width_foreach,
+ &accel_width);
+ menu_item->accelerator_width = accel_width;
+
+ if (minimum_size)
+ *minimum_size = min_width;
+
+ if (natural_size)
+ *natural_size = nat_width;
+}
+
+static void
+gtk_menu_item_get_preferred_height (GtkWidget *request,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkMenuItem *menu_item;
+ GtkBin *bin;
+ GtkStyle *style;
+ GtkWidget *child, *widget = GTK_WIDGET (request);
+ GtkWidget *parent;
+ guint accel_width;
+ guint horizontal_padding;
+ guint border_width;
+ GtkPackDirection pack_dir;
+ GtkPackDirection child_pack_dir;
+ gint min_height, nat_height;
+
+ min_height = nat_height = 0;
+
+ style = gtk_widget_get_style (widget);
+
+ gtk_widget_style_get (widget,
+ "horizontal-padding", &horizontal_padding,
+ NULL);
+
+ bin = GTK_BIN (widget);
+ menu_item = GTK_MENU_ITEM (widget);
+ parent = gtk_widget_get_parent (widget);
+
+ if (GTK_IS_MENU_BAR (parent))
+ {
+ pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
+ child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
+ }
+ else
+ {
+ pack_dir = GTK_PACK_DIRECTION_LTR;
+ child_pack_dir = GTK_PACK_DIRECTION_LTR;
+ }
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ min_height = (border_width + style->ythickness) * 2;
+
+ if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
+ (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
+ min_height += 2 * horizontal_padding;
+
+ nat_height = min_height;
+
+ child = gtk_bin_get_child (bin);
+
+ if (child != NULL && gtk_widget_get_visible (child))
+ {
+ gint child_min, child_nat;
+
+ gtk_widget_get_preferred_height (child, &child_min, &child_nat);
+
+ min_height += child_min;
+ nat_height += child_nat;
+
+ if (menu_item->submenu && menu_item->show_submenu_indicator)
+ {
+ gint arrow_size;
+
+ get_arrow_size (widget, child, &arrow_size);
+
+ min_height = MAX (min_height, arrow_size);
+ nat_height = MAX (nat_height, arrow_size);
+ }
+ }
+ else /* separator item */
+ {
+ gboolean wide_separators;
+ gint separator_height;
+
+ gtk_widget_style_get (widget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
+
+ if (wide_separators)
+ min_height += separator_height + style->ythickness;
+ else
+ min_height += style->ythickness * 2;
+
+ nat_height = min_height;
+ }
+
+ accel_width = 0;
+ gtk_container_foreach (GTK_CONTAINER (menu_item),
+ gtk_menu_item_accel_width_foreach,
+ &accel_width);
+ menu_item->accelerator_width = accel_width;
+
+ if (minimum_size)
+ *minimum_size = min_height;
+
+ if (natural_size)
+ *natural_size = nat_height;
+}
+
+static void
+gtk_menu_item_get_preferred_height_for_width (GtkWidget *request,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkMenuItem *menu_item;
+ GtkBin *bin;
+ GtkStyle *style;
+ GtkWidget *child, *widget = GTK_WIDGET (request);
+ GtkWidget *parent;
+ guint horizontal_padding;
+ guint border_width;
+ GtkPackDirection pack_dir;
+ GtkPackDirection child_pack_dir;
+ gint min_height, nat_height;
+ gint avail_size;
+
+ min_height = nat_height = 0;
+
+ style = gtk_widget_get_style (widget);
+
+ gtk_widget_style_get (widget,
+ "horizontal-padding", &horizontal_padding,
+ NULL);
+
+ bin = GTK_BIN (widget);
+ menu_item = GTK_MENU_ITEM (widget);
+ parent = gtk_widget_get_parent (widget);
+
+ if (GTK_IS_MENU_BAR (parent))
+ {
+ pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
+ child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
+ }
+ else
+ {
+ pack_dir = GTK_PACK_DIRECTION_LTR;
+ child_pack_dir = GTK_PACK_DIRECTION_LTR;
+ }
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ min_height = (border_width + style->ythickness) * 2;
+
+ avail_size = for_size;
+ avail_size -= (border_width + style->xthickness) * 2;
+
+ if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
+ (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
+ min_height += 2 * horizontal_padding;
+
+ if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
+ (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
+ avail_size -= 2 * horizontal_padding;
+
+ nat_height = min_height;
+
+ child = gtk_bin_get_child (bin);
+
+ if (child != NULL && gtk_widget_get_visible (child))
+ {
+ gint child_min, child_nat;
+ gint arrow_size = 0;
+
+ if (menu_item->submenu && menu_item->show_submenu_indicator)
+ {
+
+ guint arrow_spacing;
+
+ gtk_widget_style_get (widget,
+ "arrow-spacing", &arrow_spacing,
+ NULL);
+
+ get_arrow_size (widget, child, &arrow_size);
+
+ avail_size -= arrow_size;
+ avail_size -= arrow_spacing;
+ }
+
+ gtk_widget_get_preferred_height_for_width (child,
+ avail_size,
+ &child_min,
+ &child_nat);
+
+ min_height += child_min;
+ nat_height += child_nat;
+
+ if (menu_item->submenu && menu_item->show_submenu_indicator)
+ {
+ min_height = MAX (min_height, arrow_size);
+ nat_height = MAX (nat_height, arrow_size);
+ }
+ }
+ else /* separator item */
+ {
+ gboolean wide_separators;
+ gint separator_height;
+
+ gtk_widget_style_get (widget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ NULL);
+
+ if (wide_separators)
+ min_height += separator_height + style->ythickness;
+ else
+ min_height += style->ythickness * 2;
+
+ nat_height = min_height;
+ }
+
+ if (minimum_size)
+ *minimum_size = min_height;
+
+ if (natural_size)
+ *natural_size = nat_height;
+}
+
+static void
+gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+ iface->add_child = gtk_menu_item_buildable_add_child;
+ iface->custom_finished = gtk_menu_item_buildable_custom_finished;
+}
+
+static void
+gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ if (type && strcmp (type, "submenu") == 0)
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
+ GTK_WIDGET (child));
+ else
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+
+static void
+gtk_menu_item_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data)
+{
+ GtkWidget *toplevel;
+
+ if (strcmp (tagname, "accelerator") == 0)
+ {
+ GtkMenuShell *menu_shell;
+ GtkWidget *attach;
+
+ menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (buildable)));
+ if (menu_shell)
+ {
+ while (GTK_IS_MENU (menu_shell) &&
+ (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
+ menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (attach));
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
+ }
+ else
+ {
+ /* Fall back to something ... */
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (buildable));
+
+ g_warning ("found a GtkMenuItem '%s' without a parent GtkMenuShell, assigned accelerators wont work.",
+ gtk_buildable_get_name (buildable));
+ }
+
+ /* Feed the correct toplevel to the GtkWidget accelerator parsing code */
+ _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
+ }
+ else
+ parent_buildable_iface->custom_finished (buildable, builder, child, tagname, user_data);
+}
+
+
+static void
+gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+ iface->update = gtk_menu_item_update;
+ iface->sync_action_properties = gtk_menu_item_sync_action_properties;
+}
+
+static void
+activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
+{
+ GtkWidget *child;
+
+ child = gtk_bin_get_child (GTK_BIN (menu_item));
+
+ if (GTK_IS_LABEL (child))
+ {
+ const gchar *label;
+
+ label = gtk_action_get_label (action);
+ gtk_menu_item_set_label (menu_item, label);
+ }
+}
+
+gboolean _gtk_menu_is_empty (GtkWidget *menu);
+
+static void
+gtk_menu_item_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (strcmp (property_name, "visible") == 0)
+ _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
+ _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
+ else if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
+ else if (priv->use_action_appearance)
+ {
+ if (strcmp (property_name, "label") == 0)
+ activatable_update_label (menu_item, action);
+ }
+}
+
+static void
+gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+ GtkWidget *label;
+
+ if (!priv->use_action_appearance || !action)
+ {
+ label = gtk_bin_get_child (GTK_BIN (menu_item));
+
+ if (GTK_IS_ACCEL_LABEL (label))
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), GTK_WIDGET (menu_item));
+ }
+
+ if (!action)
+ return;
+
+ _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
+ _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
+
+ gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
+
+ if (priv->use_action_appearance)
+ {
+ label = gtk_bin_get_child (GTK_BIN (menu_item));
+
+ /* make sure label is a label */
+ if (label && !GTK_IS_LABEL (label))
+ {
+ gtk_container_remove (GTK_CONTAINER (menu_item), label);
+ label = NULL;
+ }
+
+ gtk_menu_item_ensure_label (menu_item);
+ gtk_menu_item_set_use_underline (menu_item, TRUE);
+
+ if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
+ {
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), NULL);
+ gtk_accel_label_set_accel_closure (GTK_ACCEL_LABEL (label),
+ gtk_action_get_accel_closure (action));
+ }
+
+ activatable_update_label (menu_item, action);
+ }
+}
+
+static void
+gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
+ GtkAction *action)
+{
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (priv->action == action)
+ return;
+
+ if (priv->action)
+ {
+ gtk_action_disconnect_accelerator (priv->action);
+ }
+
+ if (action)
+ {
+ const gchar *accel_path;
+
+ accel_path = gtk_action_get_accel_path (action);
+ if (accel_path)
+ {
+ gtk_action_connect_accelerator (action);
+ gtk_menu_item_set_accel_path (menu_item, accel_path);
+ }
+ }
+
+ gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
+
+ priv->action = action;
+}
+
+static void
+gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
+ gboolean use_appearance)
+{
+ GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+ if (priv->use_action_appearance != use_appearance)
+ {
+ priv->use_action_appearance = use_appearance;
+
+ gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (menu_item), priv->action);
+ }
+}
+
+
/**
* gtk_menu_item_set_submenu:
* @menu_item: a #GtkMenuItem
- * @submenu: the submenu, or %NULL
+ * @submenu: (allow-none): the submenu, or %NULL
*
* Sets or replaces the menu item's submenu, or removes it when a %NULL
* submenu is passed.
gtk_menu_item_detacher);
}
- if (GTK_WIDGET (menu_item)->parent)
+ if (gtk_widget_get_parent (GTK_WIDGET (menu_item)))
gtk_widget_queue_resize (GTK_WIDGET (menu_item));
g_object_notify (G_OBJECT (menu_item), "submenu");
* gtk_menu_item_get_submenu:
* @menu_item: a #GtkMenuItem
*
- * Gets the submenu underneath this menu item, if any. See
- * gtk_menu_item_set_submenu().
+ * Gets the submenu underneath this menu item, if any.
+ * See gtk_menu_item_set_submenu().
*
- * Return value: submenu for this menu item, or %NULL if none.
+ * Return value: (transfer none): submenu for this menu item, or %NULL if none.
**/
GtkWidget *
gtk_menu_item_get_submenu (GtkMenuItem *menu_item)
return menu_item->submenu;
}
-/**
- * gtk_menu_item_remove_submenu:
- * @menu_item: a #GtkMenuItem
- *
- * Removes the widget's submenu.
- *
- * Deprecated: 2.12: gtk_menu_item_remove_submenu() is deprecated and
- * should not be used in newly written code. Use
- * gtk_menu_item_set_submenu() instead.
- **/
-void
-gtk_menu_item_remove_submenu (GtkMenuItem *menu_item)
-{
- g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-
- gtk_menu_item_set_submenu (menu_item, NULL);
-}
-
void _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
GtkSubmenuPlacement placement);
void
gtk_menu_item_select (GtkMenuItem *menu_item)
{
- g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-
- gtk_item_select (GTK_ITEM (menu_item));
-
- /* Enable themeing of the parent menu item depending on whether
- * something is selected in its submenu
- */
- if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
- {
- GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
-
- if (menu->parent_menu_item)
- gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
- }
-}
+ GtkWidget *parent;
-void
-gtk_menu_item_deselect (GtkMenuItem *menu_item)
-{
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
- gtk_item_deselect (GTK_ITEM (menu_item));
+ g_signal_emit (menu_item, menu_item_signals[SELECT], 0);
/* Enable themeing of the parent menu item depending on whether
* something is selected in its submenu
*/
- if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
+ parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
+ if (GTK_IS_MENU (parent))
{
- GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
+ GtkMenu *menu = GTK_MENU (parent);
if (menu->parent_menu_item)
gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
}
}
-void
-gtk_menu_item_activate (GtkMenuItem *menu_item)
-{
- g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-
- g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
-}
-
-void
-gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
- gint *requisition)
-{
- g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-
- g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
-}
-
-void
-gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
- gint allocation)
-{
- g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-
- g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
-}
-
-static void
-gtk_menu_item_accel_width_foreach (GtkWidget *widget,
- gpointer data)
-{
- guint *width = data;
-
- if (GTK_IS_ACCEL_LABEL (widget))
- {
- guint w;
-
- w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
- *width = MAX (*width, w);
- }
- else if (GTK_IS_CONTAINER (widget))
- gtk_container_foreach (GTK_CONTAINER (widget),
- gtk_menu_item_accel_width_foreach,
- data);
-}
-
-static gint
-get_minimum_width (GtkWidget *widget)
-{
- PangoContext *context;
- PangoFontMetrics *metrics;
- gint width;
- gint width_chars;
-
- context = gtk_widget_get_pango_context (widget);
- metrics = pango_context_get_metrics (context,
- widget->style->font_desc,
- pango_context_get_language (context));
-
- width = pango_font_metrics_get_approximate_char_width (metrics);
-
- pango_font_metrics_unref (metrics);
-
- gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
-
- return PANGO_PIXELS (width_chars * width);
-}
-
-static void
-gtk_menu_item_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- GtkMenuItem *menu_item;
- GtkBin *bin;
- guint accel_width;
- guint horizontal_padding;
- GtkPackDirection pack_dir;
- GtkPackDirection child_pack_dir;
-
- g_return_if_fail (GTK_IS_MENU_ITEM (widget));
- g_return_if_fail (requisition != NULL);
-
- gtk_widget_style_get (widget,
- "horizontal-padding", &horizontal_padding,
- NULL);
-
- bin = GTK_BIN (widget);
- menu_item = GTK_MENU_ITEM (widget);
-
- if (GTK_IS_MENU_BAR (widget->parent))
- {
- pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
- child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
- }
- else
- {
- pack_dir = GTK_PACK_DIRECTION_LTR;
- child_pack_dir = GTK_PACK_DIRECTION_LTR;
- }
-
- requisition->width = (GTK_CONTAINER (widget)->border_width +
- widget->style->xthickness) * 2;
- requisition->height = (GTK_CONTAINER (widget)->border_width +
- widget->style->ythickness) * 2;
+void
+gtk_menu_item_deselect (GtkMenuItem *menu_item)
+{
+ GtkWidget *parent;
- if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
- (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
- requisition->width += 2 * horizontal_padding;
- else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
- (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
- requisition->height += 2 * horizontal_padding;
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
- if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ g_signal_emit (menu_item, menu_item_signals[DESELECT], 0);
+
+ /* Enable themeing of the parent menu item depending on whether
+ * something is selected in its submenu
+ */
+ parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
+ if (GTK_IS_MENU (parent))
{
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (bin->child, &child_requisition);
+ GtkMenu *menu = GTK_MENU (parent);
- requisition->width += child_requisition.width;
- requisition->height += child_requisition.height;
+ if (menu->parent_menu_item)
+ gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
+ }
+}
- if (menu_item->submenu && menu_item->show_submenu_indicator)
- {
- guint arrow_spacing;
-
- gtk_widget_style_get (widget,
- "arrow-spacing", &arrow_spacing,
- NULL);
+void
+gtk_menu_item_activate (GtkMenuItem *menu_item)
+{
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
- requisition->width += child_requisition.height;
- requisition->width += arrow_spacing;
+ g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
+}
- requisition->width = MAX (requisition->width, get_minimum_width (widget));
- }
- }
- else /* separator item */
- {
- gboolean wide_separators;
- gint separator_height;
+void
+gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
+ gint *requisition)
+{
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
- gtk_widget_style_get (widget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
- NULL);
+ g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
+}
- if (wide_separators)
- requisition->height += separator_height + widget->style->ythickness;
- else
- requisition->height += widget->style->ythickness * 2;
- }
+void
+gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
+ gint allocation)
+{
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
- accel_width = 0;
- gtk_container_foreach (GTK_CONTAINER (menu_item),
- gtk_menu_item_accel_width_foreach,
- &accel_width);
- menu_item->accelerator_width = accel_width;
+ g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
}
static void
GtkTextDirection direction;
GtkPackDirection pack_dir;
GtkPackDirection child_pack_dir;
+ GtkWidget *child;
+ GtkWidget *parent;
g_return_if_fail (GTK_IS_MENU_ITEM (widget));
g_return_if_fail (allocation != NULL);
direction = gtk_widget_get_direction (widget);
- if (GTK_IS_MENU_BAR (widget->parent))
+ parent = gtk_widget_get_parent (widget);
+ if (GTK_IS_MENU_BAR (parent))
{
- pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
- child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
+ pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
+ child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
}
else
{
pack_dir = GTK_PACK_DIRECTION_LTR;
child_pack_dir = GTK_PACK_DIRECTION_LTR;
}
-
- widget->allocation = *allocation;
- if (bin->child)
+ gtk_widget_set_allocation (widget, allocation);
+
+ child = gtk_bin_get_child (bin);
+ if (child)
{
GtkRequisition child_requisition;
+ GtkStyle *style;
guint horizontal_padding;
+ guint border_width;
+ style = gtk_widget_get_style (widget);
gtk_widget_style_get (widget,
"horizontal-padding", &horizontal_padding,
NULL);
- child_allocation.x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
- child_allocation.y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness;
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ child_allocation.x = border_width + style->xthickness;
+ child_allocation.y = border_width + style->ythickness;
if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
(child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
(child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
child_allocation.y += horizontal_padding;
-
+
child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
child_allocation.height -= GTK_MENU_ITEM (widget)->toggle_size;
}
- child_allocation.x += widget->allocation.x;
- child_allocation.y += widget->allocation.y;
+ child_allocation.x += allocation->x;
+ child_allocation.y += allocation->y;
- gtk_widget_get_child_requisition (bin->child, &child_requisition);
+ gtk_widget_get_preferred_size (child, &child_requisition, NULL);
if (menu_item->submenu && menu_item->show_submenu_indicator)
{
if (direction == GTK_TEXT_DIR_RTL)
if (child_allocation.width < 1)
child_allocation.width = 1;
- gtk_widget_size_allocate (bin->child, &child_allocation);
+ gtk_widget_size_allocate (child, &child_allocation);
}
- if (GTK_WIDGET_REALIZED (widget))
+ if (gtk_widget_get_realized (widget))
gdk_window_move_resize (menu_item->event_window,
allocation->x, allocation->y,
allocation->width, allocation->height);
static void
gtk_menu_item_realize (GtkWidget *widget)
{
+ GtkAllocation allocation;
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
+ GdkWindow *window;
GdkWindowAttr attributes;
gint attributes_mask;
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ gtk_widget_set_realized (widget, TRUE);
- widget->window = gtk_widget_get_parent_window (widget);
- g_object_ref (widget->window);
-
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
+ window = gtk_widget_get_parent_window (widget);
+ gtk_widget_set_window (widget, window);
+ g_object_ref (window);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.wclass = GDK_INPUT_ONLY;
attributes.event_mask = (gtk_widget_get_events (widget) |
GDK_POINTER_MOTION_MASK);
attributes_mask = GDK_WA_X | GDK_WA_Y;
- menu_item->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
+
+ menu_item->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
gdk_window_set_user_data (menu_item->event_window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_widget_style_attach (widget);
}
static void
gdk_window_set_user_data (menu_item->event_window, NULL);
gdk_window_destroy (menu_item->event_window);
menu_item->event_window = NULL;
-
- if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize)
- (* GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize) (widget);
+
+ GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize (widget);
}
static void
GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unmap (widget);
}
-static void
-gtk_menu_item_paint (GtkWidget *widget,
- GdkRectangle *area)
+static gboolean
+gtk_menu_item_enter (GtkWidget *widget,
+ GdkEventCrossing *event)
{
- GtkMenuItem *menu_item;
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
+}
+
+static gboolean
+gtk_menu_item_leave (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent*) event);
+}
+
+static gboolean
+gtk_menu_item_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
GtkStateType state_type;
GtkShadowType shadow_type, selected_shadow_type;
- gint width, height;
- gint x, y;
- gint border_width = GTK_CONTAINER (widget)->border_width;
+ GtkStyle *style;
+ GtkWidget *child;
+ GdkWindow *window;
+ gint x, y, w, h, width, height;
+ guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+ state_type = gtk_widget_get_state (widget);
+ style = gtk_widget_get_style (widget);
+ window = gtk_widget_get_window (widget);
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+
+ x = border_width;
+ y = border_width;
+ w = width - border_width * 2;
+ h = height - border_width * 2;
+
+ child = gtk_bin_get_child (GTK_BIN (menu_item));
+
+ if (child && state_type == GTK_STATE_PRELIGHT)
+ {
+ gtk_widget_style_get (widget,
+ "selected-shadow-type", &selected_shadow_type,
+ NULL);
+ gtk_paint_box (style,
+ cr,
+ GTK_STATE_PRELIGHT,
+ selected_shadow_type,
+ widget, "menuitem",
+ x, y, w, h);
+ }
- if (GTK_WIDGET_DRAWABLE (widget))
+ if (menu_item->submenu && menu_item->show_submenu_indicator)
{
- menu_item = GTK_MENU_ITEM (widget);
+ gint arrow_x, arrow_y;
+ gint arrow_size;
+ guint horizontal_padding;
+ GtkTextDirection direction;
+ GtkArrowType arrow_type;
- state_type = widget->state;
-
- x = widget->allocation.x + border_width;
- y = widget->allocation.y + border_width;
- width = widget->allocation.width - border_width * 2;
- height = widget->allocation.height - border_width * 2;
-
- if ((state_type == GTK_STATE_PRELIGHT) &&
- (GTK_BIN (menu_item)->child))
- {
- gtk_widget_style_get (widget,
- "selected-shadow-type", &selected_shadow_type,
- NULL);
- gtk_paint_box (widget->style,
- widget->window,
- GTK_STATE_PRELIGHT,
- selected_shadow_type,
- area, widget, "menuitem",
- x, y, width, height);
- }
+ direction = gtk_widget_get_direction (widget);
- if (menu_item->submenu && menu_item->show_submenu_indicator)
- {
- gint arrow_x, arrow_y;
- gint arrow_size;
- gint arrow_extent;
- guint horizontal_padding;
- gfloat arrow_scaling;
- GtkTextDirection direction;
- GtkArrowType arrow_type;
- PangoContext *context;
- PangoFontMetrics *metrics;
-
- direction = gtk_widget_get_direction (widget);
-
- gtk_widget_style_get (widget,
- "horizontal-padding", &horizontal_padding,
- "arrow-scaling", &arrow_scaling,
- NULL);
-
- context = gtk_widget_get_pango_context (GTK_BIN (menu_item)->child);
- metrics = pango_context_get_metrics (context,
- GTK_WIDGET (GTK_BIN (menu_item)->child)->style->font_desc,
- pango_context_get_language (context));
-
- arrow_size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
- pango_font_metrics_get_descent (metrics)));
-
- pango_font_metrics_unref (metrics);
-
- arrow_extent = arrow_size * arrow_scaling;
+ gtk_widget_style_get (widget,
+ "horizontal-padding", &horizontal_padding,
+ NULL);
- shadow_type = GTK_SHADOW_OUT;
- if (state_type == GTK_STATE_PRELIGHT)
- shadow_type = GTK_SHADOW_IN;
+ get_arrow_size (widget, child, &arrow_size);
- if (direction == GTK_TEXT_DIR_LTR)
- {
- arrow_x = x + width - horizontal_padding - arrow_extent;
- arrow_type = GTK_ARROW_RIGHT;
- }
- else
- {
- arrow_x = x + horizontal_padding;
- arrow_type = GTK_ARROW_LEFT;
- }
+ shadow_type = GTK_SHADOW_OUT;
+ if (state_type == GTK_STATE_PRELIGHT)
+ shadow_type = GTK_SHADOW_IN;
- arrow_y = y + (height - arrow_extent) / 2;
+ if (direction == GTK_TEXT_DIR_LTR)
+ {
+ arrow_x = x + w - horizontal_padding - arrow_size;
+ arrow_type = GTK_ARROW_RIGHT;
+ }
+ else
+ {
+ arrow_x = x + horizontal_padding;
+ arrow_type = GTK_ARROW_LEFT;
+ }
- gtk_paint_arrow (widget->style, widget->window,
- state_type, shadow_type,
- area, widget, "menuitem",
- arrow_type, TRUE,
- arrow_x, arrow_y,
- arrow_extent, arrow_extent);
- }
- else if (!GTK_BIN (menu_item)->child)
- {
- gboolean wide_separators;
- gint separator_height;
- guint horizontal_padding;
+ arrow_y = y + (h - arrow_size) / 2;
- gtk_widget_style_get (widget,
- "wide-separators", &wide_separators,
- "separator-height", &separator_height,
- "horizontal-padding", &horizontal_padding,
- NULL);
-
- if (wide_separators)
- gtk_paint_box (widget->style, widget->window,
- GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
- area, widget, "hseparator",
- widget->allocation.x + horizontal_padding + widget->style->xthickness,
- widget->allocation.y + (widget->allocation.height -
- separator_height -
- widget->style->ythickness) / 2,
- widget->allocation.width -
- 2 * (horizontal_padding + widget->style->xthickness),
- separator_height);
- else
- gtk_paint_hline (widget->style, widget->window,
- GTK_STATE_NORMAL, area, widget, "menuitem",
- widget->allocation.x + horizontal_padding + widget->style->xthickness,
- widget->allocation.x + widget->allocation.width - horizontal_padding - widget->style->xthickness - 1,
- widget->allocation.y + (widget->allocation.height -
- widget->style->ythickness) / 2);
- }
+ gtk_paint_arrow (style, cr,
+ state_type, shadow_type,
+ widget, "menuitem",
+ arrow_type, TRUE,
+ arrow_x, arrow_y,
+ arrow_size, arrow_size);
}
-}
-
-static gint
-gtk_menu_item_expose (GtkWidget *widget,
- GdkEventExpose *event)
-{
- g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- if (GTK_WIDGET_DRAWABLE (widget))
+ else if (!child)
{
- gtk_menu_item_paint (widget, &event->area);
+ gboolean wide_separators;
+ gint separator_height;
+ guint horizontal_padding;
+
+ gtk_widget_style_get (widget,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
+ "horizontal-padding", &horizontal_padding,
+ NULL);
- (* GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->expose_event) (widget, event);
+ if (wide_separators)
+ gtk_paint_box (style, cr,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ widget, "hseparator",
+ horizontal_padding + style->xthickness,
+ (height - separator_height - style->ythickness) / 2,
+ width - 2 * (horizontal_padding + style->xthickness),
+ separator_height);
+ else
+ gtk_paint_hline (style, cr,
+ GTK_STATE_NORMAL, widget, "menuitem",
+ horizontal_padding + style->xthickness,
+ width - horizontal_padding - style->xthickness - 1,
+ (height - style->ythickness) / 2);
}
+ GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->draw (widget, cr);
+
return FALSE;
}
static void
-gtk_real_menu_item_select (GtkItem *item)
+gtk_real_menu_item_select (GtkMenuItem *menu_item)
{
- GtkMenuItem *menu_item;
gboolean touchscreen_mode;
- g_return_if_fail (GTK_IS_MENU_ITEM (item));
-
- menu_item = GTK_MENU_ITEM (item);
-
- g_object_get (gtk_widget_get_settings (GTK_WIDGET (item)),
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_item)),
"gtk-touchscreen-mode", &touchscreen_mode,
NULL);
if (!touchscreen_mode &&
menu_item->submenu &&
- (!GTK_WIDGET_MAPPED (menu_item->submenu) ||
+ (!gtk_widget_get_mapped (menu_item->submenu) ||
GTK_MENU (menu_item->submenu)->tearoff_active))
{
_gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), TRUE);
}
static void
-gtk_real_menu_item_deselect (GtkItem *item)
+gtk_real_menu_item_deselect (GtkMenuItem *menu_item)
{
- GtkMenuItem *menu_item;
-
- g_return_if_fail (GTK_IS_MENU_ITEM (item));
-
- menu_item = GTK_MENU_ITEM (item);
-
if (menu_item->submenu)
_gtk_menu_item_popdown_submenu (GTK_WIDGET (menu_item));
gtk_menu_item_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling)
{
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (widget);
+
+ if (GTK_IS_MENU_SHELL (parent))
+ _gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (parent), TRUE);
+
if (group_cycling &&
- widget->parent &&
- GTK_IS_MENU_SHELL (widget->parent) &&
- GTK_MENU_SHELL (widget->parent)->active)
+ parent &&
+ GTK_IS_MENU_SHELL (parent) &&
+ GTK_MENU_SHELL (parent)->active)
{
- gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent),
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (parent),
widget);
}
else
return TRUE;
}
+static void
+gtk_real_menu_item_activate (GtkMenuItem *menu_item)
+{
+ GtkMenuItemPrivate *priv;
+
+ priv = GET_PRIVATE (menu_item);
+
+ if (priv->action)
+ gtk_action_activate (priv->action);
+}
+
+
static void
gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
{
+ GtkMenuItemPrivate *priv;
+ GtkWidget *parent;
GtkWidget *widget;
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+ priv = GET_PRIVATE (menu_item);
widget = GTK_WIDGET (menu_item);
-
- if (widget->parent &&
- GTK_IS_MENU_SHELL (widget->parent))
+ parent = gtk_widget_get_parent (widget);
+
+ if (parent && GTK_IS_MENU_SHELL (parent))
{
+ GtkMenuShell *menu_shell = GTK_MENU_SHELL (parent);
+
if (menu_item->submenu == NULL)
- gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget->parent),
+ gtk_menu_shell_activate_item (menu_shell,
widget, TRUE);
else
{
- GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget->parent);
-
_gtk_menu_shell_activate (menu_shell);
- gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent), widget);
+ gtk_menu_shell_select_item (menu_shell, widget);
_gtk_menu_item_popup_submenu (widget, FALSE);
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
menu_item->toggle_size = allocation;
}
+static void
+gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
+ const gchar *label)
+{
+ GtkWidget *child;
+
+ gtk_menu_item_ensure_label (menu_item);
+
+ child = gtk_bin_get_child (GTK_BIN (menu_item));
+ if (GTK_IS_LABEL (child))
+ {
+ gtk_label_set_label (GTK_LABEL (child), label ? label : "");
+
+ g_object_notify (G_OBJECT (menu_item), "label");
+ }
+}
+
+static G_CONST_RETURN gchar *
+gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
+{
+ GtkWidget *child;
+
+ gtk_menu_item_ensure_label (menu_item);
+
+ child = gtk_bin_get_child (GTK_BIN (menu_item));
+ if (GTK_IS_LABEL (child))
+ return gtk_label_get_label (GTK_LABEL (child));
+
+ return NULL;
+}
+
static void
free_timeval (GTimeVal *val)
{
gboolean remember_exact_time)
{
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (widget);
- if (GTK_WIDGET_IS_SENSITIVE (menu_item->submenu))
+ if (gtk_widget_is_sensitive (menu_item->submenu) && parent)
{
gboolean take_focus;
GtkMenuPositionFunc menu_position_func;
- take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (widget->parent));
+ take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent));
gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (menu_item->submenu),
take_focus);
* positioning function instead which places the submenu at the
* mouse cursor.
*/
- if (widget->window)
+ if (gtk_widget_get_window (widget))
menu_position_func = gtk_menu_item_position_menu;
else
menu_position_func = NULL;
gtk_menu_popup (GTK_MENU (menu_item->submenu),
- widget->parent,
+ parent,
widget,
menu_position_func,
menu_item,
- GTK_MENU_SHELL (widget->parent)->button,
+ GTK_MENU_SHELL (parent)->button,
0);
}
menu_item = GTK_MENU_ITEM (data);
- parent = GTK_WIDGET (menu_item)->parent;
+ parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active) ||
(GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off))
static gint
get_popup_delay (GtkWidget *widget)
{
- if (GTK_IS_MENU_SHELL (widget->parent))
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (widget);
+ if (GTK_IS_MENU_SHELL (parent))
{
- return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (widget->parent));
+ return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (parent));
}
else
{
"vertical-padding", &vertical_padding,
NULL);
- *vertical_offset -= GTK_WIDGET (menu)->style->ythickness;
+ *vertical_offset -= gtk_widget_get_style (GTK_WIDGET (menu))->ythickness;
*vertical_offset -= vertical_padding;
*horizontal_offset += horizontal_padding;
}
gboolean *push_in,
gpointer user_data)
{
+ GtkAllocation allocation;
GtkMenuItem *menu_item;
GtkWidget *widget;
GtkMenuItem *parent_menu_item;
+ GtkRequisition requisition;
+ GtkWidget *parent;
GdkScreen *screen;
gint twidth, theight;
gint tx, ty;
direction = gtk_widget_get_direction (widget);
- twidth = GTK_WIDGET (menu)->requisition.width;
- theight = GTK_WIDGET (menu)->requisition.height;
+ gtk_widget_get_preferred_size (GTK_WIDGET (menu), &requisition, NULL);
+ twidth = requisition.width;
+ theight = requisition.height;
screen = gtk_widget_get_screen (GTK_WIDGET (menu));
monitor_num = gdk_screen_get_monitor_at_window (screen, menu_item->event_window);
monitor_num = 0;
gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
- if (!gdk_window_get_origin (widget->window, &tx, &ty))
+ if (!gdk_window_get_origin (gtk_widget_get_window (widget),
+ &tx, &ty))
{
g_warning ("Menu not on screen");
return;
}
- tx += widget->allocation.x;
- ty += widget->allocation.y;
+ gtk_widget_get_allocation (widget, &allocation);
+
+ tx += allocation.x;
+ ty += allocation.y;
get_offsets (menu, &horizontal_offset, &vertical_offset);
available_left = tx - monitor.x;
- available_right = monitor.x + monitor.width - (tx + widget->allocation.width);
+ available_right = monitor.x + monitor.width - (tx + allocation.width);
- if (GTK_IS_MENU_BAR (widget->parent))
+ parent = gtk_widget_get_parent (widget);
+ if (GTK_IS_MENU_BAR (parent))
{
menu_item->from_menubar = TRUE;
}
- else if (GTK_IS_MENU (widget->parent))
+ else if (GTK_IS_MENU (parent))
{
- if (GTK_MENU (widget->parent)->parent_menu_item)
- menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item)->from_menubar;
+ if (GTK_MENU (parent)->parent_menu_item)
+ menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (parent)->parent_menu_item)->from_menubar;
else
menu_item->from_menubar = FALSE;
}
else
{
menu_item->submenu_direction = GTK_DIRECTION_LEFT;
- tx += widget->allocation.width - twidth;
+ tx += allocation.width - twidth;
}
- if ((ty + widget->allocation.height + theight) <= monitor.y + monitor.height)
- ty += widget->allocation.height;
+ if ((ty + allocation.height + theight) <= monitor.y + monitor.height)
+ ty += allocation.height;
else if ((ty - theight) >= monitor.y)
ty -= theight;
- else if (monitor.y + monitor.height - (ty + widget->allocation.height) > ty)
- ty += widget->allocation.height;
+ else if (monitor.y + monitor.height - (ty + allocation.height) > ty)
+ ty += allocation.height;
else
ty -= theight;
break;
case GTK_LEFT_RIGHT:
- if (GTK_IS_MENU (widget->parent))
- parent_menu_item = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item);
+ if (GTK_IS_MENU (parent))
+ parent_menu_item = GTK_MENU_ITEM (GTK_MENU (parent)->parent_menu_item);
else
parent_menu_item = NULL;
-
- parent_xthickness = widget->parent->style->xthickness;
- if (parent_menu_item && !GTK_MENU (widget->parent)->torn_off)
+ parent_xthickness = gtk_widget_get_style (parent)->xthickness;
+
+ if (parent_menu_item && !GTK_MENU (parent)->torn_off)
{
menu_item->submenu_direction = parent_menu_item->submenu_direction;
}
else
{
menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
- tx += widget->allocation.width + parent_xthickness + horizontal_offset;
+ tx += allocation.width + parent_xthickness + horizontal_offset;
}
break;
case GTK_DIRECTION_RIGHT:
- if (tx + widget->allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
+ if (tx + allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
available_right >= available_left)
- tx += widget->allocation.width + parent_xthickness + horizontal_offset;
+ tx += allocation.width + parent_xthickness + horizontal_offset;
else
{
menu_item->submenu_direction = GTK_DIRECTION_LEFT;
gtk_menu_set_monitor (menu, monitor_num);
- if (!GTK_WIDGET_VISIBLE (menu->toplevel))
+ if (!gtk_widget_get_visible (menu->toplevel))
{
gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar?
GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
gtk_menu_item_can_activate_accel (GtkWidget *widget,
guint signal_id)
{
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (widget);
/* Chain to the parent GtkMenu for further checks */
- return (GTK_WIDGET_IS_SENSITIVE (widget) && GTK_WIDGET_VISIBLE (widget) &&
- widget->parent && gtk_widget_can_activate_accel (widget->parent, signal_id));
+ return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) &&
+ parent && gtk_widget_can_activate_accel (parent, signal_id));
}
static void
GtkWidget *previous_parent)
{
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
- GtkMenu *menu = GTK_IS_MENU (widget->parent) ? GTK_MENU (widget->parent) : NULL;
+ GtkMenu *menu;
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (widget);
+ menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
if (menu)
_gtk_menu_item_refresh_accel_path (menu_item,
/**
* gtk_menu_item_set_accel_path
* @menu_item: a valid #GtkMenuItem
- * @accel_path: accelerator path, corresponding to this menu item's
+ * @accel_path: (allow-none): accelerator path, corresponding to this menu item's
* functionality, or %NULL to unset the current path.
*
* Set the accelerator path on @menu_item, through which runtime changes of the
gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
const gchar *accel_path)
{
+ GtkWidget *parent;
GtkWidget *widget;
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
gtk_widget_set_accel_path (widget, NULL, NULL);
/* install accelerators associated with new path */
- if (GTK_IS_MENU (widget->parent))
+ parent = gtk_widget_get_parent (widget);
+ if (GTK_IS_MENU (parent))
{
- GtkMenu *menu = GTK_MENU (widget->parent);
+ GtkMenu *menu = GTK_MENU (parent);
if (menu->accel_group)
_gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
GtkCallback callback,
gpointer callback_data)
{
- GtkBin *bin;
+ GtkWidget *child;
g_return_if_fail (GTK_IS_MENU_ITEM (container));
g_return_if_fail (callback != NULL);
- bin = GTK_BIN (container);
-
- if (bin->child)
- callback (bin->child, callback_data);
+ child = gtk_bin_get_child (GTK_BIN (container));
+ if (child)
+ callback (child, callback_data);
}
gboolean
_gtk_menu_item_is_selectable (GtkWidget *menu_item)
{
- if ((!GTK_BIN (menu_item)->child &&
+ if ((!gtk_bin_get_child (GTK_BIN (menu_item)) &&
G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
- !GTK_WIDGET_IS_SENSITIVE (menu_item) ||
- !GTK_WIDGET_VISIBLE (menu_item))
+ !gtk_widget_is_sensitive (menu_item) ||
+ !gtk_widget_get_visible (menu_item))
return FALSE;
return TRUE;
}
-#define __GTK_MENU_ITEM_C__
-#include "gtkaliasdef.c"
+static void
+gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
+{
+ GtkWidget *accel_label;
+
+ if (!gtk_bin_get_child (GTK_BIN (menu_item)))
+ {
+ accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
+ gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
+
+ gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label),
+ GTK_WIDGET (menu_item));
+ gtk_widget_show (accel_label);
+ }
+}
+
+/**
+ * gtk_menu_item_set_label:
+ * @menu_item: a #GtkMenuItem
+ * @label: the text you want to set
+ *
+ * Sets @text on the @menu_item label
+ *
+ * Since: 2.16
+ **/
+void
+gtk_menu_item_set_label (GtkMenuItem *menu_item,
+ const gchar *label)
+{
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ GTK_MENU_ITEM_GET_CLASS (menu_item)->set_label (menu_item, label);
+}
+
+/**
+ * gtk_menu_item_get_label:
+ * @menu_item: a #GtkMenuItem
+ *
+ * Sets @text on the @menu_item label
+ *
+ * Returns: The text in the @menu_item label. This is the internal
+ * string used by the label, and must not be modified.
+ *
+ * Since: 2.16
+ **/
+G_CONST_RETURN gchar *
+gtk_menu_item_get_label (GtkMenuItem *menu_item)
+{
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
+
+ return GTK_MENU_ITEM_GET_CLASS (menu_item)->get_label (menu_item);
+}
+
+/**
+ * gtk_menu_item_set_use_underline:
+ * @menu_item: a #GtkMenuItem
+ * @setting: %TRUE if underlines in the text indicate mnemonics
+ *
+ * If true, an underline in the text indicates the next character should be
+ * used for the mnemonic accelerator key.
+ *
+ * Since: 2.16
+ **/
+void
+gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
+ gboolean setting)
+{
+ GtkWidget *child;
+
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+
+ gtk_menu_item_ensure_label (menu_item);
+
+ child = gtk_bin_get_child (GTK_BIN (menu_item));
+ if (GTK_IS_LABEL (child))
+ {
+ gtk_label_set_use_underline (GTK_LABEL (child), setting);
+
+ g_object_notify (G_OBJECT (menu_item), "use-underline");
+ }
+}
+
+/**
+ * gtk_menu_item_get_use_underline:
+ * @menu_item: a #GtkMenuItem
+ *
+ * Checks if an underline in the text indicates the next character should be
+ * used for the mnemonic accelerator key.
+ *
+ * Return value: %TRUE if an embedded underline in the label indicates
+ * the mnemonic accelerator key.
+ *
+ * Since: 2.16
+ **/
+gboolean
+gtk_menu_item_get_use_underline (GtkMenuItem *menu_item)
+{
+ GtkWidget *child;
+
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
+
+ gtk_menu_item_ensure_label (menu_item);
+
+ child = gtk_bin_get_child (GTK_BIN (menu_item));
+ if (GTK_IS_LABEL (child))
+ return gtk_label_get_use_underline (GTK_LABEL (child));
+
+ return FALSE;
+}