Release Clutter 1.11.4 (snapshot)
[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="../../../../examples/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       if (!CLUTTER_ACTOR_IS_VISIBLE (child))
330         continue;
331
332       clutter_actor_get_preferred_width (child, for_height,
333                                          &minimum,
334                                          &natural);
335
336       min_width = MAX (min_width, minimum);
337       nat_width = MAX (nat_width, natural);
338     }
339
340   if (min_width_p)
341     *min_width_p = min_width;
342
343   if (nat_width_p)
344     *nat_width_p = nat_width;
345 }
346
347 static void
348 clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager,
349                                          ClutterContainer     *container,
350                                          gfloat                for_width,
351                                          gfloat               *min_height_p,
352                                          gfloat               *nat_height_p)
353 {
354   ClutterActor *actor = CLUTTER_ACTOR (container);
355   ClutterActorIter iter;
356   ClutterActor *child;
357   gfloat min_height, nat_height;
358
359   min_height = nat_height = 0.0;
360
361   clutter_actor_iter_init (&iter, actor);
362   while (clutter_actor_iter_next (&iter, &child))
363     {
364       gfloat minimum, natural;
365
366       if (!CLUTTER_ACTOR_IS_VISIBLE (child))
367         continue;
368
369       clutter_actor_get_preferred_height (child, for_width,
370                                           &minimum,
371                                           &natural);
372
373       min_height = MAX (min_height, minimum);
374       nat_height = MAX (nat_height, natural);
375     }
376
377   if (min_height_p)
378     *min_height_p = min_height;
379
380   if (nat_height_p)
381     *nat_height_p = nat_height;
382 }
383
384 static gdouble
385 get_bin_alignment_factor (ClutterBinAlignment alignment)
386 {
387   switch (alignment)
388     {
389     case CLUTTER_BIN_ALIGNMENT_CENTER:
390       return 0.5;
391
392     case CLUTTER_BIN_ALIGNMENT_START:
393       return 0.0;
394
395     case CLUTTER_BIN_ALIGNMENT_END:
396       return 1.0;
397
398     case CLUTTER_BIN_ALIGNMENT_FIXED:
399     case CLUTTER_BIN_ALIGNMENT_FILL:
400       return 0.0;
401     }
402
403   return 0.0;
404 }
405
406 static gdouble
407 get_actor_align_factor (ClutterActorAlign alignment)
408 {
409   switch (alignment)
410     {
411     case CLUTTER_ACTOR_ALIGN_CENTER:
412       return 0.5;
413
414     case CLUTTER_ACTOR_ALIGN_START:
415       return 0.0;
416
417     case CLUTTER_ACTOR_ALIGN_END:
418       return 1.0;
419
420     case CLUTTER_ACTOR_ALIGN_FILL:
421       return 0.0;
422     }
423
424   return 0.0;
425 }
426
427 static void
428 clutter_bin_layout_allocate (ClutterLayoutManager   *manager,
429                              ClutterContainer       *container,
430                              const ClutterActorBox  *allocation,
431                              ClutterAllocationFlags  flags)
432 {
433   gfloat allocation_x, allocation_y;
434   gfloat available_w, available_h;
435   ClutterActor *actor, *child;
436   ClutterActorIter iter;
437   gboolean use_animations;
438   ClutterAnimationMode easing_mode;
439   guint easing_duration, easing_delay;
440
441   clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y);
442   clutter_actor_box_get_size (allocation, &available_w, &available_h);
443
444   actor = CLUTTER_ACTOR (container);
445
446   use_animations = clutter_layout_manager_get_easing_state (manager,
447                                                             &easing_mode,
448                                                             &easing_duration,
449                                                             &easing_delay);
450   clutter_actor_iter_init (&iter, actor);
451   while (clutter_actor_iter_next (&iter, &child))
452     {
453       ClutterLayoutMeta *meta;
454       ClutterBinLayer *layer;
455       ClutterActorBox child_alloc = { 0, };
456       gdouble x_align, y_align;
457       gboolean x_fill, y_fill;
458
459       meta = clutter_layout_manager_get_child_meta (manager,
460                                                     container,
461                                                     child);
462       layer = CLUTTER_BIN_LAYER (meta);
463
464       if (layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED)
465         child_alloc.x1 = clutter_actor_get_x (child);
466       else
467         child_alloc.x1 = allocation_x;
468
469       if (layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED)
470         child_alloc.y1 = clutter_actor_get_y (child);
471       else
472         child_alloc.y1 = allocation_y;
473
474       child_alloc.x2 = available_w;
475       child_alloc.y2 = available_h;
476
477       if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL))
478         {
479           ClutterActorAlign align;
480
481           align = _clutter_actor_get_effective_x_align (child);
482           x_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
483           x_align = get_actor_align_factor (align);
484         }
485       else
486         {
487           x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL);
488           x_align = get_bin_alignment_factor (layer->x_align);
489         }
490
491       if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL))
492         {
493           ClutterActorAlign align;
494
495           align = clutter_actor_get_y_align (child);
496           y_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
497           y_align = get_actor_align_factor (align);
498         }
499       else
500         {
501           y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL);
502           y_align = get_bin_alignment_factor (layer->y_align);
503         }
504
505       if (use_animations)
506         {
507           clutter_actor_save_easing_state (child);
508           clutter_actor_set_easing_mode (child, easing_mode);
509           clutter_actor_set_easing_duration (child, easing_duration);
510           clutter_actor_set_easing_delay (child, easing_delay);
511         }
512
513       clutter_actor_allocate_align_fill (child, &child_alloc,
514                                          x_align, y_align,
515                                          x_fill, y_fill,
516                                          flags);
517
518       if (use_animations)
519         clutter_actor_restore_easing_state (child);
520     }
521 }
522
523 static GType
524 clutter_bin_layout_get_child_meta_type (ClutterLayoutManager *manager)
525 {
526   return CLUTTER_TYPE_BIN_LAYER;
527 }
528
529 static ClutterLayoutMeta *
530 clutter_bin_layout_create_child_meta (ClutterLayoutManager *manager,
531                                       ClutterContainer     *container,
532                                       ClutterActor         *actor)
533 {
534   ClutterBinLayoutPrivate *priv;
535
536   priv = CLUTTER_BIN_LAYOUT (manager)->priv;
537
538   return g_object_new (CLUTTER_TYPE_BIN_LAYER,
539                        "container", container,
540                        "actor", actor,
541                        "manager", manager,
542                        "x-align", priv->x_align,
543                        "y_align", priv->y_align,
544                        NULL);
545 }
546
547 static void
548 clutter_bin_layout_set_container (ClutterLayoutManager *manager,
549                                   ClutterContainer     *container)
550 {
551   ClutterBinLayoutPrivate *priv;
552   ClutterLayoutManagerClass *parent_class;
553
554   priv = CLUTTER_BIN_LAYOUT (manager)->priv;
555   priv->container = container;
556
557   parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_bin_layout_parent_class);
558   parent_class->set_container (manager, container);
559 }
560
561 static void
562 clutter_bin_layout_set_property (GObject      *gobject,
563                                  guint         prop_id,
564                                  const GValue *value,
565                                  GParamSpec   *pspec)
566 {
567   ClutterBinLayout *layout = CLUTTER_BIN_LAYOUT (gobject);
568
569   switch (prop_id)
570     {
571     case PROP_X_ALIGN:
572       set_x_align (layout, g_value_get_enum (value));
573       break;
574
575     case PROP_Y_ALIGN:
576       set_y_align (layout, g_value_get_enum (value));
577       break;
578
579     default:
580       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
581       break;
582     }
583 }
584
585 static void
586 clutter_bin_layout_get_property (GObject    *gobject,
587                                  guint       prop_id,
588                                  GValue     *value,
589                                  GParamSpec *pspec)
590 {
591   ClutterBinLayoutPrivate *priv;
592
593   priv = CLUTTER_BIN_LAYOUT (gobject)->priv;
594
595   switch (prop_id)
596     {
597     case PROP_X_ALIGN:
598       g_value_set_enum (value, priv->x_align);
599       break;
600
601     case PROP_Y_ALIGN:
602       g_value_set_enum (value, priv->y_align);
603       break;
604
605     default:
606       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
607       break;
608     }
609 }
610
611 static void
612 clutter_bin_layout_class_init (ClutterBinLayoutClass *klass)
613 {
614   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
615   ClutterLayoutManagerClass *layout_class =
616     CLUTTER_LAYOUT_MANAGER_CLASS (klass);
617
618   g_type_class_add_private (klass, sizeof (ClutterBinLayoutPrivate));
619
620   /**
621    * ClutterBinLayout:x-align:
622    *
623    * The default horizontal alignment policy for actors managed
624    * by the #ClutterBinLayout
625    *
626    * Since: 1.2
627    *
628    * Deprecated: 1.12: Use the #ClutterActor:x-expand and the
629    *   #ClutterActor:x-align properties on #ClutterActor instead.
630    */
631   bin_props[PROP_X_ALIGN] =
632     g_param_spec_enum ("x-align",
633                        P_("Horizontal Alignment"),
634                        P_("Default horizontal alignment for the actors "
635                           "inside the layout manager"),
636                        CLUTTER_TYPE_BIN_ALIGNMENT,
637                        CLUTTER_BIN_ALIGNMENT_CENTER,
638                        CLUTTER_PARAM_READWRITE);
639
640   /**
641    * ClutterBinLayout:y-align:
642    *
643    * The default vertical alignment policy for actors managed
644    * by the #ClutterBinLayout
645    *
646    * Since: 1.2
647    *
648    * Deprecated: 1.12: Use the #ClutterActor:y-expand and the
649    *   #ClutterActor:y-align properties on #ClutterActor instead.
650    */
651   bin_props[PROP_Y_ALIGN] =
652     g_param_spec_enum ("y-align",
653                        P_("Vertical Alignment"),
654                        P_("Default vertical alignment for the actors "
655                           "inside the layout manager"),
656                        CLUTTER_TYPE_BIN_ALIGNMENT,
657                        CLUTTER_BIN_ALIGNMENT_CENTER,
658                        CLUTTER_PARAM_READWRITE);
659
660   gobject_class->set_property = clutter_bin_layout_set_property;
661   gobject_class->get_property = clutter_bin_layout_get_property;
662   g_object_class_install_properties (gobject_class, PROP_LAST, bin_props);
663
664   layout_class->get_preferred_width = clutter_bin_layout_get_preferred_width;
665   layout_class->get_preferred_height = clutter_bin_layout_get_preferred_height;
666   layout_class->allocate = clutter_bin_layout_allocate;
667   layout_class->create_child_meta = clutter_bin_layout_create_child_meta;
668   layout_class->get_child_meta_type = clutter_bin_layout_get_child_meta_type;
669   layout_class->set_container = clutter_bin_layout_set_container;
670 }
671
672 static void
673 clutter_bin_layout_init (ClutterBinLayout *self)
674 {
675   self->priv = CLUTTER_BIN_LAYOUT_GET_PRIVATE (self);
676
677   self->priv->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
678   self->priv->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
679 }
680
681 /**
682  * clutter_bin_layout_new:
683  * @x_align: the default alignment policy to be used on the
684  *   horizontal axis
685  * @y_align: the default alignment policy to be used on the
686  *   vertical axis
687  *
688  * Creates a new #ClutterBinLayout layout manager
689  *
690  * Return value: the newly created layout manager
691  *
692  * Since: 1.2
693  */
694 ClutterLayoutManager *
695 clutter_bin_layout_new (ClutterBinAlignment x_align,
696                         ClutterBinAlignment y_align)
697 {
698   return g_object_new (CLUTTER_TYPE_BIN_LAYOUT,
699                        "x-align", x_align,
700                        "y-align", y_align,
701                        NULL);
702 }
703
704 /**
705  * clutter_bin_layout_set_alignment:
706  * @self: a #ClutterBinLayout
707  * @child: (allow-none): a child of @container
708  * @x_align: the horizontal alignment policy to be used for the @child
709  *   inside @container
710  * @y_align: the vertical aligment policy to be used on the @child
711  *   inside @container
712  *
713  * Sets the horizontal and vertical alignment policies to be applied
714  * to a @child of @self
715  *
716  * If @child is %NULL then the @x_align and @y_align values will
717  * be set as the default alignment policies
718  *
719  * Since: 1.2
720  *
721  * Deprecated: 1.12: Use the #ClutterActor:x-align and
722  *   #ClutterActor:y-align properties of #ClutterActor instead.
723  */
724 void
725 clutter_bin_layout_set_alignment (ClutterBinLayout    *self,
726                                   ClutterActor        *child,
727                                   ClutterBinAlignment  x_align,
728                                   ClutterBinAlignment  y_align)
729 {
730   ClutterBinLayoutPrivate *priv;
731   ClutterLayoutManager *manager;
732   ClutterLayoutMeta *meta;
733
734   g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
735   g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
736
737   priv = self->priv;
738
739   if (priv->container == NULL)
740     {
741       if (child == NULL)
742         {
743           set_x_align (self, x_align);
744           set_y_align (self, y_align);
745         }
746       else
747         g_warning ("The layout of type '%s' must be associated to "
748                    "a ClutterContainer before setting the alignment "
749                    "on its children",
750                    G_OBJECT_TYPE_NAME (self));
751
752       return;
753     }
754
755   manager = CLUTTER_LAYOUT_MANAGER (self);
756   meta = clutter_layout_manager_get_child_meta (manager,
757                                                 priv->container,
758                                                 child);
759   g_assert (CLUTTER_IS_BIN_LAYER (meta));
760
761   set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
762   set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
763 }
764
765 /**
766  * clutter_bin_layout_get_alignment:
767  * @self: a #ClutterBinLayout
768  * @child: (allow-none): a child of @container
769  * @x_align: (out) (allow-none): return location for the horizontal
770  *   alignment policy
771  * @y_align: (out) (allow-none): return location for the vertical
772  *   alignment policy
773  *
774  * Retrieves the horizontal and vertical alignment policies for
775  * a child of @self
776  *
777  * If @child is %NULL the default alignment policies will be returned
778  * instead
779  *
780  * Since: 1.2
781  *
782  * Deprecated: 1.12: Use the #ClutterActor:x-align and the
783  *   #ClutterActor:y-align properties of #ClutterActor instead.
784  */
785 void
786 clutter_bin_layout_get_alignment (ClutterBinLayout    *self,
787                                   ClutterActor        *child,
788                                   ClutterBinAlignment *x_align,
789                                   ClutterBinAlignment *y_align)
790 {
791   ClutterBinLayoutPrivate *priv;
792   ClutterLayoutManager *manager;
793   ClutterLayoutMeta *meta;
794   ClutterBinLayer *layer;
795
796   g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
797
798   priv = self->priv;
799
800   if (priv->container == NULL)
801     {
802       if (child == NULL)
803         {
804           if (x_align)
805             *x_align = priv->x_align;
806
807           if (y_align)
808             *y_align = priv->y_align;
809         }
810       else
811         g_warning ("The layout of type '%s' must be associated to "
812                    "a ClutterContainer before getting the alignment "
813                    "of its children",
814                    G_OBJECT_TYPE_NAME (self));
815
816       return;
817     }
818
819   manager = CLUTTER_LAYOUT_MANAGER (self);
820   meta = clutter_layout_manager_get_child_meta (manager,
821                                                 priv->container,
822                                                 child);
823   g_assert (CLUTTER_IS_BIN_LAYER (meta));
824
825   layer = CLUTTER_BIN_LAYER (meta);
826
827   if (x_align)
828     *x_align = layer->x_align;
829
830   if (y_align)
831     *y_align = layer->y_align;
832 }
833
834 /**
835  * clutter_bin_layout_add:
836  * @self: a #ClutterBinLayout
837  * @child: a #ClutterActor
838  * @x_align: horizontal alignment policy for @child
839  * @y_align: vertical alignment policy for @child
840  *
841  * Adds a #ClutterActor to the container using @self and
842  * sets the alignment policies for it
843  *
844  * This function is equivalent to clutter_container_add_actor()
845  * and clutter_layout_manager_child_set_property() but it does not
846  * require a pointer to the #ClutterContainer associated to the
847  * #ClutterBinLayout
848  *
849  * Since: 1.2
850  *
851  * Deprecated: 1.12: Use clutter_actor_add_child() instead.
852  */
853 void
854 clutter_bin_layout_add (ClutterBinLayout    *self,
855                         ClutterActor        *child,
856                         ClutterBinAlignment  x_align,
857                         ClutterBinAlignment  y_align)
858 {
859   ClutterBinLayoutPrivate *priv;
860   ClutterLayoutManager *manager;
861   ClutterLayoutMeta *meta;
862
863   g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
864   g_return_if_fail (CLUTTER_IS_ACTOR (child));
865
866   priv = self->priv;
867
868   if (priv->container == NULL)
869     {
870       g_warning ("The layout of type '%s' must be associated to "
871                  "a ClutterContainer before adding children",
872                  G_OBJECT_TYPE_NAME (self));
873       return;
874     }
875
876   clutter_container_add_actor (priv->container, child);
877
878   manager = CLUTTER_LAYOUT_MANAGER (self);
879   meta = clutter_layout_manager_get_child_meta (manager,
880                                                 priv->container,
881                                                 child);
882   g_assert (CLUTTER_IS_BIN_LAYER (meta));
883
884   set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
885   set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
886 }