mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
bind-constraint: Add width and height binding
Allow using the BindConstraint to bind width and height of a source actor. Also, add a test for the BindConstraint showing all types of usages for this constraint class.
This commit is contained in:
parent
b3ffe602a2
commit
32ad63efef
@ -25,11 +25,56 @@
|
||||
/**
|
||||
* SECTION:clutter-bind-constraint
|
||||
* @Title: ClutterBindConstraint
|
||||
* @Short_Description: A constraint binding the position of an actor
|
||||
* @Short_Description: A constraint binding the position or size of an actor
|
||||
*
|
||||
* #ClutterBindConstraint is a #ClutterConstraint that binds the position of
|
||||
* the #ClutterActor to which it is applied to the the position of another
|
||||
* #ClutterActor.
|
||||
* #ClutterBindConstraint is a #ClutterConstraint that binds the
|
||||
* position or the size of the #ClutterActor to which it is applied
|
||||
* to the the position or the size of another #ClutterActor, or
|
||||
* "source".
|
||||
*
|
||||
* An offset can be applied to the constraint, to avoid overlapping. The offset
|
||||
* can also be animated. For instance, the following code will set up three
|
||||
* actors to be bound to the same origin:
|
||||
*
|
||||
* |[
|
||||
* /* source */
|
||||
* rect[0] = clutter_rectangle_new_with_color (&red_color);
|
||||
* clutter_actor_set_position (rect[0], x_pos, y_pos);
|
||||
* clutter_actor_set_size (rect[0], 100, 100);
|
||||
*
|
||||
* /* second rectangle */
|
||||
* rect[1] = clutter_rectangle_new_with_color (&green_color);
|
||||
* clutter_actor_set_size (rect[1], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[1], 0);
|
||||
*
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_X, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[1], "green-x", constraint);
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_Y, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
|
||||
*
|
||||
* /* third rectangle */
|
||||
* rect[2] = clutter_rectangle_new_with_color (&blue_color);
|
||||
* clutter_actor_set_size (rect[2], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[2], 0);
|
||||
*
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_X, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[2], "blue-x", constraint);
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_Y, 0.0);
|
||||
* ]|
|
||||
*
|
||||
* The following code animates the second and third rectangles to "expand"
|
||||
* them horizontally from underneath the first rectangle:
|
||||
*
|
||||
* |[
|
||||
* clutter_actor_animate (rect[1], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
* "@constraints.green-x.offset", 100.0,
|
||||
* "opacity", 255,
|
||||
* NULL);
|
||||
* clutter_actor_animate (rect[2], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
* "@constraints.blue-x.offset", 200.0,
|
||||
* "opacity", 255,
|
||||
* NULL);
|
||||
* ]|
|
||||
*
|
||||
* #ClutterBindConstraint is available since Clutter 1.4
|
||||
*/
|
||||
@ -79,8 +124,9 @@ G_DEFINE_TYPE (ClutterBindConstraint,
|
||||
CLUTTER_TYPE_CONSTRAINT);
|
||||
|
||||
static void
|
||||
update_actor_position (ClutterBindConstraint *bind)
|
||||
update_actor_coords (ClutterBindConstraint *bind)
|
||||
{
|
||||
gfloat source_width, source_height;
|
||||
ClutterVertex source_position;
|
||||
ClutterActor *actor;
|
||||
|
||||
@ -97,6 +143,7 @@ update_actor_position (ClutterBindConstraint *bind)
|
||||
source_position.x = clutter_actor_get_x (bind->source);
|
||||
source_position.y = clutter_actor_get_y (bind->source);
|
||||
source_position.z = clutter_actor_get_depth (bind->source);
|
||||
clutter_actor_get_size (bind->source, &source_width, &source_height);
|
||||
|
||||
switch (bind->coordinate)
|
||||
{
|
||||
@ -111,20 +158,32 @@ update_actor_position (ClutterBindConstraint *bind)
|
||||
case CLUTTER_BIND_Z:
|
||||
clutter_actor_set_depth (actor, source_position.z + bind->offset);
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_WIDTH:
|
||||
clutter_actor_set_width (actor, source_width + bind->offset);
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_HEIGHT:
|
||||
clutter_actor_set_height (actor, source_height + bind->offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
source_position_changed (GObject *gobject,
|
||||
source_allocation_changed (ClutterActor *source,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags,
|
||||
ClutterBindConstraint *bind)
|
||||
{
|
||||
update_actor_coords (bind);
|
||||
}
|
||||
|
||||
static void
|
||||
source_depth_changed (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
ClutterBindConstraint *bind)
|
||||
{
|
||||
if (strcmp (pspec->name, "x") == 0 ||
|
||||
strcmp (pspec->name, "y") == 0 ||
|
||||
strcmp (pspec->name, "depth") == 0)
|
||||
{
|
||||
update_actor_position (bind);
|
||||
}
|
||||
update_actor_coords (bind);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -308,21 +367,27 @@ clutter_bind_constraint_set_source (ClutterBindConstraint *constraint,
|
||||
G_CALLBACK (source_destroyed),
|
||||
constraint);
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_position_changed),
|
||||
G_CALLBACK (source_allocation_changed),
|
||||
constraint);
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_depth_changed),
|
||||
constraint);
|
||||
}
|
||||
|
||||
constraint->source = source;
|
||||
if (constraint->source != NULL)
|
||||
{
|
||||
g_signal_connect (constraint->source, "notify",
|
||||
G_CALLBACK (source_position_changed),
|
||||
g_signal_connect (constraint->source, "allocation-changed",
|
||||
G_CALLBACK (source_allocation_changed),
|
||||
constraint);
|
||||
g_signal_connect (constraint->source, "notify::depth",
|
||||
G_CALLBACK (source_depth_changed),
|
||||
constraint);
|
||||
g_signal_connect (constraint->source, "destroy",
|
||||
G_CALLBACK (source_destroyed),
|
||||
constraint);
|
||||
|
||||
update_actor_position (constraint);
|
||||
update_actor_coords (constraint);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (constraint), "source");
|
||||
@ -366,7 +431,7 @@ clutter_bind_constraint_set_coordinate (ClutterBindConstraint *constraint,
|
||||
|
||||
constraint->coordinate = coordinate;
|
||||
|
||||
update_actor_position (constraint);
|
||||
update_actor_coords (constraint);
|
||||
|
||||
g_object_notify (G_OBJECT (constraint), "coordinate");
|
||||
}
|
||||
@ -410,7 +475,7 @@ clutter_bind_constraint_set_offset (ClutterBindConstraint *constraint,
|
||||
|
||||
constraint->offset = offset;
|
||||
|
||||
update_actor_position (constraint);
|
||||
update_actor_coords (constraint);
|
||||
|
||||
g_object_notify (G_OBJECT (constraint), "offset");
|
||||
}
|
||||
|
@ -52,15 +52,19 @@ typedef struct _ClutterBindConstraint ClutterBindConstraint;
|
||||
* @CLUTTER_BIND_X: Bind the X coordinate
|
||||
* @CLUTTER_BIND_Y: Bind the Y coordinate
|
||||
* @CLUTTER_BIND_Z: Bind the Z coordinate
|
||||
* @CLUTTER_BIND_WIDTH: Bind the width
|
||||
* @CLUTTER_BIND_HEIGHT: Bidng the height
|
||||
*
|
||||
* Specifies which coordinate should be used in a binding
|
||||
* Specifies which property should be used in a binding
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
typedef enum { /*< prefix=CLUTTER_BIND >*/
|
||||
CLUTTER_BIND_X,
|
||||
CLUTTER_BIND_Y,
|
||||
CLUTTER_BIND_Z
|
||||
CLUTTER_BIND_Z,
|
||||
CLUTTER_BIND_WIDTH,
|
||||
CLUTTER_BIND_HEIGHT
|
||||
} ClutterBindCoordinate;
|
||||
|
||||
GType clutter_bind_constraint_get_type (void) G_GNUC_CONST;
|
||||
|
1
tests/interactive/.gitignore
vendored
1
tests/interactive/.gitignore
vendored
@ -67,3 +67,4 @@
|
||||
/test-state
|
||||
/test-state-animator
|
||||
/test-scrolling
|
||||
/test-bind
|
||||
|
@ -53,7 +53,8 @@ UNIT_TESTS = \
|
||||
test-stage-sizing.c \
|
||||
test-drag.c \
|
||||
test-constraints.c \
|
||||
test-scrolling.c
|
||||
test-scrolling.c \
|
||||
test-bind.c
|
||||
|
||||
if X11_TESTS
|
||||
UNIT_TESTS += test-pixmap.c
|
||||
|
110
tests/interactive/test-bind.c
Normal file
110
tests/interactive/test-bind.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define RECT_SIZE 128.0
|
||||
|
||||
#define N_COLORS 3
|
||||
|
||||
static ClutterActor *rects[N_COLORS] = { NULL, };
|
||||
static const gchar *colors[N_COLORS] = {
|
||||
"#cc0000", "#3465a4", "#73d216"
|
||||
};
|
||||
static gboolean is_expanded = FALSE;
|
||||
|
||||
static void
|
||||
on_click (ClutterClickAction *action,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
if (!is_expanded)
|
||||
{
|
||||
clutter_actor_animate (rects[1], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
"@constraints.green-x.offset", RECT_SIZE,
|
||||
"opacity", 255,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[2], CLUTTER_EASE_OUT_CUBIC, 500,
|
||||
"@constraints.blue-x.offset", (RECT_SIZE * 2.0 + 0.5),
|
||||
"opacity", 255,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_animate (rects[1], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
"@constraints.green-x.offset", 0.0,
|
||||
"opacity", 0,
|
||||
NULL);
|
||||
clutter_actor_animate (rects[2], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
"@constraints.blue-x.offset", 0.0,
|
||||
"opacity", 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
is_expanded = !is_expanded;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_bind_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterConstraint *constraint;
|
||||
ClutterAction *action;
|
||||
ClutterColor color;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Bind Constraint");
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_set_size (stage, RECT_SIZE * 4.0, RECT_SIZE * 3.0);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* main rectangle */
|
||||
clutter_color_from_string (&color, colors[0]);
|
||||
rects[0] = clutter_rectangle_new_with_color (&color);
|
||||
clutter_actor_set_size (rects[0], RECT_SIZE, RECT_SIZE);
|
||||
|
||||
/* center it on the stage */
|
||||
clutter_actor_add_constraint (rects[0], clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.1));
|
||||
clutter_actor_add_constraint (rects[0], clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
|
||||
|
||||
/* make it clickable */
|
||||
action = clutter_click_action_new ();
|
||||
clutter_actor_add_action (rects[0], action);
|
||||
clutter_actor_set_reactive (rects[0], TRUE);
|
||||
g_signal_connect (action, "clicked", G_CALLBACK (on_click), NULL);
|
||||
|
||||
/* second rectangle */
|
||||
clutter_color_from_string (&color, colors[1]);
|
||||
rects[1] = clutter_rectangle_new_with_color (&color);
|
||||
clutter_actor_set_opacity (rects[1], 0);
|
||||
clutter_actor_add_constraint (rects[1], clutter_bind_constraint_new (rects[0], CLUTTER_BIND_WIDTH, 0.0));
|
||||
clutter_actor_add_constraint (rects[1], clutter_bind_constraint_new (rects[0], CLUTTER_BIND_HEIGHT, 0.0));
|
||||
constraint = clutter_bind_constraint_new (rects[0], CLUTTER_BIND_X, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rects[1], "green-x", constraint);
|
||||
constraint = clutter_bind_constraint_new (rects[0], CLUTTER_BIND_Y, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rects[1], "green-y", constraint);
|
||||
|
||||
/* third rectangle */
|
||||
clutter_color_from_string (&color, colors[2]);
|
||||
rects[2] = clutter_rectangle_new_with_color (&color);
|
||||
clutter_actor_set_opacity (rects[2], 0);
|
||||
clutter_actor_add_constraint (rects[2], clutter_bind_constraint_new (rects[0], CLUTTER_BIND_WIDTH, 0.0));
|
||||
clutter_actor_add_constraint (rects[2], clutter_bind_constraint_new (rects[0], CLUTTER_BIND_HEIGHT, 0.0));
|
||||
constraint = clutter_bind_constraint_new (rects[0], CLUTTER_BIND_X, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rects[2], "blue-x", constraint);
|
||||
constraint = clutter_bind_constraint_new (rects[0], CLUTTER_BIND_Y, 0.0);
|
||||
clutter_actor_add_constraint_with_name (rects[2], "blue-y", constraint);
|
||||
|
||||
/* add everything to the stage */
|
||||
clutter_container_add (CLUTTER_CONTAINER (stage),
|
||||
rects[2],
|
||||
rects[1],
|
||||
rects[0],
|
||||
NULL);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user