St: drop StClickable, add some functionality to StButton
For historical reasons, we had both StClickable and StButton, which were nearly identical. StButton was more widely-used, so keep that and port all StClickable users to that. https://bugzilla.gnome.org/show_bug.cgi?id=640583
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
|
||||
#include "st-button.h"
|
||||
|
||||
#include "st-enum-types.h"
|
||||
#include "st-marshal.h"
|
||||
#include "st-texture-cache.h"
|
||||
#include "st-private.h"
|
||||
@@ -49,8 +50,10 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_LABEL,
|
||||
PROP_BUTTON_MASK,
|
||||
PROP_TOGGLE_MODE,
|
||||
PROP_CHECKED
|
||||
PROP_CHECKED,
|
||||
PROP_PRESSED
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -65,14 +68,16 @@ enum
|
||||
|
||||
struct _StButtonPrivate
|
||||
{
|
||||
gchar *text;
|
||||
gchar *text;
|
||||
|
||||
guint is_pressed : 1;
|
||||
guint is_checked : 1;
|
||||
guint is_toggle : 1;
|
||||
guint has_grab : 1;
|
||||
guint button_mask : 3;
|
||||
guint is_toggle : 1;
|
||||
|
||||
gint spacing;
|
||||
guint pressed : 3;
|
||||
guint grabbed : 3;
|
||||
guint is_checked : 1;
|
||||
|
||||
gint spacing;
|
||||
};
|
||||
|
||||
static guint button_signals[LAST_SIGNAL] = { 0, };
|
||||
@@ -119,31 +124,32 @@ st_button_style_changed (StWidget *widget)
|
||||
}
|
||||
|
||||
static void
|
||||
st_button_press (StButton *button)
|
||||
st_button_press (StButton *button,
|
||||
StButtonMask mask)
|
||||
{
|
||||
if (button->priv->is_pressed)
|
||||
return;
|
||||
if (button->priv->pressed == 0)
|
||||
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
|
||||
|
||||
button->priv->is_pressed = TRUE;
|
||||
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
|
||||
button->priv->pressed |= mask;
|
||||
}
|
||||
|
||||
static void
|
||||
st_button_release (StButton *button,
|
||||
gboolean clicked)
|
||||
st_button_release (StButton *button,
|
||||
StButtonMask mask,
|
||||
int clicked_button)
|
||||
{
|
||||
if (!button->priv->is_pressed)
|
||||
button->priv->pressed &= ~mask;
|
||||
if (button->priv->pressed != 0)
|
||||
return;
|
||||
|
||||
button->priv->is_pressed = FALSE;
|
||||
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
|
||||
|
||||
if (clicked)
|
||||
if (clicked_button)
|
||||
{
|
||||
if (button->priv->is_toggle)
|
||||
st_button_set_checked (button, !button->priv->is_checked);
|
||||
|
||||
g_signal_emit (button, button_signals[CLICKED], 0);
|
||||
g_signal_emit (button, button_signals[CLICKED], 0, clicked_button);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,15 +157,18 @@ static gboolean
|
||||
st_button_button_press (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
|
||||
|
||||
st_widget_hide_tooltip (ST_WIDGET (actor));
|
||||
|
||||
if (event->button == 1)
|
||||
if (button->priv->button_mask & mask)
|
||||
{
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
if (button->priv->grabbed == 0)
|
||||
clutter_grab_pointer (actor);
|
||||
|
||||
clutter_grab_pointer (actor);
|
||||
button->priv->has_grab = TRUE;
|
||||
st_button_press (button);
|
||||
button->priv->grabbed |= mask;
|
||||
st_button_press (button, mask);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -171,19 +180,19 @@ static gboolean
|
||||
st_button_button_release (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
if (event->button == 1)
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
|
||||
|
||||
if (button->priv->button_mask & mask)
|
||||
{
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
gboolean is_click;
|
||||
|
||||
is_click = button->priv->has_grab && st_widget_get_hover (ST_WIDGET (button));
|
||||
st_button_release (button, is_click);
|
||||
is_click = button->priv->grabbed && st_widget_get_hover (ST_WIDGET (button));
|
||||
st_button_release (button, mask, is_click ? event->button : 0);
|
||||
|
||||
if (button->priv->has_grab)
|
||||
{
|
||||
button->priv->has_grab = FALSE;
|
||||
clutter_ungrab_pointer ();
|
||||
}
|
||||
button->priv->grabbed &= ~mask;
|
||||
if (button->priv->grabbed == 0)
|
||||
clutter_ungrab_pointer ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -195,13 +204,18 @@ static gboolean
|
||||
st_button_key_press (ClutterActor *actor,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
|
||||
st_widget_hide_tooltip (ST_WIDGET (actor));
|
||||
|
||||
if (event->keyval == CLUTTER_KEY_space ||
|
||||
event->keyval == CLUTTER_KEY_Return)
|
||||
if (button->priv->button_mask & ST_BUTTON_ONE)
|
||||
{
|
||||
st_button_press (ST_BUTTON (actor));
|
||||
return TRUE;
|
||||
if (event->keyval == CLUTTER_KEY_space ||
|
||||
event->keyval == CLUTTER_KEY_Return)
|
||||
{
|
||||
st_button_press (button, ST_BUTTON_ONE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -211,16 +225,34 @@ static gboolean
|
||||
st_button_key_release (ClutterActor *actor,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
if (event->keyval == CLUTTER_KEY_space ||
|
||||
event->keyval == CLUTTER_KEY_Return)
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
|
||||
if (button->priv->button_mask & ST_BUTTON_ONE)
|
||||
{
|
||||
st_button_release (ST_BUTTON (actor), TRUE);
|
||||
return TRUE;
|
||||
if (event->keyval == CLUTTER_KEY_space ||
|
||||
event->keyval == CLUTTER_KEY_Return)
|
||||
{
|
||||
st_button_release (button, ST_BUTTON_ONE, 1);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
st_button_key_focus_out (ClutterActor *actor)
|
||||
{
|
||||
StButton *button = ST_BUTTON (actor);
|
||||
|
||||
/* If we lose focus between a key press and release, undo the press */
|
||||
if ((button->priv->pressed & ST_BUTTON_ONE) &&
|
||||
!(button->priv->grabbed & ST_BUTTON_ONE))
|
||||
st_button_release (button, ST_BUTTON_ONE, 0);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (st_button_parent_class)->key_focus_out (actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
st_button_enter (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
@@ -230,12 +262,12 @@ st_button_enter (ClutterActor *actor,
|
||||
|
||||
ret = CLUTTER_ACTOR_CLASS (st_button_parent_class)->enter_event (actor, event);
|
||||
|
||||
if (button->priv->has_grab)
|
||||
if (button->priv->grabbed)
|
||||
{
|
||||
if (st_widget_get_hover (ST_WIDGET (button)))
|
||||
st_button_press (button);
|
||||
st_button_press (button, button->priv->grabbed);
|
||||
else
|
||||
st_button_release (button, FALSE);
|
||||
st_button_release (button, button->priv->grabbed, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -250,12 +282,12 @@ st_button_leave (ClutterActor *actor,
|
||||
|
||||
ret = CLUTTER_ACTOR_CLASS (st_button_parent_class)->leave_event (actor, event);
|
||||
|
||||
if (button->priv->has_grab)
|
||||
if (button->priv->grabbed)
|
||||
{
|
||||
if (st_widget_get_hover (ST_WIDGET (button)))
|
||||
st_button_press (button);
|
||||
st_button_press (button, button->priv->grabbed);
|
||||
else
|
||||
st_button_release (button, FALSE);
|
||||
st_button_release (button, button->priv->grabbed, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -274,6 +306,9 @@ st_button_set_property (GObject *gobject,
|
||||
case PROP_LABEL:
|
||||
st_button_set_label (button, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_BUTTON_MASK:
|
||||
st_button_set_button_mask (button, g_value_get_flags (value));
|
||||
break;
|
||||
case PROP_TOGGLE_MODE:
|
||||
st_button_set_toggle_mode (button, g_value_get_boolean (value));
|
||||
break;
|
||||
@@ -301,12 +336,18 @@ st_button_get_property (GObject *gobject,
|
||||
case PROP_LABEL:
|
||||
g_value_set_string (value, priv->text);
|
||||
break;
|
||||
case PROP_BUTTON_MASK:
|
||||
g_value_set_flags (value, priv->button_mask);
|
||||
break;
|
||||
case PROP_TOGGLE_MODE:
|
||||
g_value_set_boolean (value, priv->is_toggle);
|
||||
break;
|
||||
case PROP_CHECKED:
|
||||
g_value_set_boolean (value, priv->is_checked);
|
||||
break;
|
||||
case PROP_PRESSED:
|
||||
g_value_set_boolean (value, priv->pressed != 0);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
@@ -343,6 +384,7 @@ st_button_class_init (StButtonClass *klass)
|
||||
actor_class->button_release_event = st_button_button_release;
|
||||
actor_class->key_press_event = st_button_key_press;
|
||||
actor_class->key_release_event = st_button_key_release;
|
||||
actor_class->key_focus_out = st_button_key_focus_out;
|
||||
actor_class->enter_event = st_button_enter;
|
||||
actor_class->leave_event = st_button_leave;
|
||||
|
||||
@@ -354,6 +396,13 @@ st_button_class_init (StButtonClass *klass)
|
||||
NULL, G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
|
||||
|
||||
pspec = g_param_spec_flags ("button-mask",
|
||||
"Button mask",
|
||||
"Which buttons trigger the 'clicked' signal",
|
||||
ST_TYPE_BUTTON_MASK, ST_BUTTON_ONE,
|
||||
G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_BUTTON_MASK, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("toggle-mode",
|
||||
"Toggle Mode",
|
||||
"Enable or disable toggling",
|
||||
@@ -367,23 +416,30 @@ st_button_class_init (StButtonClass *klass)
|
||||
FALSE, G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_CHECKED, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("pressed",
|
||||
"Pressed",
|
||||
"Indicates if the button is pressed in",
|
||||
FALSE, G_PARAM_READABLE);
|
||||
g_object_class_install_property (gobject_class, PROP_PRESSED, pspec);
|
||||
|
||||
|
||||
/**
|
||||
* StButton::clicked:
|
||||
* @button: the object that received the signal
|
||||
* @clicked_button: the mouse button that was used
|
||||
*
|
||||
* Emitted when the user activates the button, either with a mouse press and
|
||||
* release or with the keyboard.
|
||||
*/
|
||||
|
||||
button_signals[CLICKED] =
|
||||
g_signal_new ("clicked",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (StButtonClass, clicked),
|
||||
NULL, NULL,
|
||||
_st_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
_st_marshal_VOID__INT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_INT);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -391,6 +447,7 @@ st_button_init (StButton *button)
|
||||
{
|
||||
button->priv = ST_BUTTON_GET_PRIVATE (button);
|
||||
button->priv->spacing = 6;
|
||||
button->priv->button_mask = ST_BUTTON_ONE;
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (button), TRUE);
|
||||
st_widget_set_track_hover (ST_WIDGET (button), TRUE);
|
||||
@@ -431,7 +488,7 @@ st_button_new_with_label (const gchar *text)
|
||||
*
|
||||
* Returns: the text for the button. This must not be freed by the application
|
||||
*/
|
||||
G_CONST_RETURN gchar *
|
||||
const gchar *
|
||||
st_button_get_label (StButton *button)
|
||||
{
|
||||
g_return_val_if_fail (ST_IS_BUTTON (button), NULL);
|
||||
@@ -487,6 +544,42 @@ st_button_set_label (StButton *button,
|
||||
g_object_notify (G_OBJECT (button), "label");
|
||||
}
|
||||
|
||||
/**
|
||||
* st_button_get_button_mask:
|
||||
* @button: a #StButton
|
||||
*
|
||||
* Gets the mask of mouse buttons that @button emits the
|
||||
* #StButton::clicked signal for.
|
||||
*
|
||||
* Returns: the mask of mouse buttons that @button emits the
|
||||
* #StButton::clicked signal for.
|
||||
*/
|
||||
StButtonMask
|
||||
st_button_get_button_mask (StButton *button)
|
||||
{
|
||||
g_return_val_if_fail (ST_IS_BUTTON (button), 0);
|
||||
|
||||
return button->priv->button_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* st_button_set_button_mask:
|
||||
* @button: a #Stbutton
|
||||
* @mask: the mask of mouse buttons that @button responds to
|
||||
*
|
||||
* Sets which mouse buttons @button emits #StButton::clicked for.
|
||||
*/
|
||||
void
|
||||
st_button_set_button_mask (StButton *button,
|
||||
StButtonMask mask)
|
||||
{
|
||||
g_return_if_fail (ST_IS_BUTTON (button));
|
||||
|
||||
button->priv->button_mask = mask;
|
||||
|
||||
g_object_notify (G_OBJECT (button), "button-mask");
|
||||
}
|
||||
|
||||
/**
|
||||
* st_button_get_toggle_mode:
|
||||
* @button: a #StButton
|
||||
@@ -564,3 +657,29 @@ st_button_set_checked (StButton *button,
|
||||
|
||||
g_object_notify (G_OBJECT (button), "checked");
|
||||
}
|
||||
|
||||
/**
|
||||
* st_button_fake_release:
|
||||
* @button: an #StButton
|
||||
*
|
||||
* If this widget is holding a pointer grab, this function will
|
||||
* will ungrab it, and reset the pressed state. The effect is
|
||||
* similar to if the user had released the mouse button, but without
|
||||
* emitting the clicked signal.
|
||||
*
|
||||
* This function is useful if for example you want to do something
|
||||
* after the user is holding the mouse button for a given period of
|
||||
* time, breaking the grab.
|
||||
*/
|
||||
void
|
||||
st_button_fake_release (StButton *button)
|
||||
{
|
||||
if (button->priv->pressed)
|
||||
st_button_release (button, button->priv->pressed, 0);
|
||||
|
||||
if (button->priv->grabbed)
|
||||
{
|
||||
button->priv->grabbed = 0;
|
||||
clutter_ungrab_pointer ();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user