From 499534f3ac44022b3204161bc12656d7fce36602 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 29 Mar 2012 13:53:40 +0100 Subject: [PATCH] actor: Make :content-gravity animatable Let's start making some non-trivial property animatable, like the content gravity. --- clutter/clutter-actor.c | 85 +++++++++++++++++++++++++++--- tests/interactive/test-image-box.c | 2 + 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index a79549af1..906f2c0ae 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -705,6 +705,7 @@ struct _ClutterActorPrivate /* delegate object used to paint the contents of this actor */ ClutterContent *content; + ClutterActorBox content_box; ClutterContentGravity content_gravity; ClutterScalingFilter min_filter; ClutterScalingFilter mag_filter; @@ -768,6 +769,7 @@ struct _ClutterActorPrivate queued without an effect. */ guint is_dirty : 1; guint bg_color_set : 1; + guint content_box_valid : 1; }; enum @@ -2259,7 +2261,10 @@ clutter_actor_set_allocation_internal (ClutterActor *self, /* if the allocation changes, so does the content box */ if (priv->content != NULL) - g_object_notify_by_pspec (obj, obj_props[PROP_CONTENT_BOX]); + { + priv->content_box_valid = FALSE; + g_object_notify_by_pspec (obj, obj_props[PROP_CONTENT_BOX]); + } retval = TRUE; } @@ -6443,6 +6448,8 @@ clutter_actor_class_init (ClutterActorClass *klass) * that have a preferred size, and if the preferred size is smaller than * the actor's allocation. * + * The #ClutterActor:content-gravity property is animatable. + * * Since: 1.10 */ obj_props[PROP_CONTENT_GRAVITY] = @@ -6471,7 +6478,9 @@ clutter_actor_class_init (ClutterActorClass *klass) P_("Content Box"), P_("The bounding box of the actor's content"), CLUTTER_TYPE_ACTOR_BOX, - CLUTTER_PARAM_READABLE); + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); obj_props[PROP_MINIFICATION_FILTER] = g_param_spec_enum ("minification-filter", @@ -12320,6 +12329,23 @@ clutter_actor_set_anchor_point_from_gravity (ClutterActor *self, } } +static void +clutter_actor_store_content_box (ClutterActor *self, + const ClutterActorBox *box) +{ + if (box != NULL) + { + self->priv->content_box = *box; + self->priv->content_box_valid = TRUE; + } + else + self->priv->content_box_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_BOX]); +} + static void clutter_container_iface_init (ClutterContainerIface *iface) { @@ -13005,6 +13031,10 @@ clutter_actor_set_animatable_property (ClutterActor *actor, g_value_get_double (value)); break; + case PROP_CONTENT_BOX: + clutter_actor_store_content_box (actor, g_value_get_boxed (value)); + break; + default: g_object_set_property (obj, pspec->name, value); break; @@ -17002,9 +17032,12 @@ transition_closure_free (gpointer data) if (G_LIKELY (data != NULL)) { TransitionClosure *clos = data; + ClutterTimeline *timeline; - if (clutter_timeline_is_playing (CLUTTER_TIMELINE (clos->transition))) - clutter_timeline_stop (CLUTTER_TIMELINE (clos->transition)); + timeline = CLUTTER_TIMELINE (clos->transition); + + if (clutter_timeline_is_playing (timeline)) + clutter_timeline_stop (timeline); g_signal_handler_disconnect (clos->transition, clos->completed_id); @@ -17022,6 +17055,9 @@ on_transition_completed (ClutterTransition *transition, ClutterActor *actor = clos->actor; ClutterAnimationInfo *info; + /* reset the caches used by animations */ + clutter_actor_store_content_box (actor, NULL); + info = _clutter_actor_get_animation_info (actor); /* this will take care of cleaning clos for us */ @@ -17787,6 +17823,8 @@ clutter_actor_get_content (ClutterActor *self) * See the description of the #ClutterActor:content-gravity property for * more information. * + * The #ClutterActor:content-gravity property is animatable. + * * Since: 1.10 */ void @@ -17802,12 +17840,37 @@ clutter_actor_set_content_gravity (ClutterActor *self, if (priv->content_gravity == gravity) return; - priv->content_gravity = gravity; + priv->content_box_valid = FALSE; + + if (_clutter_actor_get_transition (self, obj_props[PROP_CONTENT_BOX]) == NULL) + { + ClutterActorBox from_box, to_box; + + clutter_actor_get_content_box (self, &from_box); + + priv->content_gravity = gravity; + + clutter_actor_get_content_box (self, &to_box); + + _clutter_actor_create_transition (self, obj_props[PROP_CONTENT_BOX], + &from_box, + &to_box); + } + else + { + ClutterActorBox to_box; + + priv->content_gravity = gravity; + + clutter_actor_get_content_box (self, &to_box); + + _clutter_actor_update_transition (self, obj_props[PROP_CONTENT_BOX], + &to_box); + } clutter_actor_queue_redraw (self); g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_GRAVITY]); - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_BOX]); } /** @@ -17870,13 +17933,19 @@ clutter_actor_get_content_box (ClutterActor *self, box->x2 = priv->allocation.x2 - priv->allocation.x1; box->y2 = priv->allocation.y2 - priv->allocation.y1; - if (priv->content == NULL) - return; + if (priv->content_box_valid) + { + *box = priv->content_box; + return; + } /* no need to do any more work */ if (priv->content_gravity == CLUTTER_CONTENT_GRAVITY_RESIZE_FILL) return; + if (priv->content == NULL) + return; + /* if the content does not have a preferred size then there is * no point in computing the content box */ diff --git a/tests/interactive/test-image-box.c b/tests/interactive/test-image-box.c index abcd22c21..c4b8244ff 100644 --- a/tests/interactive/test-image-box.c +++ b/tests/interactive/test-image-box.c @@ -33,7 +33,9 @@ on_clicked (ClutterClickAction *action, { gchar *str; + clutter_actor_save_easing_state (actor); clutter_actor_set_content_gravity (actor, gravities[cur_gravity].gravity); + clutter_actor_restore_easing_state (actor); str = g_strconcat ("Content gravity: ", gravities[cur_gravity].name, NULL); clutter_text_set_text (label, str);