mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -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
|
* SECTION:clutter-bind-constraint
|
||||||
* @Title: ClutterBindConstraint
|
* @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
|
* #ClutterBindConstraint is a #ClutterConstraint that binds the
|
||||||
* the #ClutterActor to which it is applied to the the position of another
|
* position or the size of the #ClutterActor to which it is applied
|
||||||
* #ClutterActor.
|
* 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
|
* #ClutterBindConstraint is available since Clutter 1.4
|
||||||
*/
|
*/
|
||||||
@ -79,8 +124,9 @@ G_DEFINE_TYPE (ClutterBindConstraint,
|
|||||||
CLUTTER_TYPE_CONSTRAINT);
|
CLUTTER_TYPE_CONSTRAINT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_actor_position (ClutterBindConstraint *bind)
|
update_actor_coords (ClutterBindConstraint *bind)
|
||||||
{
|
{
|
||||||
|
gfloat source_width, source_height;
|
||||||
ClutterVertex source_position;
|
ClutterVertex source_position;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
|
|
||||||
@ -97,6 +143,7 @@ update_actor_position (ClutterBindConstraint *bind)
|
|||||||
source_position.x = clutter_actor_get_x (bind->source);
|
source_position.x = clutter_actor_get_x (bind->source);
|
||||||
source_position.y = clutter_actor_get_y (bind->source);
|
source_position.y = clutter_actor_get_y (bind->source);
|
||||||
source_position.z = clutter_actor_get_depth (bind->source);
|
source_position.z = clutter_actor_get_depth (bind->source);
|
||||||
|
clutter_actor_get_size (bind->source, &source_width, &source_height);
|
||||||
|
|
||||||
switch (bind->coordinate)
|
switch (bind->coordinate)
|
||||||
{
|
{
|
||||||
@ -111,20 +158,32 @@ update_actor_position (ClutterBindConstraint *bind)
|
|||||||
case CLUTTER_BIND_Z:
|
case CLUTTER_BIND_Z:
|
||||||
clutter_actor_set_depth (actor, source_position.z + bind->offset);
|
clutter_actor_set_depth (actor, source_position.z + bind->offset);
|
||||||
break;
|
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
|
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,
|
GParamSpec *pspec,
|
||||||
ClutterBindConstraint *bind)
|
ClutterBindConstraint *bind)
|
||||||
{
|
{
|
||||||
if (strcmp (pspec->name, "x") == 0 ||
|
update_actor_coords (bind);
|
||||||
strcmp (pspec->name, "y") == 0 ||
|
|
||||||
strcmp (pspec->name, "depth") == 0)
|
|
||||||
{
|
|
||||||
update_actor_position (bind);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -308,21 +367,27 @@ clutter_bind_constraint_set_source (ClutterBindConstraint *constraint,
|
|||||||
G_CALLBACK (source_destroyed),
|
G_CALLBACK (source_destroyed),
|
||||||
constraint);
|
constraint);
|
||||||
g_signal_handlers_disconnect_by_func (old_source,
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
constraint->source = source;
|
constraint->source = source;
|
||||||
if (constraint->source != NULL)
|
if (constraint->source != NULL)
|
||||||
{
|
{
|
||||||
g_signal_connect (constraint->source, "notify",
|
g_signal_connect (constraint->source, "allocation-changed",
|
||||||
G_CALLBACK (source_position_changed),
|
G_CALLBACK (source_allocation_changed),
|
||||||
|
constraint);
|
||||||
|
g_signal_connect (constraint->source, "notify::depth",
|
||||||
|
G_CALLBACK (source_depth_changed),
|
||||||
constraint);
|
constraint);
|
||||||
g_signal_connect (constraint->source, "destroy",
|
g_signal_connect (constraint->source, "destroy",
|
||||||
G_CALLBACK (source_destroyed),
|
G_CALLBACK (source_destroyed),
|
||||||
constraint);
|
constraint);
|
||||||
|
|
||||||
update_actor_position (constraint);
|
update_actor_coords (constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (constraint), "source");
|
g_object_notify (G_OBJECT (constraint), "source");
|
||||||
@ -366,7 +431,7 @@ clutter_bind_constraint_set_coordinate (ClutterBindConstraint *constraint,
|
|||||||
|
|
||||||
constraint->coordinate = coordinate;
|
constraint->coordinate = coordinate;
|
||||||
|
|
||||||
update_actor_position (constraint);
|
update_actor_coords (constraint);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (constraint), "coordinate");
|
g_object_notify (G_OBJECT (constraint), "coordinate");
|
||||||
}
|
}
|
||||||
@ -410,7 +475,7 @@ clutter_bind_constraint_set_offset (ClutterBindConstraint *constraint,
|
|||||||
|
|
||||||
constraint->offset = offset;
|
constraint->offset = offset;
|
||||||
|
|
||||||
update_actor_position (constraint);
|
update_actor_coords (constraint);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (constraint), "offset");
|
g_object_notify (G_OBJECT (constraint), "offset");
|
||||||
}
|
}
|
||||||
|
@ -52,15 +52,19 @@ typedef struct _ClutterBindConstraint ClutterBindConstraint;
|
|||||||
* @CLUTTER_BIND_X: Bind the X coordinate
|
* @CLUTTER_BIND_X: Bind the X coordinate
|
||||||
* @CLUTTER_BIND_Y: Bind the Y coordinate
|
* @CLUTTER_BIND_Y: Bind the Y coordinate
|
||||||
* @CLUTTER_BIND_Z: Bind the Z 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
|
* Since: 1.4
|
||||||
*/
|
*/
|
||||||
typedef enum { /*< prefix=CLUTTER_BIND >*/
|
typedef enum { /*< prefix=CLUTTER_BIND >*/
|
||||||
CLUTTER_BIND_X,
|
CLUTTER_BIND_X,
|
||||||
CLUTTER_BIND_Y,
|
CLUTTER_BIND_Y,
|
||||||
CLUTTER_BIND_Z
|
CLUTTER_BIND_Z,
|
||||||
|
CLUTTER_BIND_WIDTH,
|
||||||
|
CLUTTER_BIND_HEIGHT
|
||||||
} ClutterBindCoordinate;
|
} ClutterBindCoordinate;
|
||||||
|
|
||||||
GType clutter_bind_constraint_get_type (void) G_GNUC_CONST;
|
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
|
||||||
/test-state-animator
|
/test-state-animator
|
||||||
/test-scrolling
|
/test-scrolling
|
||||||
|
/test-bind
|
||||||
|
@ -53,7 +53,8 @@ UNIT_TESTS = \
|
|||||||
test-stage-sizing.c \
|
test-stage-sizing.c \
|
||||||
test-drag.c \
|
test-drag.c \
|
||||||
test-constraints.c \
|
test-constraints.c \
|
||||||
test-scrolling.c
|
test-scrolling.c \
|
||||||
|
test-bind.c
|
||||||
|
|
||||||
if X11_TESTS
|
if X11_TESTS
|
||||||
UNIT_TESTS += test-pixmap.c
|
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