45cab472870d77f75a8659c73859272a12125125
[profile/ivi/clutter.git] / clutter / clutter-bin-layout.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright (C) 2009  Intel Corporation.
7  *
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.
12  *
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.
17  *
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/>.
20  *
21  * Author:
22  *   Emmanuele Bassi <ebassi@linux.intel.com>
23  */
24
25 /**
26  * SECTION:clutter-bin-layout
27  * @short_description: A simple layout manager
28  *
29  * #ClutterBinLayout is a layout manager which implements the following
30  * policy:
31  *
32  * <itemizedlist>
33  *   <listitem><simpara>the preferred size is the maximum preferred size
34  *   between all the children of the container using the
35  *   layout;</simpara></listitem>
36  *   <listitem><simpara>each child is allocated in "layers", on on top
37  *   of the other;</simpara></listitem>
38  *   <listitem><simpara>for each layer there are horizontal and vertical
39  *   alignment policies.</simpara></listitem>
40  * </itemizedlist>
41  *
42  * <figure id="bin-layout">
43  *   <title>Bin layout</title>
44  *   <para>The image shows a #ClutterBinLayout with three layers:
45  *   a background #ClutterCairoTexture, set to fill on both the X
46  *   and Y axis; a #ClutterTexture, set to center on both the X and
47  *   Y axis; and a #ClutterRectangle, set to %CLUTTER_BIN_ALIGNMENT_END
48  *   on both the X and Y axis.</para>
49  *   <graphic fileref="bin-layout.png" format="PNG"/>
50  * </figure>
51  *
52  * <example id="example-clutter-bin-layout">
53  *  <title>How to pack actors inside a BinLayout</title>
54  *  <programlisting>
55  * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../tests/interactive/test-bin-layout.c">
56  *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
57  * </xi:include>
58  *  </programlisting>
59  * </example>
60  *
61  * #ClutterBinLayout is available since Clutter 1.2
62  */
63
64 #ifdef HAVE_CONFIG_H
65 #include "config.h"
66 #endif
67
68 #include <math.h>
69
70 #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
71 #include "deprecated/clutter-container.h"
72 #include "deprecated/clutter-bin-layout.h"
73
74 #include "clutter-actor-private.h"
75 #include "clutter-animatable.h"
76 #include "clutter-child-meta.h"
77 #include "clutter-debug.h"
78 #include "clutter-enum-types.h"
79 #include "clutter-layout-meta.h"
80 #include "clutter-private.h"
81
82 #define CLUTTER_TYPE_BIN_LAYER          (clutter_bin_layer_get_type ())
83 #define CLUTTER_BIN_LAYER(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIN_LAYER, ClutterBinLayer))
84 #define CLUTTER_IS_BIN_LAYER(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIN_LAYER))
85
86 #define CLUTTER_BIN_LAYOUT_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayoutPrivate))
87
88 typedef struct _ClutterBinLayer         ClutterBinLayer;
89 typedef struct _ClutterLayoutMetaClass  ClutterBinLayerClass;
90
91 struct _ClutterBinLayoutPrivate
92 {
93   ClutterBinAlignment x_align;
94   ClutterBinAlignment y_align;
95
96   ClutterContainer *container;
97 };
98
99 struct _ClutterBinLayer
100 {
101   ClutterLayoutMeta parent_instance;
102
103   ClutterBinAlignment x_align;
104   ClutterBinAlignment y_align;
105 };
106
107 enum
108 {
109   PROP_LAYER_0,
110
111   PROP_LAYER_X_ALIGN,
112   PROP_LAYER_Y_ALIGN,
113
114   PROP_LAYER_LAST
115 };
116
117 enum
118 {
119   PROP_0,
120
121   PROP_X_ALIGN,
122   PROP_Y_ALIGN,
123
124   PROP_LAST
125 };
126
127 static GParamSpec *layer_props[PROP_LAYER_LAST] = { NULL, };
128 static GParamSpec *bin_props[PROP_LAST] = { NULL, };
129
130 GType clutter_bin_layer_get_type (void);
131
132 G_DEFINE_TYPE (ClutterBinLayer,
133                clutter_bin_layer,
134                CLUTTER_TYPE_LAYOUT_META);
135
136 G_DEFINE_TYPE (ClutterBinLayout,
137                clutter_bin_layout,
138                CLUTTER_TYPE_LAYOUT_MANAGER);
139
140 /*
141  * ClutterBinLayer
142  */
143
144 static void
145 set_layer_x_align (ClutterBinLayer     *self,
146                    ClutterBinAlignment  alignment)
147 {
148   ClutterLayoutManager *manager;
149   ClutterLayoutMeta *meta;
150
151   if (self->x_align == alignment)
152     return;
153
154   self->x_align = alignment;
155
156   meta = CLUTTER_LAYOUT_META (self);
157   manager = clutter_layout_meta_get_manager (meta);
158   clutter_layout_manager_layout_changed (manager);
159
160   g_object_notify_by_pspec (G_OBJECT (self), layer_props[PROP_LAYER_X_ALIGN]);
161 }
162
163 static void
164 set_layer_y_align (ClutterBinLayer     *self,
165                    ClutterBinAlignment  alignment)
166 {
167   ClutterLayoutManager *manager;
168   ClutterLayoutMeta *meta;
169
170   if (self->y_align == alignment)
171     return;
172
173   self->y_align = alignment;
174
175   meta = CLUTTER_LAYOUT_META (self);
176   manager = clutter_layout_meta_get_manager (meta);
177   clutter_layout_manager_layout_changed (manager);
178
179   g_object_notify_by_pspec (G_OBJECT (self), layer_props[PROP_LAYER_Y_ALIGN]);
180 }
181
182 static void
183 clutter_bin_layer_set_property (GObject      *gobject,
184                                 guint         prop_id,
185                                 const GValue *value,
186                                 GParamSpec   *pspec)
187 {
188   ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject);
189
190   switch (prop_id)
191     {
192     case PROP_LAYER_X_ALIGN:
193       set_layer_x_align (layer, g_value_get_enum (value));
194       break;
195
196     case PROP_LAYER_Y_ALIGN:
197       set_layer_y_align (layer, g_value_get_enum (value));
198       break;
199
200     default:
201       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
202       break;
203     }
204 }
205
206 static void
207 clutter_bin_layer_get_property (GObject    *gobject,
208                                 guint       prop_id,
209                                 GValue     *value,
210                                 GParamSpec *pspec)
211 {
212   ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject);
213
214   switch (prop_id)
215     {
216     case PROP_LAYER_X_ALIGN:
217       g_value_set_enum (value, layer->x_align);
218       break;
219
220     case PROP_LAYER_Y_ALIGN:
221       g_value_set_enum (value, layer->y_align);
222       break;
223
224     default:
225       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
226       break;
227     }
228 }
229
230 static void
231 clutter_bin_layer_class_init (ClutterBinLayerClass *klass)
232 {
233   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
234
235   gobject_class->set_property = clutter_bin_layer_set_property;
236   gobject_class->get_property = clutter_bin_layer_get_property;
237
238   layer_props[PROP_LAYER_X_ALIGN] =
239     g_param_spec_enum ("x-align",
240                        P_("Horizontal Alignment"),
241                        P_("Horizontal alignment for the actor "
242                           "inside the layout manager"),
243                        CLUTTER_TYPE_BIN_ALIGNMENT,
244                        CLUTTER_BIN_ALIGNMENT_CENTER,
245                        CLUTTER_PARAM_READWRITE);
246
247   layer_props[PROP_LAYER_Y_ALIGN] =
248     g_param_spec_enum ("y-align",
249                        P_("Vertical Alignment"),
250                        P_("Vertical alignment for the actor "
251                           "inside the layout manager"),
252                        CLUTTER_TYPE_BIN_ALIGNMENT,
253                        CLUTTER_BIN_ALIGNMENT_CENTER,
254                        CLUTTER_PARAM_READWRITE);
255
256   g_object_class_install_properties (gobject_class,
257                                      PROP_LAYER_LAST,
258                                      layer_props);
259 }
260
261 static void
262 clutter_bin_layer_init (ClutterBinLayer *layer)
263 {
264   layer->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
265   layer->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
266 }
267
268 /*
269  * ClutterBinLayout
270  */
271
272 static void
273 set_x_align (ClutterBinLayout    *self,
274              ClutterBinAlignment  alignment)
275 {
276   ClutterBinLayoutPrivate *priv = self->priv;
277
278   if (priv->x_align != alignment)
279     {
280       ClutterLayoutManager *manager;
281
282       priv->x_align = alignment;
283
284       manager = CLUTTER_LAYOUT_MANAGER (self);
285       clutter_layout_manager_layout_changed (manager);
286
287       g_object_notify_by_pspec (G_OBJECT (self), bin_props[PROP_X_ALIGN]);
288     }
289 }
290
291 static void
292 set_y_align (ClutterBinLayout    *self,
293              ClutterBinAlignment  alignment)
294 {
295   ClutterBinLayoutPrivate *priv = self->priv;
296
297   if (priv->y_align != alignment)
298     {
299       ClutterLayoutManager *manager;
300
301       priv->y_align = alignment;
302
303       manager = CLUTTER_LAYOUT_MANAGER (self);
304       clutter_layout_manager_layout_changed (manager);
305
306       g_object_notify_by_pspec (G_OBJECT (self), bin_props[PROP_Y_ALIGN]);
307     }
308 }
309
310 static void
311 clutter_bin_layout_get_preferred_width (ClutterLayoutManager *manager,
312                                         ClutterContainer     *container,
313                                         gfloat                for_height,
314                                         gfloat               *min_width_p,
315                                         gfloat               *nat_width_p)
316 {
317   ClutterActor *actor = CLUTTER_ACTOR (container);
318   ClutterActorIter iter;
319   ClutterActor *child;
320   gfloat min_width, nat_width;
321
322   min_width = nat_width = 0.0;
323
324   clutter_actor_iter_init (&iter, actor);
325   while (clutter_actor_iter_next (&iter, &child))
326     {
327       gfloat minimum, natural;
328
329       clutter_actor_get_preferred_width (child, for_height,
330                                          &minimum,
331                                          &natural);
332
333       min_width = MAX (min_width, minimum);
334       nat_width = MAX (nat_width, natural);
335     }
336
337   if (min_width_p)
338     *min_width_p = min_width;
339
340   if (nat_width_p)
341     *nat_width_p = nat_width;
342 }
343
344 static void
345 clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager,
346                                          ClutterContainer     *container,
347                                          gfloat                for_width,
348                                          gfloat               *min_height_p,
349                                          gfloat               *nat_height_p)
350 {
351   ClutterActor *actor = CLUTTER_ACTOR (container);
352   ClutterActorIter iter;
353   ClutterActor *child;
354   gfloat min_height, nat_height;
355
356   min_height = nat_height = 0.0;
357
358   clutter_actor_iter_init (&iter, actor);
359   while (clutter_actor_iter_next (&iter, &child))
360     {
361       gfloat minimum, natural;
362
363       clutter_actor_get_preferred_height (child, for_width,
364                                           &minimum,
365                                           &natural);
366
367       min_height = MAX (min_height, minimum);
368       nat_height = MAX (nat_height, natural);
369     }
370
371   if (min_height_p)
372     *min_height_p = min_height;
373
374   if (nat_height_p)
375     *nat_height_p = nat_height;
376 }
377
378 static gdouble
379 get_bin_alignment_factor (ClutterBinAlignment alignment)
380 {
381   switch (alignment)
382     {
383     case CLUTTER_BIN_ALIGNMENT_CENTER:
384       return 0.5;
385
386     case CLUTTER_BIN_ALIGNMENT_START:
387       return 0.0;
388
389     case CLUTTER_BIN_ALIGNMENT_END:
390       return 1.0;
391
392     case CLUTTER_BIN_ALIGNMENT_FIXED:
393     case CLUTTER_BIN_ALIGNMENT_FILL:
394       return 0.0;
395     }
396
397   return 0.0;
398 }
399
400 static gdouble
401 get_actor_align_factor (ClutterActorAlign alignment)
402 {
403   switch (alignment)
404     {
405     case CLUTTER_ACTOR_ALIGN_CENTER:
406       return 0.5;
407
408     case CLUTTER_ACTOR_ALIGN_START:
409       return 0.0;
410
411     case CLUTTER_ACTOR_ALIGN_END:
412       return 1.0;
413
414     case CLUTTER_ACTOR_ALIGN_FILL:
415       return 0.0;
416     }
417
418   return 0.0;
419 }
420
421 static void
422 clutter_bin_layout_allocate (ClutterLayoutManager   *manager,
423                              ClutterContainer       *container,
424                              const ClutterActorBox  *allocation,
425                              ClutterAllocationFlags  flags)
426 {
427   gfloat allocation_x, allocation_y;
428   gfloat available_w, available_h;
429   ClutterActor *actor, *child;
430   ClutterActorIter iter;
431
432   clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y);
433   clutter_actor_box_get_size (allocation, &available_w, &available_h);
434
435   actor = CLUTTER_ACTOR (container);
436
437   clutter_actor_iter_init (&iter, actor);
438   while (clutter_actor_iter_next (&iter, &child))
439     {
440       ClutterLayoutMeta *meta;
441       ClutterBinLayer *layer;
442       ClutterActorBox child_alloc = { 0, };
443       gdouble x_align, y_align;
444       gboolean x_fill, y_fill;
445
446       meta = clutter_layout_manager_get_child_meta (manager,
447                                                     container,
448                                                     child);
449       layer = CLUTTER_BIN_LAYER (meta);
450
451       if (layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED)
452         child_alloc.x1 = clutter_actor_get_x (child);
453       else
454         child_alloc.x1 = allocation_x;
455
456       if (layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED)
457         child_alloc.y1 = clutter_actor_get_y (child);
458       else
459         child_alloc.y1 = allocation_y;
460
461       child_alloc.x2 = available_w;
462       child_alloc.y2 = available_h;
463
464       if (clutter_actor_needs_x_expand (child))
465         {
466           ClutterActorAlign align;
467
468           align = _clutter_actor_get_effective_x_align (child);
469           x_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
470           x_align = get_actor_align_factor (align);
471         }
472       else
473         {
474           x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL);
475           x_align = get_bin_alignment_factor (layer->x_align);
476         }
477
478       if (clutter_actor_needs_y_expand (child))
479         {
480           ClutterActorAlign align;
481
482           align = clutter_actor_get_y_align (child);
483           y_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
484           y_align = get_actor_align_factor (align);
485         }
486       else
487         {
488           y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL);
489           y_align = get_bin_alignment_factor (layer->y_align);
490         }
491
492       clutter_actor_allocate_align_fill (child, &child_alloc,
493                                          x_align, y_align,
494                                          x_fill, y_fill,
495                                          flags);
496     }
497 }
498
499 static GType
500 clutter_bin_layout_get_child_meta_type (ClutterLayoutManager *manager)
501 {
502   return CLUTTER_TYPE_BIN_LAYER;
503 }
504
505 static ClutterLayoutMeta *
506 clutter_bin_layout_create_child_meta (ClutterLayoutManager *manager,
507                                       ClutterContainer     *container,
508                                       ClutterActor         *actor)
509 {
510   ClutterBinLayoutPrivate *priv;
511
512   priv = CLUTTER_BIN_LAYOUT (manager)->priv;
513
514   return g_object_new (CLUTTER_TYPE_BIN_LAYER,
515                        "container", container,
516                        "actor", actor,
517                        "manager", manager,
518                        "x-align", priv->x_align,
519                        "y_align", priv->y_align,
520                        NULL);
521 }
522
523 static void
524 clutter_bin_layout_set_container (ClutterLayoutManager *manager,
525                                   ClutterContainer     *container)
526 {
527   ClutterBinLayoutPrivate *priv;
528   ClutterLayoutManagerClass *parent_class;
529
530   priv = CLUTTER_BIN_LAYOUT (manager)->priv;
531   priv->container = container;
532
533   parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_bin_layout_parent_class);
534   parent_class->set_container (manager, container);
535 }
536
537 static void
538 clutter_bin_layout_set_property (GObject      *gobject,
539                                  guint         prop_id,
540                                  const GValue *value,
541                                  GParamSpec   *pspec)
542 {
543   ClutterBinLayout *layout = CLUTTER_BIN_LAYOUT (gobject);
544
545   switch (prop_id)
546     {
547     case PROP_X_ALIGN:
548       set_x_align (layout, g_value_get_enum (value));
549       break;
550
551     case PROP_Y_ALIGN:
552       set_y_align (layout, g_value_get_enum (value));
553       break;
554
555     default:
556       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
557       break;
558     }
559 }
560
561 static void
562 clutter_bin_layout_get_property (GObject    *gobject,
563                                  guint       prop_id,
564                                  GValue     *value,
565                                  GParamSpec *pspec)
566 {
567   ClutterBinLayoutPrivate *priv;
568
569   priv = CLUTTER_BIN_LAYOUT (gobject)->priv;
570
571   switch (prop_id)
572     {
573     case PROP_X_ALIGN:
574       g_value_set_enum (value, priv->x_align);
575       break;
576
577     case PROP_Y_ALIGN:
578       g_value_set_enum (value, priv->y_align);
579       break;
580
581     default:
582       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
583       break;
584     }
585 }
586
587 static void
588 clutter_bin_layout_class_init (ClutterBinLayoutClass *klass)
589 {
590   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
591   ClutterLayoutManagerClass *layout_class =
592     CLUTTER_LAYOUT_MANAGER_CLASS (klass);
593
594   g_type_class_add_private (klass, sizeof (ClutterBinLayoutPrivate));
595
596   /**
597    * ClutterBinLayout:x-align:
598    *
599    * The default horizontal alignment policy for actors managed
600    * by the #ClutterBinLayout
601    *
602    * Since: 1.2
603    *
604    * Deprecated: 1.12: Use the #ClutterActor:x-expand and the
605    *   #ClutterActor:x-align properties on #ClutterActor instead.
606    */
607   bin_props[PROP_X_ALIGN] =
608     g_param_spec_enum ("x-align",
609                        P_("Horizontal Alignment"),
610                        P_("Default horizontal alignment for the actors "
611                           "inside the layout manager"),
612                        CLUTTER_TYPE_BIN_ALIGNMENT,
613                        CLUTTER_BIN_ALIGNMENT_CENTER,
614                        CLUTTER_PARAM_READWRITE);
615
616   /**
617    * ClutterBinLayout:y-align:
618    *
619    * The default vertical alignment policy for actors managed
620    * by the #ClutterBinLayout
621    *
622    * Since: 1.2
623    *
624    * Deprecated: 1.12: Use the #ClutterActor:y-expand and the
625    *   #ClutterActor:y-align properties on #ClutterActor instead.
626    */
627   bin_props[PROP_Y_ALIGN] =
628     g_param_spec_enum ("y-align",
629                        P_("Vertical Alignment"),
630                        P_("Default vertical alignment for the actors "
631                           "inside the layout manager"),
632                        CLUTTER_TYPE_BIN_ALIGNMENT,
633                        CLUTTER_BIN_ALIGNMENT_CENTER,
634                        CLUTTER_PARAM_READWRITE);
635
636   gobject_class->set_property = clutter_bin_layout_set_property;
637   gobject_class->get_property = clutter_bin_layout_get_property;
638   g_object_class_install_properties (gobject_class, PROP_LAST, bin_props);
639
640   layout_class->get_preferred_width = clutter_bin_layout_get_preferred_width;
641   layout_class->get_preferred_height = clutter_bin_layout_get_preferred_height;
642   layout_class->allocate = clutter_bin_layout_allocate;
643   layout_class->create_child_meta = clutter_bin_layout_create_child_meta;
644   layout_class->get_child_meta_type = clutter_bin_layout_get_child_meta_type;
645   layout_class->set_container = clutter_bin_layout_set_container;
646 }
647
648 static void
649 clutter_bin_layout_init (ClutterBinLayout *self)
650 {
651   self->priv = CLUTTER_BIN_LAYOUT_GET_PRIVATE (self);
652
653   self->priv->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
654   self->priv->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
655 }
656
657 /**
658  * clutter_bin_layout_new:
659  * @x_align: the default alignment policy to be used on the
660  *   horizontal axis
661  * @y_align: the default alignment policy to be used on the
662  *   vertical axis
663  *
664  * Creates a new #ClutterBinLayout layout manager
665  *
666  * Return value: the newly created layout manager
667  *
668  * Since: 1.2
669  */
670 ClutterLayoutManager *
671 clutter_bin_layout_new (ClutterBinAlignment x_align,
672                         ClutterBinAlignment y_align)
673 {
674   return g_object_new (CLUTTER_TYPE_BIN_LAYOUT,
675                        "x-align", x_align,
676                        "y-align", y_align,
677                        NULL);
678 }
679
680 /**
681  * clutter_bin_layout_set_alignment:
682  * @self: a #ClutterBinLayout
683  * @child: (allow-none): a child of @container
684  * @x_align: the horizontal alignment policy to be used for the @child
685  *   inside @container
686  * @y_align: the vertical aligment policy to be used on the @child
687  *   inside @container
688  *
689  * Sets the horizontal and vertical alignment policies to be applied
690  * to a @child of @self
691  *
692  * If @child is %NULL then the @x_align and @y_align values will
693  * be set as the default alignment policies
694  *
695  * Since: 1.2
696  *
697  * Deprecated: 1.12: Use the #ClutterActor:x-align and
698  *   #ClutterActor:y-align properties of #ClutterActor instead.
699  */
700 void
701 clutter_bin_layout_set_alignment (ClutterBinLayout    *self,
702                                   ClutterActor        *child,
703                                   ClutterBinAlignment  x_align,
704                                   ClutterBinAlignment  y_align)
705 {
706   ClutterBinLayoutPrivate *priv;
707   ClutterLayoutManager *manager;
708   ClutterLayoutMeta *meta;
709
710   g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
711   g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
712
713   priv = self->priv;
714
715   if (priv->container == NULL)
716     {
717       if (child == NULL)
718         {
719           set_x_align (self, x_align);
720           set_y_align (self, y_align);
721         }
722       else
723         g_warning ("The layout of type '%s' must be associated to "
724                    "a ClutterContainer before setting the alignment "
725                    "on its children",
726                    G_OBJECT_TYPE_NAME (self));
727
728       return;
729     }
730
731   manager = CLUTTER_LAYOUT_MANAGER (self);
732   meta = clutter_layout_manager_get_child_meta (manager,
733                                                 priv->container,
734                                                 child);
735   g_assert (CLUTTER_IS_BIN_LAYER (meta));
736
737   set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
738   set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
739 }
740
741 /**
742  * clutter_bin_layout_get_alignment:
743  * @self: a #ClutterBinLayout
744  * @child: (allow-none): a child of @container
745  * @x_align: (out) (allow-none): return location for the horizontal
746  *   alignment policy
747  * @y_align: (out) (allow-none): return location for the vertical
748  *   alignment policy
749  *
750  * Retrieves the horizontal and vertical alignment policies for
751  * a child of @self
752  *
753  * If @child is %NULL the default alignment policies will be returned
754  * instead
755  *
756  * Since: 1.2
757  *
758  * Deprecated: 1.12: Use the #ClutterActor:x-align and the
759  *   #ClutterActor:y-align properties of #ClutterActor instead.
760  */
761 void
762 clutter_bin_layout_get_alignment (ClutterBinLayout    *self,
763                                   ClutterActor        *child,
764                                   ClutterBinAlignment *x_align,
765                                   ClutterBinAlignment *y_align)
766 {
767   ClutterBinLayoutPrivate *priv;
768   ClutterLayoutManager *manager;
769   ClutterLayoutMeta *meta;
770   ClutterBinLayer *layer;
771
772   g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
773
774   priv = self->priv;
775
776   if (priv->container == NULL)
777     {
778       if (child == NULL)
779         {
780           if (x_align)
781             *x_align = priv->x_align;
782
783           if (y_align)
784             *y_align = priv->y_align;
785         }
786       else
787         g_warning ("The layout of type '%s' must be associated to "
788                    "a ClutterContainer before getting the alignment "
789                    "of its children",
790                    G_OBJECT_TYPE_NAME (self));
791
792       return;
793     }
794
795   manager = CLUTTER_LAYOUT_MANAGER (self);
796   meta = clutter_layout_manager_get_child_meta (manager,
797                                                 priv->container,
798                                                 child);
799   g_assert (CLUTTER_IS_BIN_LAYER (meta));
800
801   layer = CLUTTER_BIN_LAYER (meta);
802
803   if (x_align)
804     *x_align = layer->x_align;
805
806   if (y_align)
807     *y_align = layer->y_align;
808 }
809
810 /**
811  * clutter_bin_layout_add:
812  * @self: a #ClutterBinLayout
813  * @child: a #ClutterActor
814  * @x_align: horizontal alignment policy for @child
815  * @y_align: vertical alignment policy for @child
816  *
817  * Adds a #ClutterActor to the container using @self and
818  * sets the alignment policies for it
819  *
820  * This function is equivalent to clutter_container_add_actor()
821  * and clutter_layout_manager_child_set_property() but it does not
822  * require a pointer to the #ClutterContainer associated to the
823  * #ClutterBinLayout
824  *
825  * Since: 1.2
826  *
827  * Deprecated: 1.12: Use clutter_actor_add_child() instead.
828  */
829 void
830 clutter_bin_layout_add (ClutterBinLayout    *self,
831                         ClutterActor        *child,
832                         ClutterBinAlignment  x_align,
833                         ClutterBinAlignment  y_align)
834 {
835   ClutterBinLayoutPrivate *priv;
836   ClutterLayoutManager *manager;
837   ClutterLayoutMeta *meta;
838
839   g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
840   g_return_if_fail (CLUTTER_IS_ACTOR (child));
841
842   priv = self->priv;
843
844   if (priv->container == NULL)
845     {
846       g_warning ("The layout of type '%s' must be associated to "
847                  "a ClutterContainer before adding children",
848                  G_OBJECT_TYPE_NAME (self));
849       return;
850     }
851
852   clutter_container_add_actor (priv->container, child);
853
854   manager = CLUTTER_LAYOUT_MANAGER (self);
855   meta = clutter_layout_manager_get_child_meta (manager,
856                                                 priv->container,
857                                                 child);
858   g_assert (CLUTTER_IS_BIN_LAYER (meta));
859
860   set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
861   set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
862 }