4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2010 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22 * Emmanuele Bassi <ebassi@linux.intel.com>
26 * SECTION:clutter-align-constraint
27 * @Title: ClutterAlignConstraint
28 * @Short_Description: A constraint aligning the position of an actor
30 * #ClutterAlignConstraint is a #ClutterConstraint that aligns the position
31 * of the #ClutterActor to which it is applied to the size of another
32 * #ClutterActor using an alignment factor
34 * #ClutterAlignConstraint is available since Clutter 1.4
41 #include "clutter-align-constraint.h"
43 #include "clutter-actor-meta-private.h"
44 #include "clutter-actor-private.h"
45 #include "clutter-constraint.h"
46 #include "clutter-debug.h"
47 #include "clutter-enum-types.h"
48 #include "clutter-private.h"
52 #define CLUTTER_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass))
53 #define CLUTTER_IS_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT))
54 #define CLUTTER_ALIGN_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass))
56 struct _ClutterAlignConstraint
58 ClutterConstraint parent_instance;
62 ClutterAlignAxis align_axis;
66 struct _ClutterAlignConstraintClass
68 ClutterConstraintClass parent_class;
82 static GParamSpec *obj_props[PROP_LAST];
84 G_DEFINE_TYPE (ClutterAlignConstraint,
85 clutter_align_constraint,
86 CLUTTER_TYPE_CONSTRAINT);
89 source_position_changed (ClutterActor *actor,
90 const ClutterActorBox *allocation,
91 ClutterAllocationFlags flags,
92 ClutterAlignConstraint *align)
94 if (align->actor != NULL)
95 clutter_actor_queue_relayout (align->actor);
99 source_destroyed (ClutterActor *actor,
100 ClutterAlignConstraint *align)
102 align->source = NULL;
106 clutter_align_constraint_set_actor (ClutterActorMeta *meta,
107 ClutterActor *new_actor)
109 ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (meta);
110 ClutterActorMetaClass *parent;
112 if (new_actor != NULL &&
113 align->source != NULL &&
114 clutter_actor_contains (new_actor, align->source))
116 g_warning (G_STRLOC ": The source actor '%s' is contained "
117 "by the actor '%s' associated to the constraint "
119 _clutter_actor_get_debug_name (align->source),
120 _clutter_actor_get_debug_name (new_actor),
121 _clutter_actor_meta_get_debug_name (meta));
125 /* store the pointer to the actor, for later use */
126 align->actor = new_actor;
128 parent = CLUTTER_ACTOR_META_CLASS (clutter_align_constraint_parent_class);
129 parent->set_actor (meta, new_actor);
133 clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
135 ClutterActorBox *allocation)
137 ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
138 gfloat source_width, source_height;
139 gfloat actor_width, actor_height;
140 gfloat source_x, source_y;
142 if (align->source == NULL)
145 clutter_actor_box_get_size (allocation, &actor_width, &actor_height);
147 clutter_actor_get_position (align->source, &source_x, &source_y);
148 clutter_actor_get_size (align->source, &source_width, &source_height);
150 switch (align->align_axis)
152 case CLUTTER_ALIGN_X_AXIS:
153 allocation->x1 = ((source_width - actor_width) * align->factor)
155 allocation->x1 = floorf (allocation->x1 + 0.5);
156 allocation->x2 = allocation->x1 + actor_width;
159 case CLUTTER_ALIGN_Y_AXIS:
160 allocation->y1 = ((source_height - actor_height) * align->factor)
162 allocation->y1 = floorf (allocation->y1 + 0.5);
163 allocation->y2 = allocation->y1 + actor_height;
166 case CLUTTER_ALIGN_BOTH:
167 allocation->x1 = ((source_width - actor_width) * align->factor)
169 allocation->y1 = ((source_height - actor_height) * align->factor)
171 allocation->x1 = floorf (allocation->x1 + 0.5f);
172 allocation->y1 = floorf (allocation->y1 + 0.5f);
173 allocation->x2 = allocation->x1 + actor_width;
174 allocation->y2 = allocation->y1 + actor_height;
178 g_assert_not_reached ();
184 clutter_align_constraint_dispose (GObject *gobject)
186 ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject);
188 if (align->source != NULL)
190 g_signal_handlers_disconnect_by_func (align->source,
191 G_CALLBACK (source_destroyed),
193 g_signal_handlers_disconnect_by_func (align->source,
194 G_CALLBACK (source_position_changed),
196 align->source = NULL;
199 G_OBJECT_CLASS (clutter_align_constraint_parent_class)->dispose (gobject);
203 clutter_align_constraint_set_property (GObject *gobject,
208 ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject);
213 clutter_align_constraint_set_source (align, g_value_get_object (value));
216 case PROP_ALIGN_AXIS:
217 clutter_align_constraint_set_align_axis (align, g_value_get_enum (value));
221 clutter_align_constraint_set_factor (align, g_value_get_float (value));
225 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
231 clutter_align_constraint_get_property (GObject *gobject,
236 ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject);
241 g_value_set_object (value, align->source);
244 case PROP_ALIGN_AXIS:
245 g_value_set_enum (value, align->align_axis);
249 g_value_set_float (value, align->factor);
253 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
259 clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
261 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
262 ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
263 ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass);
265 meta_class->set_actor = clutter_align_constraint_set_actor;
267 constraint_class->update_allocation = clutter_align_constraint_update_allocation;
270 * ClutterAlignConstraint:source:
272 * The #ClutterActor used as the source for the alignment.
274 * The #ClutterActor must not be a child or a grandchild of the actor
275 * using the constraint.
279 obj_props[PROP_SOURCE] =
280 g_param_spec_object ("source",
282 P_("The source of the alignment"),
284 CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT);
287 * ClutterAlignConstraint:align-axis:
289 * The axis to be used to compute the alignment
293 obj_props[PROP_ALIGN_AXIS] =
294 g_param_spec_enum ("align-axis",
296 P_("The axis to align the position to"),
297 CLUTTER_TYPE_ALIGN_AXIS,
298 CLUTTER_ALIGN_X_AXIS,
299 CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT);
302 * ClutterAlignConstraint:factor:
304 * The alignment factor, as a normalized value between 0.0 and 1.0
306 * The factor depends on the #ClutterAlignConstraint:align-axis property:
307 * with an align-axis value of %CLUTTER_ALIGN_X_AXIS, 0.0 means left and
308 * 1.0 means right; with a value of %CLUTTER_ALIGN_Y_AXIS, 0.0 means top
309 * and 1.0 means bottom.
313 obj_props[PROP_FACTOR] =
314 g_param_spec_float ("factor",
316 P_("The alignment factor, between 0.0 and 1.0"),
319 CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT);
321 gobject_class->dispose = clutter_align_constraint_dispose;
322 gobject_class->set_property = clutter_align_constraint_set_property;
323 gobject_class->get_property = clutter_align_constraint_get_property;
324 g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
328 clutter_align_constraint_init (ClutterAlignConstraint *self)
332 self->align_axis = CLUTTER_ALIGN_X_AXIS;
337 * clutter_align_constraint_new:
338 * @source: (allow-none): the #ClutterActor to use as the source of the
339 * alignment, or %NULL
340 * @axis: the axis to be used to compute the alignment
341 * @factor: the alignment factor, between 0.0 and 1.0
343 * Creates a new constraint, aligning a #ClutterActor's position with
344 * regards of the size of the actor to @source, with the given
347 * Return value: the newly created #ClutterAlignConstraint
352 clutter_align_constraint_new (ClutterActor *source,
353 ClutterAlignAxis axis,
356 g_return_val_if_fail (source == NULL || CLUTTER_IS_ACTOR (source), NULL);
358 return g_object_new (CLUTTER_TYPE_ALIGN_CONSTRAINT,
366 * clutter_align_constraint_set_source:
367 * @align: a #ClutterAlignConstraint
368 * @source: (allow-none): a #ClutterActor, or %NULL to unset the source
370 * Sets the source of the alignment constraint
375 clutter_align_constraint_set_source (ClutterAlignConstraint *align,
376 ClutterActor *source)
378 ClutterActor *old_source, *actor;
379 ClutterActorMeta *meta;
381 g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
382 g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source));
384 if (align->source == source)
387 meta = CLUTTER_ACTOR_META (align);
388 actor = clutter_actor_meta_get_actor (meta);
389 if (actor != NULL && source != NULL)
391 if (clutter_actor_contains (actor, source))
393 g_warning (G_STRLOC ": The source actor '%s' is contained "
394 "by the actor '%s' associated to the constraint "
396 _clutter_actor_get_debug_name (source),
397 _clutter_actor_get_debug_name (actor),
398 _clutter_actor_meta_get_debug_name (meta));
403 old_source = align->source;
404 if (old_source != NULL)
406 g_signal_handlers_disconnect_by_func (old_source,
407 G_CALLBACK (source_destroyed),
409 g_signal_handlers_disconnect_by_func (old_source,
410 G_CALLBACK (source_position_changed),
414 align->source = source;
415 if (align->source != NULL)
417 g_signal_connect (align->source, "allocation-changed",
418 G_CALLBACK (source_position_changed),
420 g_signal_connect (align->source, "destroy",
421 G_CALLBACK (source_destroyed),
424 if (align->actor != NULL)
425 clutter_actor_queue_relayout (align->actor);
428 g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_SOURCE]);
432 * clutter_align_constraint_get_source:
433 * @align: a #ClutterAlignConstraint
435 * Retrieves the source of the alignment
437 * Return value: (transfer none): the #ClutterActor used as the source
443 clutter_align_constraint_get_source (ClutterAlignConstraint *align)
445 g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), NULL);
447 return align->source;
451 * clutter_align_constraint_set_align_axis:
452 * @align: a #ClutterAlignConstraint
453 * @axis: the axis to which the alignment refers to
455 * Sets the axis to which the alignment refers to
460 clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align,
461 ClutterAlignAxis axis)
463 g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
465 if (align->align_axis == axis)
468 align->align_axis = axis;
470 if (align->actor != NULL)
471 clutter_actor_queue_relayout (align->actor);
473 g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_ALIGN_AXIS]);
477 * clutter_align_constraint_get_align_axis:
478 * @align: a #ClutterAlignConstraint
480 * Retrieves the value set using clutter_align_constraint_set_align_axis()
482 * Return value: the alignment axis
487 clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align)
489 g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align),
490 CLUTTER_ALIGN_X_AXIS);
492 return align->align_axis;
496 * clutter_align_constraint_set_factor:
497 * @align: a #ClutterAlignConstraint
498 * @factor: the alignment factor, between 0.0 and 1.0
500 * Sets the alignment factor of the constraint
502 * The factor depends on the #ClutterAlignConstraint:align-axis property
503 * and it is a value between 0.0 (meaning left, when
504 * #ClutterAlignConstraint:align-axis is set to %CLUTTER_ALIGN_X_AXIS; or
505 * meaning top, when #ClutterAlignConstraint:align-axis is set to
506 * %CLUTTER_ALIGN_Y_AXIS) and 1.0 (meaning right, when
507 * #ClutterAlignConstraint:align-axis is set to %CLUTTER_ALIGN_X_AXIS; or
508 * meaning bottom, when #ClutterAlignConstraint:align-axis is set to
509 * %CLUTTER_ALIGN_Y_AXIS). A value of 0.5 aligns in the middle in either
515 clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
518 g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
520 align->factor = CLAMP (factor, 0.0, 1.0);
522 if (align->actor != NULL)
523 clutter_actor_queue_relayout (align->actor);
525 g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_FACTOR]);
529 * clutter_align_constraint_get_factor:
530 * @align: a #ClutterAlignConstraint
532 * Retrieves the factor set using clutter_align_constraint_set_factor()
534 * Return value: the alignment factor
539 clutter_align_constraint_get_factor (ClutterAlignConstraint *align)
541 g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), 0.0);
543 return align->factor;