X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcheckmenuitem.c;h=343565d2d8d4e34d4a193fbf95c65dab6b7e613f;hb=a89d420270d1a856e072ed87c365b0176f102e6c;hp=af09b98bb649ee5022339fc6daacfeb24a44ee5c;hpb=e65030aaed38522735b1959bad28143445357c4d;p=~andy%2Fgtk diff --git a/gtk/gtkcheckmenuitem.c b/gtk/gtkcheckmenuitem.c index af09b98bb..343565d2d 100644 --- a/gtk/gtkcheckmenuitem.c +++ b/gtk/gtkcheckmenuitem.c @@ -2,196 +2,485 @@ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . */ + +/* + * Modified by the GTK+ Team and others 1997-2001. 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/. + */ + +#include "config.h" #include "gtkcheckmenuitem.h" +#include "gtkmenuitemprivate.h" #include "gtkaccellabel.h" -#include "gtksignal.h" +#include "gtkactivatable.h" +#include "gtktoggleaction.h" +#include "gtkmarshalers.h" +#include "gtkprivate.h" +#include "gtkintl.h" +#include "a11y/gtkcheckmenuitemaccessible.h" + +/** + * SECTION:gtkcheckmenuitem + * @Short_description: A menu item with a check box + * @Title: GtkCheckMenuItem + * + * A #GtkCheckMenuItem is a menu item that maintains the state of a boolean + * value in addition to a #GtkMenuItem usual role in activating application + * code. + * + * A check box indicating the state of the boolean value is displayed + * at the left side of the #GtkMenuItem. Activating the #GtkMenuItem + * toggles the value. + */ -#define CHECK_MENU_ITEM_CLASS(w) GTK_CHECK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass) +#define INDICATOR_SIZE 16 +struct _GtkCheckMenuItemPrivate +{ + guint active : 1; + guint always_show_toggle : 1; + guint draw_as_radio : 1; + guint inconsistent : 1; +}; enum { TOGGLED, LAST_SIGNAL }; +enum { + PROP_0, + PROP_ACTIVE, + PROP_INCONSISTENT, + PROP_DRAW_AS_RADIO +}; -static void gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass); -static void gtk_check_menu_item_init (GtkCheckMenuItem *check_menu_item); -static void gtk_check_menu_item_draw (GtkWidget *widget, - GdkRectangle *area); -static gint gtk_check_menu_item_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_check_menu_item_activate (GtkMenuItem *menu_item); -static void gtk_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item, - GdkRectangle *area); -static void gtk_real_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item, - GdkRectangle *area); +static gint gtk_check_menu_item_draw (GtkWidget *widget, + cairo_t *cr); +static void gtk_check_menu_item_activate (GtkMenuItem *menu_item); +static void gtk_check_menu_item_toggle_size_request (GtkMenuItem *menu_item, + gint *requisition); +static void gtk_real_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item, + cairo_t *cr); +static void gtk_check_menu_item_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_check_menu_item_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void gtk_check_menu_item_activatable_interface_init (GtkActivatableIface *iface); +static void gtk_check_menu_item_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name); +static void gtk_check_menu_item_sync_action_properties (GtkActivatable *activatable, + GtkAction *action); + +static GtkActivatableIface *parent_activatable_iface; +static guint check_menu_item_signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE_WITH_CODE (GtkCheckMenuItem, gtk_check_menu_item, GTK_TYPE_MENU_ITEM, + G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, + gtk_check_menu_item_activatable_interface_init)) +static void +gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + GtkMenuItemClass *menu_item_class; + + gobject_class = G_OBJECT_CLASS (klass); + widget_class = (GtkWidgetClass*) klass; + menu_item_class = (GtkMenuItemClass*) klass; + + gobject_class->set_property = gtk_check_menu_item_set_property; + gobject_class->get_property = gtk_check_menu_item_get_property; + + g_object_class_install_property (gobject_class, + PROP_ACTIVE, + g_param_spec_boolean ("active", + P_("Active"), + P_("Whether the menu item is checked"), + FALSE, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_INCONSISTENT, + g_param_spec_boolean ("inconsistent", + P_("Inconsistent"), + P_("Whether to display an \"inconsistent\" state"), + FALSE, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_DRAW_AS_RADIO, + g_param_spec_boolean ("draw-as-radio", + P_("Draw as radio menu item"), + P_("Whether the menu item looks like a radio menu item"), + FALSE, + GTK_PARAM_READWRITE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("indicator-size", + P_("Indicator Size"), + P_("Size of check or radio indicator"), + 0, + G_MAXINT, + INDICATOR_SIZE, + GTK_PARAM_READABLE)); + + widget_class->draw = gtk_check_menu_item_draw; + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_CHECK_MENU_ITEM_ACCESSIBLE); + + menu_item_class->activate = gtk_check_menu_item_activate; + menu_item_class->hide_on_activate = FALSE; + menu_item_class->toggle_size_request = gtk_check_menu_item_toggle_size_request; + + klass->toggled = NULL; + klass->draw_indicator = gtk_real_check_menu_item_draw_indicator; -static GtkMenuItemClass *parent_class = NULL; -static guint check_menu_item_signals[LAST_SIGNAL] = { 0 }; + /** + * GtkCheckMenuItem::toggled: + * @checkmenuitem: the object which received the signal. + * + * This signal is emitted when the state of the check box is changed. + * + * A signal handler can use gtk_check_menu_item_get_active() + * to discover the new state. + */ + check_menu_item_signals[TOGGLED] = + g_signal_new (I_("toggled"), + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkCheckMenuItemClass, toggled), + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private (klass, sizeof (GtkCheckMenuItemPrivate)); +} +static void +gtk_check_menu_item_activatable_interface_init (GtkActivatableIface *iface) +{ + parent_activatable_iface = g_type_interface_peek_parent (iface); + iface->update = gtk_check_menu_item_update; + iface->sync_action_properties = gtk_check_menu_item_sync_action_properties; +} -GtkType -gtk_check_menu_item_get_type (void) +static void +gtk_check_menu_item_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name) { - static GtkType check_menu_item_type = 0; + GtkCheckMenuItem *check_menu_item; - if (!check_menu_item_type) + check_menu_item = GTK_CHECK_MENU_ITEM (activatable); + + parent_activatable_iface->update (activatable, action, property_name); + + if (strcmp (property_name, "active") == 0) { - static const GtkTypeInfo check_menu_item_info = - { - "GtkCheckMenuItem", - sizeof (GtkCheckMenuItem), - sizeof (GtkCheckMenuItemClass), - (GtkClassInitFunc) gtk_check_menu_item_class_init, - (GtkObjectInitFunc) gtk_check_menu_item_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - check_menu_item_type = gtk_type_unique (gtk_menu_item_get_type (), &check_menu_item_info); + gtk_action_block_activate (action); + gtk_check_menu_item_set_active (check_menu_item, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); + gtk_action_unblock_activate (action); } - return check_menu_item_type; + if (!gtk_activatable_get_use_action_appearance (activatable)) + return; + + if (strcmp (property_name, "draw-as-radio") == 0) + gtk_check_menu_item_set_draw_as_radio (check_menu_item, + gtk_toggle_action_get_draw_as_radio (GTK_TOGGLE_ACTION (action))); } +static void +gtk_check_menu_item_sync_action_properties (GtkActivatable *activatable, + GtkAction *action) +{ + GtkCheckMenuItem *check_menu_item; + + check_menu_item = GTK_CHECK_MENU_ITEM (activatable); + + parent_activatable_iface->sync_action_properties (activatable, action); + + if (!GTK_IS_TOGGLE_ACTION (action)) + return; + + gtk_action_block_activate (action); + gtk_check_menu_item_set_active (check_menu_item, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); + gtk_action_unblock_activate (action); + + if (!gtk_activatable_get_use_action_appearance (activatable)) + return; + + gtk_check_menu_item_set_draw_as_radio (check_menu_item, + gtk_toggle_action_get_draw_as_radio (GTK_TOGGLE_ACTION (action))); +} + +/** + * gtk_check_menu_item_new: + * + * Creates a new #GtkCheckMenuItem. + * + * Returns: a new #GtkCheckMenuItem. + */ GtkWidget* gtk_check_menu_item_new (void) { - return GTK_WIDGET (gtk_type_new (gtk_check_menu_item_get_type ())); + return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, NULL); } +/** + * gtk_check_menu_item_new_with_label: + * @label: the string to use for the label. + * + * Creates a new #GtkCheckMenuItem with a label. + * + * Returns: a new #GtkCheckMenuItem. + */ GtkWidget* gtk_check_menu_item_new_with_label (const gchar *label) { - GtkWidget *check_menu_item; - GtkWidget *accel_label; - - check_menu_item = gtk_check_menu_item_new (); - accel_label = gtk_accel_label_new (label); - gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5); + return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, + "label", label, + NULL); +} - gtk_container_add (GTK_CONTAINER (check_menu_item), accel_label); - gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), check_menu_item); - gtk_widget_show (accel_label); - return check_menu_item; +/** + * gtk_check_menu_item_new_with_mnemonic: + * @label: The text of the button, with an underscore in front of the + * character + * + * Creates a new #GtkCheckMenuItem containing a label. The label + * will be created using gtk_label_new_with_mnemonic(), so underscores + * in @label indicate the mnemonic for the menu item. + * + * Returns: a new #GtkCheckMenuItem + */ +GtkWidget* +gtk_check_menu_item_new_with_mnemonic (const gchar *label) +{ + return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, + "label", label, + "use-underline", TRUE, + NULL); } +/** + * gtk_check_menu_item_set_active: + * @check_menu_item: a #GtkCheckMenuItem. + * @is_active: boolean value indicating whether the check box is active. + * + * Sets the active state of the menu item's check box. + */ void gtk_check_menu_item_set_active (GtkCheckMenuItem *check_menu_item, - gboolean is_active) + gboolean is_active) { - g_return_if_fail (check_menu_item != NULL); + GtkCheckMenuItemPrivate *priv; + g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item)); + priv = check_menu_item->priv; + is_active = is_active != 0; - if (check_menu_item->active != is_active) + if (priv->active != is_active) gtk_menu_item_activate (GTK_MENU_ITEM (check_menu_item)); } -void -gtk_check_menu_item_set_show_toggle (GtkCheckMenuItem *menu_item, - gboolean always) +/** + * gtk_check_menu_item_get_active: + * @check_menu_item: a #GtkCheckMenuItem + * + * Returns whether the check menu item is active. See + * gtk_check_menu_item_set_active (). + * + * Return value: %TRUE if the menu item is checked. + */ +gboolean +gtk_check_menu_item_get_active (GtkCheckMenuItem *check_menu_item) { - g_return_if_fail (menu_item != NULL); + g_return_val_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item), FALSE); + + return check_menu_item->priv->active; +} + +static void +gtk_check_menu_item_toggle_size_request (GtkMenuItem *menu_item, + gint *requisition) +{ + guint toggle_spacing; + guint indicator_size; + g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (menu_item)); - menu_item->always_show_toggle = always != FALSE; + gtk_widget_style_get (GTK_WIDGET (menu_item), + "toggle-spacing", &toggle_spacing, + "indicator-size", &indicator_size, + NULL); + + *requisition = indicator_size + toggle_spacing; } +/** + * gtk_check_menu_item_toggled: + * @check_menu_item: a #GtkCheckMenuItem. + * + * Emits the #GtkCheckMenuItem::toggled signal. + */ void gtk_check_menu_item_toggled (GtkCheckMenuItem *check_menu_item) { - gtk_signal_emit (GTK_OBJECT (check_menu_item), check_menu_item_signals[TOGGLED]); + g_signal_emit (check_menu_item, check_menu_item_signals[TOGGLED], 0); } -static void -gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass) +/** + * gtk_check_menu_item_set_inconsistent: + * @check_menu_item: a #GtkCheckMenuItem + * @setting: %TRUE to display an "inconsistent" third state check + * + * If the user has selected a range of elements (such as some text or + * spreadsheet cells) that are affected by a boolean setting, and the + * current values in that range are inconsistent, you may want to + * display the check in an "in between" state. This function turns on + * "in between" display. Normally you would turn off the inconsistent + * state again if the user explicitly selects a setting. This has to be + * done manually, gtk_check_menu_item_set_inconsistent() only affects + * visual appearance, it doesn't affect the semantics of the widget. + * + **/ +void +gtk_check_menu_item_set_inconsistent (GtkCheckMenuItem *check_menu_item, + gboolean setting) { - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkMenuItemClass *menu_item_class; + GtkCheckMenuItemPrivate *priv; - object_class = (GtkObjectClass*) klass; - widget_class = (GtkWidgetClass*) klass; - menu_item_class = (GtkMenuItemClass*) klass; + g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item)); - parent_class = gtk_type_class (gtk_menu_item_get_type ()); + priv = check_menu_item->priv; + + setting = setting != FALSE; - check_menu_item_signals[TOGGLED] = - gtk_signal_new ("toggled", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (GtkCheckMenuItemClass, toggled), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); + if (setting != priv->inconsistent) + { + priv->inconsistent = setting; + gtk_widget_queue_draw (GTK_WIDGET (check_menu_item)); + g_object_notify (G_OBJECT (check_menu_item), "inconsistent"); + } +} - gtk_object_class_add_signals (object_class, check_menu_item_signals, LAST_SIGNAL); +/** + * gtk_check_menu_item_get_inconsistent: + * @check_menu_item: a #GtkCheckMenuItem + * + * Retrieves the value set by gtk_check_menu_item_set_inconsistent(). + * + * Return value: %TRUE if inconsistent + **/ +gboolean +gtk_check_menu_item_get_inconsistent (GtkCheckMenuItem *check_menu_item) +{ + g_return_val_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item), FALSE); - widget_class->draw = gtk_check_menu_item_draw; - widget_class->expose_event = gtk_check_menu_item_expose; + return check_menu_item->priv->inconsistent; +} - menu_item_class->activate = gtk_check_menu_item_activate; - menu_item_class->toggle_size = 12; +/** + * gtk_check_menu_item_set_draw_as_radio: + * @check_menu_item: a #GtkCheckMenuItem + * @draw_as_radio: whether @check_menu_item is drawn like a #GtkRadioMenuItem + * + * Sets whether @check_menu_item is drawn like a #GtkRadioMenuItem + * + * Since: 2.4 + **/ +void +gtk_check_menu_item_set_draw_as_radio (GtkCheckMenuItem *check_menu_item, + gboolean draw_as_radio) +{ + GtkCheckMenuItemPrivate *priv; - menu_item_class->hide_on_activate = FALSE; + g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item)); - klass->toggled = NULL; - klass->draw_indicator = gtk_real_check_menu_item_draw_indicator; + priv = check_menu_item->priv; + + draw_as_radio = draw_as_radio != FALSE; + + if (draw_as_radio != priv->draw_as_radio) + { + priv->draw_as_radio = draw_as_radio; + + gtk_widget_queue_draw (GTK_WIDGET (check_menu_item)); + + g_object_notify (G_OBJECT (check_menu_item), "draw-as-radio"); + } } -static void -gtk_check_menu_item_init (GtkCheckMenuItem *check_menu_item) +/** + * gtk_check_menu_item_get_draw_as_radio: + * @check_menu_item: a #GtkCheckMenuItem + * + * Returns whether @check_menu_item looks like a #GtkRadioMenuItem + * + * Return value: Whether @check_menu_item looks like a #GtkRadioMenuItem + * + * Since: 2.4 + **/ +gboolean +gtk_check_menu_item_get_draw_as_radio (GtkCheckMenuItem *check_menu_item) { - check_menu_item->active = FALSE; - check_menu_item->always_show_toggle = FALSE; + g_return_val_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item), FALSE); + + return check_menu_item->priv->draw_as_radio; } static void -gtk_check_menu_item_draw (GtkWidget *widget, - GdkRectangle *area) +gtk_check_menu_item_init (GtkCheckMenuItem *check_menu_item) { - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (widget)); - g_return_if_fail (area != NULL); + GtkCheckMenuItemPrivate *priv; - if (GTK_WIDGET_CLASS (parent_class)->draw) - (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area); + check_menu_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (check_menu_item, + GTK_TYPE_CHECK_MENU_ITEM, + GtkCheckMenuItemPrivate); + priv = check_menu_item->priv; - gtk_check_menu_item_draw_indicator (GTK_CHECK_MENU_ITEM (widget), area); + priv->active = FALSE; + priv->always_show_toggle = TRUE; } static gint -gtk_check_menu_item_expose (GtkWidget *widget, - GdkEventExpose *event) +gtk_check_menu_item_draw (GtkWidget *widget, + cairo_t *cr) { - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CHECK_MENU_ITEM (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (widget); - if (GTK_WIDGET_CLASS (parent_class)->expose_event) - (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); + if (GTK_WIDGET_CLASS (gtk_check_menu_item_parent_class)->draw) + GTK_WIDGET_CLASS (gtk_check_menu_item_parent_class)->draw (widget, cr); - gtk_check_menu_item_draw_indicator (GTK_CHECK_MENU_ITEM (widget), &event->area); + if (GTK_CHECK_MENU_ITEM_GET_CLASS (check_menu_item)->draw_indicator) + GTK_CHECK_MENU_ITEM_GET_CLASS (check_menu_item)->draw_indicator (check_menu_item, cr); return FALSE; } @@ -199,77 +488,174 @@ gtk_check_menu_item_expose (GtkWidget *widget, static void gtk_check_menu_item_activate (GtkMenuItem *menu_item) { - GtkCheckMenuItem *check_menu_item; + GtkCheckMenuItemPrivate *priv; - g_return_if_fail (menu_item != NULL); - g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (menu_item)); + GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item); + priv = check_menu_item->priv; - check_menu_item = GTK_CHECK_MENU_ITEM (menu_item); - check_menu_item->active = !check_menu_item->active; + priv->active = !priv->active; gtk_check_menu_item_toggled (check_menu_item); gtk_widget_queue_draw (GTK_WIDGET (check_menu_item)); -} -static void -gtk_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item, - GdkRectangle *area) -{ - g_return_if_fail (check_menu_item != NULL); - g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item)); - g_return_if_fail (CHECK_MENU_ITEM_CLASS (check_menu_item) != NULL); + GTK_MENU_ITEM_CLASS (gtk_check_menu_item_parent_class)->activate (menu_item); - if (CHECK_MENU_ITEM_CLASS (check_menu_item)->draw_indicator) - (* CHECK_MENU_ITEM_CLASS (check_menu_item)->draw_indicator) (check_menu_item, area); + g_object_notify (G_OBJECT (check_menu_item), "active"); } static void gtk_real_check_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item, - GdkRectangle *area) + cairo_t *cr) { + GtkCheckMenuItemPrivate *priv = check_menu_item->priv; GtkWidget *widget; - GtkStateType state_type; - GtkShadowType shadow_type; - gint width, height; gint x, y; - g_return_if_fail (check_menu_item != NULL); - g_return_if_fail (GTK_IS_CHECK_MENU_ITEM (check_menu_item)); + widget = GTK_WIDGET (check_menu_item); + + if (gtk_widget_is_drawable (widget)) + { + GtkAllocation allocation; + GtkStyleContext *context; + guint border_width; + guint offset; + guint toggle_size; + guint toggle_spacing; + guint horizontal_padding; + guint indicator_size; + GtkStateFlags state; + GtkBorder padding; + + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); + + gtk_widget_get_allocation (widget, &allocation); + + gtk_widget_style_get (widget, + "toggle-spacing", &toggle_spacing, + "horizontal-padding", &horizontal_padding, + "indicator-size", &indicator_size, + NULL); + + toggle_size = GTK_MENU_ITEM (check_menu_item)->priv->toggle_size; + border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); + offset = border_width + padding.left + 2; + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + { + x = offset + horizontal_padding + + (toggle_size - toggle_spacing - indicator_size) / 2; + } + else + { + x = allocation.width - + offset - horizontal_padding - toggle_size + toggle_spacing + + (toggle_size - toggle_spacing - indicator_size) / 2; + } + + y = (allocation.height - indicator_size) / 2; + + if (priv->active || + priv->always_show_toggle || + (state & GTK_STATE_FLAG_PRELIGHT)) + { + gtk_style_context_save (context); + + if (priv->inconsistent) + state |= GTK_STATE_FLAG_INCONSISTENT; + else if (priv->active) + state |= GTK_STATE_FLAG_ACTIVE; + + gtk_style_context_set_state (context, state); + + if (priv->draw_as_radio) + { + gtk_style_context_add_class (context, GTK_STYLE_CLASS_RADIO); + gtk_render_option (context, cr, x, y, + indicator_size, indicator_size); + } + else + { + gtk_style_context_add_class (context, GTK_STYLE_CLASS_CHECK); + gtk_render_check (context, cr, x, y, + indicator_size, indicator_size); + } + + gtk_style_context_restore (context); + } + } +} + + +static void +gtk_check_menu_item_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkCheckMenuItem *checkitem = GTK_CHECK_MENU_ITEM (object); + GtkCheckMenuItemPrivate *priv = checkitem->priv; + + switch (prop_id) + { + case PROP_ACTIVE: + g_value_set_boolean (value, priv->active); + break; + case PROP_INCONSISTENT: + g_value_set_boolean (value, priv->inconsistent); + break; + case PROP_DRAW_AS_RADIO: + g_value_set_boolean (value, priv->draw_as_radio); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - if (GTK_WIDGET_DRAWABLE (check_menu_item)) + +static void +gtk_check_menu_item_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkCheckMenuItem *checkitem = GTK_CHECK_MENU_ITEM (object); + + switch (prop_id) { - widget = GTK_WIDGET (check_menu_item); - - width = 8; - height = 8; - x = (GTK_CONTAINER (check_menu_item)->border_width + - widget->style->klass->xthickness + 2); - y = (widget->allocation.height - height) / 2; - - if (check_menu_item->active || - check_menu_item->always_show_toggle || - (GTK_WIDGET_STATE (check_menu_item) == GTK_STATE_PRELIGHT)) - { - state_type = GTK_WIDGET_STATE (widget); - - if (check_menu_item->always_show_toggle) - { - shadow_type = GTK_SHADOW_OUT; - if (check_menu_item->active) - shadow_type = GTK_SHADOW_IN; - } - else - { - shadow_type = GTK_SHADOW_IN; - if (check_menu_item->active && - (state_type == GTK_STATE_PRELIGHT)) - shadow_type = GTK_SHADOW_OUT; - } - - gtk_paint_check (widget->style, widget->window, - state_type, shadow_type, - area, widget, "check", - x, y, width, height); - } + case PROP_ACTIVE: + gtk_check_menu_item_set_active (checkitem, g_value_get_boolean (value)); + break; + case PROP_INCONSISTENT: + gtk_check_menu_item_set_inconsistent (checkitem, g_value_get_boolean (value)); + break; + case PROP_DRAW_AS_RADIO: + gtk_check_menu_item_set_draw_as_radio (checkitem, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } + + +/* Private */ + +/* + * _gtk_check_menu_item_set_active: + * @check_menu_item: a #GtkCheckMenuItem + * @is_active: whether the action is active or not + * + * Sets the #GtkCheckMenuItem:active property directly. This function does + * not emit signals or notifications: it is left to the caller to do so. + */ +void +_gtk_check_menu_item_set_active (GtkCheckMenuItem *check_menu_item, + gboolean is_active) +{ + GtkCheckMenuItemPrivate *priv = check_menu_item->priv; + + priv->active = is_active; +}