/**
* SECTION:clutter-constraint
* @Title: ClutterConstraint
* @Short_Description: Abstract class for constraints on position or size
* @See_Also: #ClutterAction
*
* #ClutterConstraint is a base abstract class for modifiers of a #ClutterActor
* position or size.
*
* A #ClutterConstraint sub-class should contain the logic for modifying
* the position or size of the #ClutterActor to which it is applied, by
* updating the actor's allocation. Each #ClutterConstraint can change the
* allocation of the actor to which they are applied by overriding the
* #ClutterConstraintClass.update_allocation() virtual function.
*
*
* Using Constraints
* Constraints can be used with fixed layout managers, like
* #ClutterFixedLayout, or with actors implicitly using a fixed layout
* manager, like #ClutterGroup and #ClutterStage.
* Constraints provide a way to build user interfaces by using
* relations between #ClutterActors, without explicit fixed
* positioning and sizing, similarly to how fluid layout managers like
* #ClutterBoxLayout and #ClutterTableLayout lay out their children.
* Constraints are attached to a #ClutterActor, and are available
* for inspection using clutter_actor_get_constraints().
* Clutter provides different implementation of the #ClutterConstraint
* abstract class, for instance:
*
*
* #ClutterAlignConstraint
* this constraint can be used to align an actor
* to another one, on either the horizontal or the vertical axis; the
* #ClutterAlignConstraint uses a normalized offset between 0.0 (the
* top or the left of the source actor, depending on the axis) and
* 1.0 (the bottom or the right of the source actor, depending on the
* axis).
*
*
* #ClutterBindConstraint
* this constraint binds the X, Y, width or height
* of an actor to the corresponding position or size of a source
* actor; it can also apply an offset.
*
*
* #ClutterSnapConstraint
* this constraint "snaps" together the edges of
* two #ClutterActors; if an actor uses two constraints on
* both its horizontal or vertical edges then it can also expand to
* fit the empty space.
*
*
*
* Usage of constraints
* The example below uses various #ClutterConstraints to
* lay out three actors on a resizable stage. Only the central actor has
* an explicit size, and no actor has an explicit position.
*
* The #ClutterRectangle with #ClutterActor:name
* layerA is explicitly sized to 100 pixels by 25
* pixels, and it's added to the #ClutterStage;
* two #ClutterAlignConstraints are used
* to anchor layerA to the center of the stage,
* by using 0.5 as the alignment #ClutterAlignConstraint:factor on
* both the X and Y axis.
* the #ClutterRectangle with #ClutterActor:name
* layerB is added to the #ClutterStage with
* no explicit size;
* the #ClutterActor:x and #ClutterActor:width
* of layerB are bound to the same properties
* of layerA using two #ClutterBindConstraint
* objects, thus keeping layerB aligned to
* layerA;
* the top edge of layerB is
* snapped together with the bottom edge of layerA;
* the bottom edge of layerB is also snapped
* together with the bottom edge of the #ClutterStage; an offset is
* given to the two #ClutterSnapConstraints to allow for some
* padding; since layerB is snapped between two
* different #ClutterActors, its height is stretched to match
* the gap;
* the #ClutterRectangle with #ClutterActor:name
* layerC mirrors layerB,
* snapping the top edge of the #ClutterStage to the top edge of
* layerC and the top edge of
* layerA to the bottom edge of
* layerC;
*
*
*
*FIXME: MISSING XINCLUDE CONTENT
*
* You can try resizing interactively the #ClutterStage and verify
* that the three #ClutterActors maintain the same position and
* size relative to each other, and to the #ClutterStage.
*
* It's important to note that Clutter does not avoid loops
* or competing constraints; if two or more #ClutterConstraints
* are operating on the same positional or dimensional attributes of an
* actor, or if the constraints on two different actors depend on each
* other, then the behavior is undefined.
*
*
*
* Implementing a ClutterConstraint
* Creating a sub-class of #ClutterConstraint requires the
* implementation of the update_allocation()
* virtual function.
* The update_allocation() virtual function
* is called during the allocation sequence of a #ClutterActor, and
* allows any #ClutterConstraint attached to that actor to modify the
* allocation before it is passed to the allocate()
* implementation.
* The #ClutterActorBox passed to the
* update_allocation() implementation contains the
* original allocation of the #ClutterActor, plus the eventual modifications
* applied by the other #ClutterConstraints.
* Constraints are queried in the same order as they were
* applied using clutter_actor_add_constraint() or
* clutter_actor_add_constraint_with_name().
* It is not necessary for a #ClutterConstraint sub-class to chain
* up to the parent's implementation.
* If a #ClutterConstraint is parametrized - i.e. if it contains
* properties that affect the way the constraint is implemented - it should
* call clutter_actor_queue_relayout() on the actor to which it is attached
* to whenever any parameter is changed. The actor to which it is attached
* can be recovered at any point using clutter_actor_meta_get_actor().
*
*
* #ClutterConstraint is available since Clutter 1.4
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include "clutter-constraint.h"
#include "clutter-actor.h"
#include "clutter-actor-meta-private.h"
#include "clutter-private.h"
G_DEFINE_ABSTRACT_TYPE (ClutterConstraint,
clutter_constraint,
CLUTTER_TYPE_ACTOR_META);
static void
constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterActorBox *allocation)
{
}
static void
clutter_constraint_notify (GObject *gobject,
GParamSpec *pspec)
{
if (strcmp (pspec->name, "enabled") == 0)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
ClutterActor *actor = clutter_actor_meta_get_actor (meta);
if (actor != NULL)
clutter_actor_queue_relayout (actor);
}
if (G_OBJECT_CLASS (clutter_constraint_parent_class)->notify != NULL)
G_OBJECT_CLASS (clutter_constraint_parent_class)->notify (gobject, pspec);
}
static void
clutter_constraint_class_init (ClutterConstraintClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->notify = clutter_constraint_notify;
klass->update_allocation = constraint_update_allocation;
}
static void
clutter_constraint_init (ClutterConstraint *self)
{
}
void
_clutter_constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterActorBox *allocation)
{
g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_return_if_fail (allocation != NULL);
CLUTTER_CONSTRAINT_GET_CLASS (constraint)->update_allocation (constraint,
actor,
allocation);
}