[clutter/wip/base-types: 5/6] actor: Add position and size animatable properties



commit 9a52a70eeab1d0966c1065af6b83277fa6f7ca7f
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Sun Apr 1 17:32:59 2012 +0100

    actor: Add position and size animatable properties
    
    Using a compound type property for position and size has various
    advantages: it reduces the amount of checks; it reduces the amount
    of notify signals to connect to; it reduces the amount of transitions
    generated.

 clutter/clutter-actor.c |  230 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 218 insertions(+), 12 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index e5f6109..34711e8 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -788,6 +788,9 @@ enum
   PROP_WIDTH,
   PROP_HEIGHT,
 
+  PROP_POSITION,
+  PROP_SIZE,
+
   /* Then the rest of these size-related properties are the "actual"
    * underlying properties set or gotten by X, Y, WIDTH, HEIGHT
    */
@@ -2165,13 +2168,16 @@ clutter_actor_notify_if_geometry_changed (ClutterActor          *self,
     {
       g_object_notify_by_pspec (obj, obj_props[PROP_X]);
       g_object_notify_by_pspec (obj, obj_props[PROP_Y]);
+      g_object_notify_by_pspec (obj, obj_props[PROP_POSITION]);
       g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]);
       g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]);
+      g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]);
     }
   else if (priv->needs_width_request || priv->needs_height_request)
     {
       g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]);
       g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]);
+      g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]);
     }
   else
     {
@@ -2184,16 +2190,28 @@ clutter_actor_notify_if_geometry_changed (ClutterActor          *self,
       height = priv->allocation.y2 - priv->allocation.y1;
 
       if (x != old->x1)
-        g_object_notify_by_pspec (obj, obj_props[PROP_X]);
+        {
+          g_object_notify_by_pspec (obj, obj_props[PROP_X]);
+          g_object_notify_by_pspec (obj, obj_props[PROP_POSITION]);
+        }
 
       if (y != old->y1)
-        g_object_notify_by_pspec (obj, obj_props[PROP_Y]);
+        {
+          g_object_notify_by_pspec (obj, obj_props[PROP_Y]);
+          g_object_notify_by_pspec (obj, obj_props[PROP_POSITION]);
+        }
 
       if (width != (old->x2 - old->x1))
-        g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]);
+        {
+          g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]);
+          g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]);
+        }
 
       if (height != (old->y2 - old->y1))
-        g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]);
+        {
+          g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]);
+          g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]);
+        }
     }
 
   g_object_thaw_notify (obj);
@@ -4331,6 +4349,17 @@ clutter_actor_set_property (GObject      *object,
       clutter_actor_set_y (actor, g_value_get_float (value));
       break;
 
+    case PROP_POSITION:
+      {
+        const ClutterPoint *pos = g_value_get_boxed (value);
+
+        if (pos != NULL)
+          clutter_actor_set_position (actor, pos->x, pos->y);
+        else
+          clutter_actor_set_fixed_position_set (actor, FALSE);
+      }
+      break;
+
     case PROP_WIDTH:
       clutter_actor_set_width (actor, g_value_get_float (value));
       break;
@@ -4339,6 +4368,17 @@ clutter_actor_set_property (GObject      *object,
       clutter_actor_set_height (actor, g_value_get_float (value));
       break;
 
+    case PROP_SIZE:
+      {
+        const ClutterSize *size = g_value_get_boxed (value);
+
+        if (size != NULL)
+          clutter_actor_set_size (actor, size->width, size->height);
+        else
+          clutter_actor_set_size (actor, -1, -1);
+      }
+      break;
+
     case PROP_FIXED_X:
       clutter_actor_set_x (actor, g_value_get_float (value));
       break;
@@ -4610,6 +4650,17 @@ clutter_actor_get_property (GObject    *object,
       g_value_set_float (value, clutter_actor_get_y (actor));
       break;
 
+    case PROP_POSITION:
+      {
+        ClutterPoint position;
+
+        clutter_point_init (&position,
+                            clutter_actor_get_x (actor),
+                            clutter_actor_get_y (actor));
+        g_value_set_boxed (value, &position);
+      }
+      break;
+
     case PROP_WIDTH:
       g_value_set_float (value, clutter_actor_get_width (actor));
       break;
@@ -4618,6 +4669,17 @@ clutter_actor_get_property (GObject    *object,
       g_value_set_float (value, clutter_actor_get_height (actor));
       break;
 
+    case PROP_SIZE:
+      {
+        ClutterSize size;
+
+        clutter_size_init (&size,
+                           clutter_actor_get_width (actor),
+                           clutter_actor_get_height (actor));
+        g_value_set_boxed (value, &size);
+      }
+      break;
+
     case PROP_FIXED_X:
       {
         const ClutterLayoutInfo *info;
@@ -5428,6 +5490,28 @@ clutter_actor_class_init (ClutterActorClass *klass)
                         CLUTTER_PARAM_ANIMATABLE);
 
   /**
+   * ClutterActor:position:
+   *
+   * The position of the origin of the actor.
+   *
+   * This property is a shorthand for setting and getting the
+   * #ClutterActor:x and #ClutterActor:y properties at the same
+   * time.
+   *
+   * The #ClutterActor:position property is animatable.
+   *
+   * Since: 1.12
+   */
+  obj_props[PROP_POSITION] =
+    g_param_spec_boxed ("position",
+                        P_("Position"),
+                        P_("The position of the origin of the actor"),
+                        CLUTTER_TYPE_POINT,
+                        G_PARAM_READWRITE |
+                        G_PARAM_STATIC_STRINGS |
+                        CLUTTER_PARAM_ANIMATABLE);
+
+  /**
    * ClutterActor:width:
    *
    * Width of the actor (in pixels). If written, forces the minimum and
@@ -5466,6 +5550,27 @@ clutter_actor_class_init (ClutterActorClass *klass)
                         CLUTTER_PARAM_ANIMATABLE);
 
   /**
+   * ClutterActor:size:
+   *
+   * The size of the actor.
+   *
+   * This property is a shorthand for setting and getting the
+   * #ClutterActor:width and #ClutterActor:height at the same time.
+   *
+   * The #ClutterActor:size property is animatable.
+   *
+   * Since: 1.12
+   */
+  obj_props[PROP_SIZE] =
+    g_param_spec_boxed ("size",
+                        P_("Size"),
+                        P_("The size of the actor"),
+                        CLUTTER_TYPE_SIZE,
+                        G_PARAM_READWRITE |
+                        G_PARAM_STATIC_STRINGS |
+                        CLUTTER_PARAM_ANIMATABLE);
+
+  /**
    * ClutterActor:fixed-x:
    *
    * The fixed X position of the actor in pixels.
@@ -8707,14 +8812,29 @@ clutter_actor_set_position (ClutterActor *self,
 			    gfloat        x,
 			    gfloat        y)
 {
+  ClutterPoint new_position;
+
   g_return_if_fail (CLUTTER_IS_ACTOR (self));
 
-  g_object_freeze_notify (G_OBJECT (self));
+  clutter_point_init (&new_position, x, y);
 
-  clutter_actor_set_x (self, x);
-  clutter_actor_set_y (self, y);
+  if (_clutter_actor_get_transition (self, obj_props[PROP_POSITION]) == NULL)
+    {
+      ClutterPoint cur_position;
 
-  g_object_thaw_notify (G_OBJECT (self));
+      cur_position.x = clutter_actor_get_x (self);
+      cur_position.y = clutter_actor_get_y (self);
+
+      _clutter_actor_create_transition (self, obj_props[PROP_POSITION],
+                                        &cur_position,
+                                        &new_position);
+    }
+  else
+    _clutter_actor_update_transition (self,
+                                      obj_props[PROP_POSITION],
+                                      &new_position);
+
+  clutter_actor_queue_relayout (self);
 }
 
 /**
@@ -9130,6 +9250,22 @@ clutter_actor_set_height_internal (ClutterActor *self,
     }
 }
 
+static void
+clutter_actor_set_size_internal (ClutterActor      *self,
+                                 const ClutterSize *size)
+{
+  if (size != NULL)
+    {
+      clutter_actor_set_width_internal (self, size->width);
+      clutter_actor_set_height_internal (self, size->height);
+    }
+  else
+    {
+      clutter_actor_set_width_internal (self, -1);
+      clutter_actor_set_height_internal (self, -1);
+    }
+}
+
 /**
  * clutter_actor_set_size:
  * @self: A #ClutterActor
@@ -9152,14 +9288,47 @@ clutter_actor_set_size (ClutterActor *self,
 			gfloat        width,
 			gfloat        height)
 {
+  ClutterSize new_size;
+
   g_return_if_fail (CLUTTER_IS_ACTOR (self));
 
-  g_object_freeze_notify (G_OBJECT (self));
+  clutter_size_init (&new_size, width, height);
 
-  clutter_actor_set_width (self, width);
-  clutter_actor_set_height (self, height);
+  if (_clutter_actor_get_transition (self, obj_props[PROP_SIZE]) == NULL)
+    {
+      /* minor optimization: if we don't have a duration then we can
+       * skip the get_size() below, to avoid the chance of going through
+       * get_preferred_width() and get_preferred_height() just to jump to
+       * a new desired size
+       */
+      if (clutter_actor_get_easing_duration (self) == 0)
+        {
+          g_object_freeze_notify (G_OBJECT (self));
 
-  g_object_thaw_notify (G_OBJECT (self));
+          clutter_actor_set_size_internal (self, &new_size);
+
+          g_object_thaw_notify (G_OBJECT (self));
+
+          return;
+        }
+      else
+        {
+          ClutterSize cur_size;
+
+          clutter_size_init (&cur_size,
+                             clutter_actor_get_width (self),
+                             clutter_actor_get_height (self));
+
+         _clutter_actor_create_transition (self,
+                                           obj_props[PROP_SIZE],
+                                           &cur_size,
+                                           &new_size);
+        }
+    }
+  else
+    _clutter_actor_update_transition (self, obj_props[PROP_SIZE], &new_size);
+
+  clutter_actor_queue_relayout (self);
 }
 
 /**
@@ -9605,6 +9774,35 @@ clutter_actor_set_y_internal (ClutterActor *self,
   clutter_actor_queue_relayout (self);
 }
 
+static void
+clutter_actor_set_position_internal (ClutterActor       *self,
+                                     const ClutterPoint *position)
+{
+  ClutterActorPrivate *priv = self->priv;
+  ClutterLayoutInfo *linfo;
+  ClutterActorBox old = { 0, };
+
+  linfo = _clutter_actor_get_layout_info (self);
+
+  if (priv->position_set &&
+      clutter_point_equals (position, &linfo->fixed_pos))
+    return;
+
+  clutter_actor_store_old_geometry (self, &old);
+
+  if (position != NULL)
+    {
+      linfo->fixed_pos = *position;
+      clutter_actor_set_fixed_position_set (self, TRUE);
+    }
+  else
+    clutter_actor_set_fixed_position_set (self, FALSE);
+
+  clutter_actor_notify_if_geometry_changed (self, &old);
+
+  clutter_actor_queue_relayout (self);
+}
+
 /**
  * clutter_actor_set_x:
  * @self: a #ClutterActor
@@ -12971,6 +13169,10 @@ clutter_actor_set_animatable_property (ClutterActor *actor,
       clutter_actor_set_y_internal (actor, g_value_get_float (value));
       break;
 
+    case PROP_POSITION:
+      clutter_actor_set_position_internal (actor, g_value_get_boxed (value));
+      break;
+
     case PROP_WIDTH:
       clutter_actor_set_width_internal (actor, g_value_get_float (value));
       break;
@@ -12979,6 +13181,10 @@ clutter_actor_set_animatable_property (ClutterActor *actor,
       clutter_actor_set_height_internal (actor, g_value_get_float (value));
       break;
 
+    case PROP_SIZE:
+      clutter_actor_set_size_internal (actor, g_value_get_boxed (value));
+      break;
+
     case PROP_DEPTH:
       clutter_actor_set_depth_internal (actor, g_value_get_float (value));
       break;



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