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. */
|
* not all properties may be set yet. */
|
||||||
guint is_constructing : 1;
|
guint is_constructing : 1;
|
||||||
|
|
||||||
|
GHashTable *transitions;
|
||||||
|
|
||||||
gdouble lower;
|
gdouble lower;
|
||||||
gdouble upper;
|
gdouble upper;
|
||||||
gdouble value;
|
gdouble value;
|
||||||
@ -85,6 +87,14 @@ enum
|
|||||||
|
|
||||||
static guint signals[LAST_SIGNAL] = { 0, };
|
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,
|
static gboolean st_adjustment_set_lower (StAdjustment *adjustment,
|
||||||
gdouble lower);
|
gdouble lower);
|
||||||
static gboolean st_adjustment_set_upper (StAdjustment *adjustment,
|
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
|
static void
|
||||||
st_adjustment_class_init (StAdjustmentClass *klass)
|
st_adjustment_class_init (StAdjustmentClass *klass)
|
||||||
{
|
{
|
||||||
@ -209,6 +230,7 @@ st_adjustment_class_init (StAdjustmentClass *klass)
|
|||||||
object_class->constructed = st_adjustment_constructed;
|
object_class->constructed = st_adjustment_constructed;
|
||||||
object_class->get_property = st_adjustment_get_property;
|
object_class->get_property = st_adjustment_get_property;
|
||||||
object_class->set_property = st_adjustment_set_property;
|
object_class->set_property = st_adjustment_set_property;
|
||||||
|
object_class->dispose = st_adjustment_dispose;
|
||||||
|
|
||||||
props[PROP_LOWER] =
|
props[PROP_LOWER] =
|
||||||
g_param_spec_double ("lower", "Lower", "Lower bound",
|
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;
|
new_value = priv->value + delta * scroll_unit;
|
||||||
st_adjustment_set_value (adjustment, new_value);
|
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,
|
void st_adjustment_adjust_for_scroll_event (StAdjustment *adjustment,
|
||||||
gdouble delta);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __ST_ADJUSTMENT_H__ */
|
#endif /* __ST_ADJUSTMENT_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user