constraint: Re-implement using update_allocation()

Instead of using the fixed position and size API, use the newly added
update_allocation() virtual function in ClutterConstraint to change the
allocation of a ClutterActor. This allows using constraints inside
layout managers, and also allows Constraints to react to changes in the
size of an actor without causing relayout cycles.

http://bugzilla.clutter-project.org/show_bug.cgi?id=2319
This commit is contained in:
Emmanuele Bassi
2010-09-17 12:13:29 +01:00
parent 5da0064de7
commit cdff2a9e7a
3 changed files with 153 additions and 110 deletions

View File

@ -55,6 +55,7 @@ struct _ClutterAlignConstraint
{
ClutterConstraint parent_instance;
ClutterActor *actor;
ClutterActor *source;
ClutterAlignAxis align_axis;
gfloat factor;
@ -82,52 +83,14 @@ G_DEFINE_TYPE (ClutterAlignConstraint,
clutter_align_constraint,
CLUTTER_TYPE_CONSTRAINT);
static void
update_actor_position (ClutterAlignConstraint *align)
{
gfloat source_width, source_height;
gfloat actor_width, actor_height;
gfloat source_x, source_y;
gfloat new_position;
ClutterActor *actor;
if (align->source == NULL)
return;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (align)))
return;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (align));
if (actor == NULL)
return;
clutter_actor_get_position (align->source, &source_x, &source_y);
clutter_actor_get_size (align->source, &source_width, &source_height);
clutter_actor_get_size (actor, &actor_width, &actor_height);
switch (align->align_axis)
{
case CLUTTER_ALIGN_X_AXIS:
new_position = ((source_width - actor_width) * align->factor)
+ source_x;
clutter_actor_set_x (actor, new_position);
break;
case CLUTTER_ALIGN_Y_AXIS:
new_position = ((source_height - actor_height) * align->factor)
+ source_y;
clutter_actor_set_y (actor, new_position);
break;
}
}
static void
source_position_changed (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
ClutterAlignConstraint *align)
{
update_actor_position (align);
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
}
static void
@ -137,6 +100,62 @@ source_destroyed (ClutterActor *actor,
align->source = NULL;
}
static void
clutter_align_constraint_set_actor (ClutterActorMeta *meta,
ClutterActor *new_actor)
{
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (meta);
ClutterActorMetaClass *parent;
/* store the pointer to the actor, for later use */
align->actor = new_actor;
parent = CLUTTER_ACTOR_META_CLASS (clutter_align_constraint_parent_class);
parent->set_actor (meta, new_actor);
}
static void
clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterActorBox *allocation)
{
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
ClutterActorMeta *meta = CLUTTER_ACTOR_META (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
gfloat source_x, source_y;
if (align->source == NULL)
return;
if (!clutter_actor_meta_get_enabled (meta))
return;
clutter_actor_get_position (align->source, &source_x, &source_y);
clutter_actor_get_size (align->source, &source_width, &source_height);
switch (align->align_axis)
{
case CLUTTER_ALIGN_X_AXIS:
actor_width = clutter_actor_box_get_width (allocation);
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->x2 = allocation->x1 + actor_width;
break;
case CLUTTER_ALIGN_Y_AXIS:
actor_height = clutter_actor_box_get_height (allocation);
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->y2 = allocation->y1 + actor_height;
break;
default:
g_assert_not_reached ();
break;
}
}
static void
clutter_align_constraint_set_property (GObject *gobject,
guint prop_id,
@ -197,11 +216,17 @@ static void
clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = clutter_align_constraint_set_property;
gobject_class->get_property = clutter_align_constraint_get_property;
meta_class->set_actor = clutter_align_constraint_set_actor;
constraint_class->update_allocation = clutter_align_constraint_update_allocation;
/**
* ClutterAlignConstraint:source:
*
@ -261,6 +286,7 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
static void
clutter_align_constraint_init (ClutterAlignConstraint *self)
{
self->actor = NULL;
self->source = NULL;
self->align_axis = CLUTTER_ALIGN_X_AXIS;
self->factor = 0.0f;
@ -328,7 +354,6 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
}
align->source = source;
if (align->source != NULL)
{
g_signal_connect (align->source, "allocation-changed",
@ -338,7 +363,8 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
G_CALLBACK (source_destroyed),
align);
update_actor_position (align);
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
}
_clutter_notify_by_pspec (G_OBJECT (align), obj_props[PROP_SOURCE]);
@ -383,7 +409,8 @@ clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align,
align->align_axis = axis;
update_actor_position (align);
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
_clutter_notify_by_pspec (G_OBJECT (align), obj_props[PROP_ALIGN_AXIS]);
}
@ -434,7 +461,8 @@ clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
align->factor = CLAMP (factor, 0.0, 1.0);
update_actor_position (align);
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
_clutter_notify_by_pspec (G_OBJECT (align), obj_props[PROP_FACTOR]);
}