X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktogglebutton.c;h=7b8ae49f620639faf32621703af44b32212fbf07;hb=31536736ea0fe25056689b9b7ccd914910281b37;hp=088198a7cccc35a9e2d8bf3c6a8f8fae69c6990e;hpb=f26aad1916445d25c99878138dfc384de67a2060;p=~andy%2Fgtk diff --git a/gtk/gtktogglebutton.c b/gtk/gtktogglebutton.c index 088198a7c..7b8ae49f6 100644 --- a/gtk/gtktogglebutton.c +++ b/gtk/gtktogglebutton.c @@ -24,19 +24,31 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#include +#include "config.h" + +#include "gtktogglebutton.h" + +#include "gtkbuttonprivate.h" #include "gtklabel.h" #include "gtkmain.h" #include "gtkmarshalers.h" -#include "gtktogglebutton.h" +#include "gtktoggleaction.h" +#include "gtkactivatable.h" #include "gtkprivate.h" #include "gtkintl.h" -#include "gtkalias.h" + #define DEFAULT_LEFT_POS 4 #define DEFAULT_TOP_POS 4 #define DEFAULT_SPACING 7 +struct _GtkToggleButtonPrivate +{ + guint active : 1; + guint draw_indicator : 1; + guint inconsistent : 1; +}; + enum { TOGGLED, LAST_SIGNAL @@ -50,8 +62,8 @@ enum { }; -static gint gtk_toggle_button_expose (GtkWidget *widget, - GdkEventExpose *event); +static gint gtk_toggle_button_draw (GtkWidget *widget, + cairo_t *cr); static gboolean gtk_toggle_button_mnemonic_activate (GtkWidget *widget, gboolean group_cycling); static void gtk_toggle_button_pressed (GtkButton *button); @@ -67,27 +79,36 @@ static void gtk_toggle_button_get_property (GObject *object, GParamSpec *pspec); static void gtk_toggle_button_update_state (GtkButton *button); -static guint toggle_button_signals[LAST_SIGNAL] = { 0 }; -G_DEFINE_TYPE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON); +static void gtk_toggle_button_activatable_interface_init (GtkActivatableIface *iface); +static void gtk_toggle_button_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name); +static void gtk_toggle_button_sync_action_properties (GtkActivatable *activatable, + GtkAction *action); + +static GtkActivatableIface *parent_activatable_iface; +static guint toggle_button_signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE_WITH_CODE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON, + G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, + gtk_toggle_button_activatable_interface_init)) static void gtk_toggle_button_class_init (GtkToggleButtonClass *class) { GObjectClass *gobject_class; GtkWidgetClass *widget_class; - GtkContainerClass *container_class; GtkButtonClass *button_class; gobject_class = G_OBJECT_CLASS (class); widget_class = (GtkWidgetClass*) class; - container_class = (GtkContainerClass*) class; button_class = (GtkButtonClass*) class; gobject_class->set_property = gtk_toggle_button_set_property; gobject_class->get_property = gtk_toggle_button_get_property; - widget_class->expose_event = gtk_toggle_button_expose; + widget_class->draw = gtk_toggle_button_draw; widget_class->mnemonic_activate = gtk_toggle_button_mnemonic_activate; button_class->pressed = gtk_toggle_button_pressed; @@ -102,7 +123,7 @@ gtk_toggle_button_class_init (GtkToggleButtonClass *class) PROP_ACTIVE, g_param_spec_boolean ("active", P_("Active"), - P_("If the toggle button should be pressed in or not"), + P_("If the toggle button should be pressed in"), FALSE, GTK_PARAM_READWRITE)); @@ -130,14 +151,69 @@ gtk_toggle_button_class_init (GtkToggleButtonClass *class) NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); + + g_type_class_add_private (class, sizeof (GtkToggleButtonPrivate)); } static void gtk_toggle_button_init (GtkToggleButton *toggle_button) { - toggle_button->active = FALSE; - toggle_button->draw_indicator = FALSE; - GTK_BUTTON (toggle_button)->depress_on_activate = TRUE; + GtkToggleButtonPrivate *priv; + + toggle_button->priv = G_TYPE_INSTANCE_GET_PRIVATE (toggle_button, + GTK_TYPE_TOGGLE_BUTTON, + GtkToggleButtonPrivate); + priv = toggle_button->priv; + + priv->active = FALSE; + priv->draw_indicator = FALSE; + GTK_BUTTON (toggle_button)->priv->depress_on_activate = TRUE; +} + +static void +gtk_toggle_button_activatable_interface_init (GtkActivatableIface *iface) +{ + parent_activatable_iface = g_type_interface_peek_parent (iface); + iface->update = gtk_toggle_button_update; + iface->sync_action_properties = gtk_toggle_button_sync_action_properties; +} + +static void +gtk_toggle_button_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name) +{ + GtkToggleButton *button; + + parent_activatable_iface->update (activatable, action, property_name); + + button = GTK_TOGGLE_BUTTON (activatable); + + if (strcmp (property_name, "active") == 0) + { + gtk_action_block_activate (action); + gtk_toggle_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); + gtk_action_unblock_activate (action); + } + +} + +static void +gtk_toggle_button_sync_action_properties (GtkActivatable *activatable, + GtkAction *action) +{ + GtkToggleButton *button; + + parent_activatable_iface->sync_action_properties (activatable, action); + + if (!GTK_IS_TOGGLE_ACTION (action)) + return; + + button = GTK_TOGGLE_BUTTON (activatable); + + gtk_action_block_activate (action); + gtk_toggle_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); + gtk_action_unblock_activate (action); } @@ -194,6 +270,7 @@ gtk_toggle_button_set_property (GObject *object, gtk_toggle_button_set_mode (tb, g_value_get_boolean (value)); break; default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } @@ -204,20 +281,19 @@ gtk_toggle_button_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - GtkToggleButton *tb; - - tb = GTK_TOGGLE_BUTTON (object); + GtkToggleButton *tb = GTK_TOGGLE_BUTTON (object); + GtkToggleButtonPrivate *priv = tb->priv; switch (prop_id) { case PROP_ACTIVE: - g_value_set_boolean (value, tb->active); + g_value_set_boolean (value, priv->active); break; case PROP_INCONSISTENT: - g_value_set_boolean (value, tb->inconsistent); + g_value_set_boolean (value, priv->inconsistent); break; case PROP_DRAW_INDICATOR: - g_value_set_boolean (value, tb->draw_indicator); + g_value_set_boolean (value, priv->draw_indicator); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -243,23 +319,35 @@ void gtk_toggle_button_set_mode (GtkToggleButton *toggle_button, gboolean draw_indicator) { - GtkWidget *widget; + GtkToggleButtonPrivate *priv; g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button)); - widget = GTK_WIDGET (toggle_button); + priv = toggle_button->priv; draw_indicator = draw_indicator ? TRUE : FALSE; - if (toggle_button->draw_indicator != draw_indicator) + if (priv->draw_indicator != draw_indicator) { - toggle_button->draw_indicator = draw_indicator; - GTK_BUTTON (toggle_button)->depress_on_activate = !draw_indicator; - - if (GTK_WIDGET_VISIBLE (toggle_button)) + GtkStyleContext *context; + + priv->draw_indicator = draw_indicator; + GTK_BUTTON (toggle_button)->priv->depress_on_activate = !draw_indicator; + + if (gtk_widget_get_visible (GTK_WIDGET (toggle_button))) gtk_widget_queue_resize (GTK_WIDGET (toggle_button)); g_object_notify (G_OBJECT (toggle_button), "draw-indicator"); + + /* Make toggle buttons conditionally have the "button" + * class depending on draw_indicator. + */ + context = gtk_widget_get_style_context (GTK_WIDGET (toggle_button)); + + if (draw_indicator) + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BUTTON); + else + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON); } } @@ -278,28 +366,38 @@ gtk_toggle_button_get_mode (GtkToggleButton *toggle_button) { g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button), FALSE); - return toggle_button->draw_indicator; + return toggle_button->priv->draw_indicator; } void gtk_toggle_button_set_active (GtkToggleButton *toggle_button, gboolean is_active) { + GtkToggleButtonPrivate *priv; + g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button)); + priv = toggle_button->priv; + is_active = is_active != FALSE; - if (toggle_button->active != is_active) + if (priv->active != is_active) gtk_button_clicked (GTK_BUTTON (toggle_button)); } +void +_gtk_toggle_button_set_active (GtkToggleButton *toggle_button, + gboolean is_active) +{ + toggle_button->priv->active = is_active; +} gboolean gtk_toggle_button_get_active (GtkToggleButton *toggle_button) { g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button), FALSE); - return (toggle_button->active) ? TRUE : FALSE; + return toggle_button->priv->active; } @@ -330,14 +428,18 @@ void gtk_toggle_button_set_inconsistent (GtkToggleButton *toggle_button, gboolean setting) { + GtkToggleButtonPrivate *priv; + g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button)); - + + priv = toggle_button->priv; + setting = setting != FALSE; - if (setting != toggle_button->inconsistent) + if (setting != priv->inconsistent) { - toggle_button->inconsistent = setting; - + priv->inconsistent = setting; + gtk_toggle_button_update_state (GTK_BUTTON (toggle_button)); gtk_widget_queue_draw (GTK_WIDGET (toggle_button)); @@ -358,38 +460,40 @@ gtk_toggle_button_get_inconsistent (GtkToggleButton *toggle_button) { g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button), FALSE); - return toggle_button->inconsistent; + return toggle_button->priv->inconsistent; } static gint -gtk_toggle_button_expose (GtkWidget *widget, - GdkEventExpose *event) +gtk_toggle_button_draw (GtkWidget *widget, + cairo_t *cr) { - if (GTK_WIDGET_DRAWABLE (widget)) - { - GtkWidget *child = GTK_BIN (widget)->child; - GtkButton *button = GTK_BUTTON (widget); - GtkStateType state_type; - GtkShadowType shadow_type; - - state_type = GTK_WIDGET_STATE (widget); - - if (GTK_TOGGLE_BUTTON (widget)->inconsistent) - { - if (state_type == GTK_STATE_ACTIVE) - state_type = GTK_STATE_NORMAL; - shadow_type = GTK_SHADOW_ETCHED_IN; - } - else - shadow_type = button->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT; + GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (widget); + GtkToggleButtonPrivate *priv = toggle_button->priv; + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + GtkButton *button = GTK_BUTTON (widget); + GtkStateType state_type; + GtkShadowType shadow_type; - _gtk_button_paint (button, &event->area, state_type, shadow_type, - "togglebutton", "togglebuttondefault"); + state_type = gtk_widget_get_state (widget); - if (child) - gtk_container_propagate_expose (GTK_CONTAINER (widget), child, event); + if (priv->inconsistent) + { + if (state_type == GTK_STATE_ACTIVE) + state_type = GTK_STATE_NORMAL; + shadow_type = GTK_SHADOW_ETCHED_IN; } - + else + shadow_type = button->priv->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT; + + _gtk_button_paint (button, cr, + gtk_widget_get_allocated_width (widget), + gtk_widget_get_allocated_height (widget), + state_type, shadow_type, + "togglebutton", "togglebuttondefault"); + + if (child) + gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr); + return FALSE; } @@ -402,7 +506,7 @@ gtk_toggle_button_mnemonic_activate (GtkWidget *widget, * gtk_widget_real_mnemonic_activate() in order to focus the widget even * if there is no mnemonic conflict. */ - if (GTK_WIDGET_CAN_FOCUS (widget)) + if (gtk_widget_get_can_focus (widget)) gtk_widget_grab_focus (widget); if (!group_cycling) @@ -414,7 +518,7 @@ gtk_toggle_button_mnemonic_activate (GtkWidget *widget, static void gtk_toggle_button_pressed (GtkButton *button) { - button->button_down = TRUE; + button->priv->button_down = TRUE; gtk_toggle_button_update_state (button); gtk_widget_queue_draw (GTK_WIDGET (button)); @@ -423,11 +527,11 @@ gtk_toggle_button_pressed (GtkButton *button) static void gtk_toggle_button_released (GtkButton *button) { - if (button->button_down) + if (button->priv->button_down) { - button->button_down = FALSE; + button->priv->button_down = FALSE; - if (button->in_button) + if (button->priv->in_button) gtk_button_clicked (button); gtk_toggle_button_update_state (button); @@ -439,41 +543,48 @@ static void gtk_toggle_button_clicked (GtkButton *button) { GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button); - toggle_button->active = !toggle_button->active; + GtkToggleButtonPrivate *priv = toggle_button->priv; + + priv->active = !priv->active; gtk_toggle_button_toggled (toggle_button); gtk_toggle_button_update_state (button); g_object_notify (G_OBJECT (toggle_button), "active"); + + if (GTK_BUTTON_CLASS (gtk_toggle_button_parent_class)->clicked) + GTK_BUTTON_CLASS (gtk_toggle_button_parent_class)->clicked (button); } static void gtk_toggle_button_update_state (GtkButton *button) { GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (button); + GtkToggleButtonPrivate *priv = toggle_button->priv; gboolean depressed, touchscreen; - GtkStateType new_state; + GtkStateFlags new_state = 0; g_object_get (gtk_widget_get_settings (GTK_WIDGET (button)), "gtk-touchscreen-mode", &touchscreen, NULL); - if (toggle_button->inconsistent) + if (priv->inconsistent) + new_state |= GTK_STATE_FLAG_INCONSISTENT; + + if (priv->inconsistent) depressed = FALSE; - else if (button->in_button && button->button_down) + else if (button->priv->in_button && button->priv->button_down) depressed = TRUE; else - depressed = toggle_button->active; - - if (!touchscreen && button->in_button && (!button->button_down || toggle_button->draw_indicator)) - new_state = GTK_STATE_PRELIGHT; - else - new_state = depressed ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL; + depressed = priv->active; - _gtk_button_set_depressed (button, depressed); - gtk_widget_set_state (GTK_WIDGET (toggle_button), new_state); -} + if (!touchscreen && button->priv->in_button && (!button->priv->button_down || priv->draw_indicator)) + new_state |= GTK_STATE_FLAG_PRELIGHT; -#define __GTK_TOGGLE_BUTTON_C__ -#include "gtkaliasdef.c" + if (depressed) + new_state |= GTK_STATE_FLAG_ACTIVE; + + _gtk_button_set_depressed (button, depressed); + gtk_widget_set_state_flags (GTK_WIDGET (toggle_button), new_state, TRUE); +}