[clutter] actor: Make :content-gravity animatable



commit 499534f3ac44022b3204161bc12656d7fce36602
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Thu Mar 29 13:53:40 2012 +0100

    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 a79549a..906f2c0 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",
@@ -12321,6 +12330,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)
 {
   /* we don't override anything, as ClutterContainer already has a default
@@ -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;
+
+      timeline = CLUTTER_TIMELINE (clos->transition);
 
-      if (clutter_timeline_is_playing (CLUTTER_TIMELINE (clos->transition)))
-        clutter_timeline_stop (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 abcd22c..c4b8244 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]