![]() |
![]() |
![]() |
Clutter Reference Manual | ![]() |
---|---|---|---|---|
Top | Description | Object Hierarchy |
GObject +----GInitiallyUnowned +----ClutterActorMeta +----ClutterConstraint +----ClutterAlignConstraint +----ClutterBindConstraint +----ClutterPathConstraint +----ClutterSnapConstraint
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.
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:
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). | |
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. | |
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. |
Example 2. 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.
#include <stdlib.h> #include <clutter/clutter.h> int main (int argc, char *argv[]) { ClutterActor *stage, *layer_a, *layer_b, *layer_c; if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; /* the main container */ stage = clutter_stage_new (); clutter_actor_set_name (stage, "stage"); clutter_stage_set_title (CLUTTER_STAGE (stage), "Snap Constraint"); clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium1); clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); /* first layer, with a fixed (100, 25) size */ layer_a = clutter_actor_new (); clutter_actor_set_background_color (layer_a, CLUTTER_COLOR_ScarletRed); clutter_actor_set_name (layer_a, "layerA"); clutter_actor_set_size (layer_a, 100.0, 25.0); clutter_actor_add_child (stage, layer_a); /* the first layer is anchored to the middle of the stage */ clutter_actor_add_constraint (layer_a, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); /* second layer, with no implicit size */ layer_b = clutter_actor_new (); clutter_actor_set_background_color (layer_b, CLUTTER_COLOR_DarkButter); clutter_actor_set_name (layer_b, "layerB"); clutter_actor_add_child (stage, layer_b); /* the second layer tracks the X coordinate and the width of * the first layer */ clutter_actor_add_constraint (layer_b, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_X, 0.0)); clutter_actor_add_constraint (layer_b, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_WIDTH, 0.0)); /* the second layer is snapped between the bottom edge of * the first layer, and the bottom edge of the stage; a * spacing of 10 pixels in each direction is added for padding */ clutter_actor_add_constraint (layer_b, clutter_snap_constraint_new (layer_a, CLUTTER_SNAP_EDGE_TOP, CLUTTER_SNAP_EDGE_BOTTOM, 10.0)); clutter_actor_add_constraint (layer_b, clutter_snap_constraint_new (stage, CLUTTER_SNAP_EDGE_BOTTOM, CLUTTER_SNAP_EDGE_BOTTOM, -10.0)); /* the third layer, with no implicit size */ layer_c = clutter_actor_new (); clutter_actor_set_background_color (layer_c, CLUTTER_COLOR_LightChameleon); clutter_actor_set_name (layer_c, "layerC"); clutter_actor_add_child (stage, layer_c); /* as for the second layer, the third layer tracks the X * coordinate and width of the first layer */ clutter_actor_add_constraint (layer_c, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_X, 0.0)); clutter_actor_add_constraint (layer_c, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_WIDTH, 0.0)); /* the third layer is snapped between the top edge of the stage * and the top edge of the first layer; again, a spacing of * 10 pixels in each direction is added for padding */ clutter_actor_add_constraint (layer_c, clutter_snap_constraint_new (layer_a, CLUTTER_SNAP_EDGE_BOTTOM, CLUTTER_SNAP_EDGE_TOP, -10.0)); clutter_actor_add_constraint (layer_c, clutter_snap_constraint_new (stage, CLUTTER_SNAP_EDGE_TOP, CLUTTER_SNAP_EDGE_TOP, 10.0)); clutter_actor_show (stage); clutter_main (); return EXIT_SUCCESS; }
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.
Creating a sub-class of ClutterConstraint requires the
implementation of the
virtual function.update_allocation()
The
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 update_allocation()
implementation.allocate()
The ClutterActorBox passed to the
implementation contains the
original allocation of the ClutterActor, plus the eventual modifications
applied by the other ClutterConstraints.update_allocation()
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