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.
This commit is contained in:
Emmanuele Bassi 2012-04-01 17:32:59 +01:00
parent 0f3f0d54d2
commit 7814ec2eb5

View File

@ -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);
@ -4334,6 +4352,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;
@ -4342,6 +4371,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;
@ -4613,6 +4653,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;
@ -4621,6 +4672,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;
@ -5436,6 +5498,28 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_PARAM_STATIC_STRINGS |
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:
*
@ -5474,6 +5558,27 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_PARAM_STATIC_STRINGS |
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:
*
@ -8716,14 +8821,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);
}
/**
@ -9139,6 +9259,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
@ -9161,14 +9297,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);
}
/**
@ -9614,6 +9783,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
@ -12985,6 +13183,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;
@ -12993,6 +13195,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;