st: Add transition API to StAdjustment
StAdjustment implements the ClutterAnimatable interface, so we can already animate its properties with ClutterPropertyTransitions. But as it is currently not possible to associate a transition with an adjustment, it must be owned (and kept alive in case of GC) by the calling code. Change that by implementing the same (add|remove|get)_transition() API as ClutterActor, so we can use a familiar API and even duck typing in case of javascript. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/669
This commit is contained in:
parent
79b54f65b4
commit
9097c5e9c0
@ -45,6 +45,8 @@ struct _StAdjustmentPrivate
|
||||
* not all properties may be set yet. */
|
||||
guint is_constructing : 1;
|
||||
|
||||
GHashTable *transitions;
|
||||
|
||||
gdouble lower;
|
||||
gdouble upper;
|
||||
gdouble value;
|
||||
@ -85,6 +87,14 @@ enum
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
typedef struct _TransitionClosure
|
||||
{
|
||||
StAdjustment *adjustment;
|
||||
ClutterTransition *transition;
|
||||
char *name;
|
||||
gulong completed_id;
|
||||
} TransitionClosure;
|
||||
|
||||
static gboolean st_adjustment_set_lower (StAdjustment *adjustment,
|
||||
gdouble lower);
|
||||
static gboolean st_adjustment_set_upper (StAdjustment *adjustment,
|
||||
@ -201,6 +211,17 @@ st_adjustment_set_property (GObject *gobject,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_adjustment_dispose (GObject *object)
|
||||
{
|
||||
StAdjustmentPrivate *priv;
|
||||
|
||||
priv = st_adjustment_get_instance_private (ST_ADJUSTMENT (object));
|
||||
g_clear_pointer (&priv->transitions, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (st_adjustment_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
st_adjustment_class_init (StAdjustmentClass *klass)
|
||||
{
|
||||
@ -209,6 +230,7 @@ st_adjustment_class_init (StAdjustmentClass *klass)
|
||||
object_class->constructed = st_adjustment_constructed;
|
||||
object_class->get_property = st_adjustment_get_property;
|
||||
object_class->set_property = st_adjustment_set_property;
|
||||
object_class->dispose = st_adjustment_dispose;
|
||||
|
||||
props[PROP_LOWER] =
|
||||
g_param_spec_double ("lower", "Lower", "Lower bound",
|
||||
@ -588,3 +610,145 @@ st_adjustment_adjust_for_scroll_event (StAdjustment *adjustment,
|
||||
new_value = priv->value + delta * scroll_unit;
|
||||
st_adjustment_set_value (adjustment, new_value);
|
||||
}
|
||||
|
||||
static void
|
||||
transition_closure_free (gpointer data)
|
||||
{
|
||||
TransitionClosure *clos;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
if (G_UNLIKELY (data == NULL))
|
||||
return;
|
||||
|
||||
clos = data;
|
||||
timeline = CLUTTER_TIMELINE (clos->transition);
|
||||
|
||||
g_signal_handler_disconnect (clos->transition, clos->completed_id);
|
||||
|
||||
if (clutter_timeline_is_playing (timeline))
|
||||
clutter_timeline_stop (timeline);
|
||||
|
||||
g_object_unref (clos->transition);
|
||||
g_free (clos->name);
|
||||
g_free (clos);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_transition (StAdjustment *adjustment,
|
||||
const char *name)
|
||||
{
|
||||
StAdjustmentPrivate *priv = st_adjustment_get_instance_private (adjustment);
|
||||
|
||||
g_hash_table_remove (priv->transitions, name);
|
||||
|
||||
if (g_hash_table_size (priv->transitions) == 0)
|
||||
g_clear_pointer (&priv->transitions, g_hash_table_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
on_transition_stopped (ClutterTransition *transition,
|
||||
gboolean is_finished,
|
||||
TransitionClosure *clos)
|
||||
{
|
||||
StAdjustment *adjustment = clos->adjustment;
|
||||
|
||||
if (!clutter_transition_get_remove_on_complete (transition))
|
||||
return;
|
||||
|
||||
/* Take a reference, because removing the closure will
|
||||
* release the reference on the transition, and we want
|
||||
* it to survive the signal emission; ClutterTransition's
|
||||
* own ::stopped signal closure will release it after all
|
||||
* other handlers have run.
|
||||
*/
|
||||
g_object_ref (transition);
|
||||
|
||||
remove_transition (adjustment, clos->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* st_adjustment_get_transition:
|
||||
* Returns: (transfer none) (nullable):
|
||||
*/
|
||||
ClutterTransition *
|
||||
st_adjustment_get_transition (StAdjustment *adjustment,
|
||||
const char *name)
|
||||
{
|
||||
StAdjustmentPrivate *priv;
|
||||
TransitionClosure *clos;
|
||||
|
||||
g_return_val_if_fail (ST_IS_ADJUSTMENT (adjustment), NULL);
|
||||
|
||||
priv = st_adjustment_get_instance_private (adjustment);
|
||||
|
||||
if (priv->transitions == NULL)
|
||||
return NULL;
|
||||
|
||||
clos = g_hash_table_lookup (priv->transitions, name);
|
||||
if (clos == NULL)
|
||||
return NULL;
|
||||
|
||||
return clos->transition;
|
||||
}
|
||||
|
||||
void
|
||||
st_adjustment_add_transition (StAdjustment *adjustment,
|
||||
const char *name,
|
||||
ClutterTransition *transition)
|
||||
{
|
||||
StAdjustmentPrivate *priv;
|
||||
TransitionClosure *clos;
|
||||
|
||||
g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
|
||||
g_return_if_fail (name != NULL);
|
||||
g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
|
||||
|
||||
priv = st_adjustment_get_instance_private (adjustment);
|
||||
|
||||
if (priv->transitions == NULL)
|
||||
priv->transitions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL,
|
||||
transition_closure_free);
|
||||
|
||||
if (g_hash_table_lookup (priv->transitions, name) != NULL)
|
||||
{
|
||||
g_warning ("A transition with name '%s' already exists for "
|
||||
"adjustment '%p'", name, adjustment);
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_transition_set_animatable (transition, CLUTTER_ANIMATABLE (adjustment));
|
||||
|
||||
clos = g_new (TransitionClosure, 1);
|
||||
clos->adjustment = adjustment;
|
||||
clos->transition = g_object_ref (transition);
|
||||
clos->name = g_strdup (name);
|
||||
clos->completed_id = g_signal_connect (transition, "stopped",
|
||||
G_CALLBACK (on_transition_stopped),
|
||||
clos);
|
||||
|
||||
g_hash_table_insert (priv->transitions, clos->name, clos);
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (transition));
|
||||
}
|
||||
|
||||
void
|
||||
st_adjustment_remove_transition (StAdjustment *adjustment,
|
||||
const char *name)
|
||||
{
|
||||
StAdjustmentPrivate *priv;
|
||||
TransitionClosure *clos;
|
||||
|
||||
g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
priv = st_adjustment_get_instance_private (adjustment);
|
||||
|
||||
if (priv->transitions == NULL)
|
||||
return;
|
||||
|
||||
clos = g_hash_table_lookup (priv->transitions, name);
|
||||
if (clos == NULL)
|
||||
return;
|
||||
|
||||
remove_transition (adjustment, name);
|
||||
}
|
||||
|
@ -78,6 +78,14 @@ void st_adjustment_get_values (StAdjustment *adjustment,
|
||||
void st_adjustment_adjust_for_scroll_event (StAdjustment *adjustment,
|
||||
gdouble delta);
|
||||
|
||||
ClutterTransition * st_adjustment_get_transition (StAdjustment *adjustment,
|
||||
const char *name);
|
||||
void st_adjustment_add_transition (StAdjustment *adjustment,
|
||||
const char *name,
|
||||
ClutterTransition *transition);
|
||||
void st_adjustment_remove_transition (StAdjustment *adjustment,
|
||||
const char *name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __ST_ADJUSTMENT_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user