mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 05:31:07 +00:00
switch: Add a delayed state capability
This commit makes it possible for GtkSwitch to indicate when the underlying state changes with a delay, causing the switch to temporarily go 'out of sync' with the underlying change. https://bugzilla.gnome.org/show_bug.cgi?id=725648
This commit is contained in:
parent
4ebd2d3f7e
commit
7b11f761b3
154
gtk/gtkswitch.c
154
gtk/gtkswitch.c
@ -32,6 +32,9 @@
|
||||
* #GtkSwitch is a widget that has two states: on or off. The user can control
|
||||
* which state should be active by clicking the empty area, or by dragging the
|
||||
* handle.
|
||||
*
|
||||
* GtkSwitch can also handle situations where the underlying state changes with
|
||||
* a delay. See #GtkSwitch::state-set for details.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -64,6 +67,7 @@ struct _GtkSwitchPrivate
|
||||
gint drag_start;
|
||||
gint drag_threshold;
|
||||
|
||||
guint state : 1;
|
||||
guint is_active : 1;
|
||||
guint is_dragging : 1;
|
||||
guint in_press : 1;
|
||||
@ -75,6 +79,7 @@ enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ACTIVE,
|
||||
PROP_STATE,
|
||||
PROP_RELATED_ACTION,
|
||||
PROP_USE_ACTION_APPEARANCE,
|
||||
LAST_PROP,
|
||||
@ -85,6 +90,7 @@ enum
|
||||
enum
|
||||
{
|
||||
ACTIVATE,
|
||||
STATE_SET,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -729,6 +735,10 @@ gtk_switch_set_property (GObject *gobject,
|
||||
gtk_switch_set_active (sw, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_STATE:
|
||||
gtk_switch_set_state (sw, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_RELATED_ACTION:
|
||||
gtk_switch_set_related_action (sw, g_value_get_object (value));
|
||||
break;
|
||||
@ -764,6 +774,10 @@ gtk_switch_get_property (GObject *gobject,
|
||||
g_value_set_boolean (value, priv->is_active);
|
||||
break;
|
||||
|
||||
case PROP_STATE:
|
||||
g_value_set_boolean (value, priv->state);
|
||||
break;
|
||||
|
||||
case PROP_RELATED_ACTION:
|
||||
g_value_set_object (value, priv->action);
|
||||
break;
|
||||
@ -803,6 +817,22 @@ gtk_switch_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (gtk_switch_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
state_set (GtkSwitch *sw, gboolean state)
|
||||
{
|
||||
if (sw->priv->action_helper)
|
||||
gtk_action_helper_activate (sw->priv->action_helper);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
if (sw->priv->action)
|
||||
gtk_action_activate (sw->priv->action);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
gtk_switch_set_state (sw, state);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_switch_class_init (GtkSwitchClass *klass)
|
||||
{
|
||||
@ -836,6 +866,21 @@ gtk_switch_class_init (GtkSwitchClass *klass)
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE);
|
||||
|
||||
/**
|
||||
* GtkSwitch:state:
|
||||
*
|
||||
* The backend state that is controlled by the switch.
|
||||
* See #GtkSwitch::state-set for details.
|
||||
*
|
||||
* Since: 3.14
|
||||
*/
|
||||
switch_props[PROP_STATE] =
|
||||
g_param_spec_boolean ("state",
|
||||
P_("State"),
|
||||
P_("The backend state"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE);
|
||||
|
||||
gobject_class->set_property = gtk_switch_set_property;
|
||||
gobject_class->get_property = gtk_switch_get_property;
|
||||
gobject_class->dispose = gtk_switch_dispose;
|
||||
@ -857,6 +902,7 @@ gtk_switch_class_init (GtkSwitchClass *klass)
|
||||
widget_class->leave_notify_event = gtk_switch_leave;
|
||||
|
||||
klass->activate = gtk_switch_activate;
|
||||
klass->state_set = state_set;
|
||||
|
||||
/**
|
||||
* GtkSwitch:slider-width:
|
||||
@ -890,6 +936,38 @@ gtk_switch_class_init (GtkSwitchClass *klass)
|
||||
G_TYPE_NONE, 0);
|
||||
widget_class->activate_signal = signals[ACTIVATE];
|
||||
|
||||
/**
|
||||
* GtkSwitch::state-set:
|
||||
* @widget: the object on which the signal was emitted
|
||||
*
|
||||
* The ::state-set signal on GtkSwitch is emitted to change the underlying
|
||||
* state. It is emitted when the user changes the switch position. The
|
||||
* default handler keeps the state in sync with the #GtkState:active
|
||||
* property.
|
||||
*
|
||||
* To implement delayed state change, applications can connect to this signal,
|
||||
* initiate the change of the underlying state, and call gtk_switch_set_state()
|
||||
* when the underlying state change is complete. The signal handler should
|
||||
* return %TRUE to prevent the default handler from running.
|
||||
*
|
||||
* Visually, the underlying state is represented by the trough color of
|
||||
* the switch, while the #GtkSwitch:active property is represented by the
|
||||
* position of the switch.
|
||||
*
|
||||
* Returns: %TRUE to stop the signal emission
|
||||
*
|
||||
* Since: 3.14
|
||||
*/
|
||||
signals[STATE_SET] =
|
||||
g_signal_new (I_("state-set"),
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkSwitchClass, state_set),
|
||||
_gtk_boolean_handled_accumulator, NULL,
|
||||
_gtk_marshal_BOOLEAN__BOOLEAN,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
g_object_class_override_property (gobject_class, PROP_ACTION_NAME, "action-name");
|
||||
g_object_class_override_property (gobject_class, PROP_ACTION_TARGET, "action-target");
|
||||
|
||||
@ -945,27 +1023,17 @@ gtk_switch_set_active (GtkSwitch *sw,
|
||||
if (priv->is_active != is_active)
|
||||
{
|
||||
AtkObject *accessible;
|
||||
gboolean handled;
|
||||
|
||||
priv->is_active = is_active;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (sw), switch_props[PROP_ACTIVE]);
|
||||
|
||||
if (priv->action_helper)
|
||||
gtk_action_helper_activate (priv->action_helper);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
if (priv->action)
|
||||
gtk_action_activate (priv->action);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
g_signal_emit (sw, signals[STATE_SET], 0, is_active, &handled);
|
||||
|
||||
accessible = gtk_widget_get_accessible (GTK_WIDGET (sw));
|
||||
atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, priv->is_active);
|
||||
|
||||
if (priv->is_active)
|
||||
gtk_widget_set_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE, FALSE);
|
||||
else
|
||||
gtk_widget_unset_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (sw));
|
||||
}
|
||||
}
|
||||
@ -988,6 +1056,68 @@ gtk_switch_get_active (GtkSwitch *sw)
|
||||
return sw->priv->is_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_switch_set_state:
|
||||
* @sw: a #GtkSwitch
|
||||
* @state: the new state
|
||||
*
|
||||
* Sets the underlying state of the #GtkSwitch.
|
||||
*
|
||||
* Normally, this is the same as #GtkSwitch:active, unless the switch
|
||||
* is set up for delayed state changes. This function is typically
|
||||
* called from a #GtkSwitch::state-set signal handler.
|
||||
*
|
||||
* See #GtkSwitch::state-set for details.
|
||||
*
|
||||
* Since: 3.14
|
||||
*/
|
||||
void
|
||||
gtk_switch_set_state (GtkSwitch *sw,
|
||||
gboolean state)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_SWITCH (sw));
|
||||
|
||||
state = state != FALSE;
|
||||
|
||||
if (sw->priv->state == state)
|
||||
return;
|
||||
|
||||
sw->priv->state = state;
|
||||
|
||||
/* This will be a no-op if we're switching the state in response
|
||||
* to a UI change. We're setting active anyway, to catch 'spontaneous'
|
||||
* state changes.
|
||||
*/
|
||||
gtk_switch_set_active (sw, state);
|
||||
|
||||
if (state)
|
||||
gtk_widget_set_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE, FALSE);
|
||||
else
|
||||
gtk_widget_unset_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE);
|
||||
|
||||
g_object_notify (G_OBJECT (sw), "state");
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (sw));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_switch_get_state:
|
||||
* @sw: a #GtkSwitch
|
||||
*
|
||||
* Gets the underlying state of the #GtkSwitch.
|
||||
*
|
||||
* Returns: the underlying state
|
||||
*
|
||||
* Since: 3.14
|
||||
*/
|
||||
gboolean
|
||||
gtk_switch_get_state (GtkSwitch *sw)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SWITCH (sw), FALSE);
|
||||
|
||||
return sw->priv->state;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_switch_update (GtkActivatable *activatable,
|
||||
GtkAction *action,
|
||||
|
@ -72,6 +72,7 @@ struct _GtkSwitchClass
|
||||
|
||||
void (* activate) (GtkSwitch *sw);
|
||||
|
||||
gboolean (* state_set) (GtkSwitch *sw, gboolean state);
|
||||
/*< private >*/
|
||||
|
||||
void (* _switch_padding_1) (void);
|
||||
@ -79,7 +80,6 @@ struct _GtkSwitchClass
|
||||
void (* _switch_padding_3) (void);
|
||||
void (* _switch_padding_4) (void);
|
||||
void (* _switch_padding_5) (void);
|
||||
void (* _switch_padding_6) (void);
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@ -94,6 +94,12 @@ void gtk_switch_set_active (GtkSwitch *sw,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_switch_get_active (GtkSwitch *sw);
|
||||
|
||||
GDK_AVAILABLE_IN_3_14
|
||||
void gtk_switch_set_state (GtkSwitch *sw,
|
||||
gboolean state);
|
||||
GDK_AVAILABLE_IN_3_14
|
||||
gboolean gtk_switch_get_state (GtkSwitch *sw);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SWITCH_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user