4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2009 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 * Jose Dapena Paz <jdapena@igalia.com>
24 * Based on the MX MxTable actor by:
25 * Thomas Wood <thomas.wood@intel.com>
26 * and ClutterBoxLayout by:
27 * Emmanuele Bassi <ebassi@linux.intel.com>
31 * SECTION:clutter-table-layout
32 * @title: ClutterTableLayout
33 * @short_description: A layout manager arranging children in rows
36 * The #ClutterTableLayout is a #ClutterLayoutManager implementing the
37 * following layout policy:
40 * <listitem><para>children are arranged in a table</para></listitem>
41 * <listitem><para>each child specifies the specific row and column
42 * cell to appear;</para></listitem>
43 * <listitem><para>a child can also set a span, and this way, take
44 * more than one cell both horizontally and vertically;</para></listitem>
45 * <listitem><para>each child will be allocated to its natural
46 * size or, if set to expand, the available size;</para></listitem>
47 * <listitem><para>if a child is set to fill on either (or both)
48 * axis, its allocation will match all the available size; the
49 * fill layout property only makes sense if the expand property is
50 * also set;</para></listitem>
51 * <listitem><para>if a child is set to expand but not to fill then
52 * it is possible to control the alignment using the horizontal and
53 * vertical alignment layout properties.</para></listitem>
56 * It is possible to control the spacing between children of a
57 * #ClutterTableLayout by using clutter_table_layout_set_row_spacing()
58 * and clutter_table_layout_set_column_spacing().
60 * In order to set the layout properties when packing an actor inside a
61 * #ClutterTableLayout you should use the clutter_table_layout_pack()
64 * A #ClutterTableLayout can use animations to transition between different
65 * values of the layout management properties; the easing mode and duration
66 * used for the animations are controlled by the
67 * #ClutterTableLayout:easing-mode and #ClutterTableLayout:easing-duration
68 * properties and their accessor functions.
70 * <figure id="table-layout-image">
71 * <title>Table layout</title>
72 * <para>The image shows a #ClutterTableLayout.</para>
73 * <graphic fileref="table-layout.png" format="PNG"/>
76 * #ClutterTableLayout is available since Clutter 1.4
85 #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
86 #include "deprecated/clutter-container.h"
87 #include "deprecated/clutter-alpha.h"
89 #include "clutter-table-layout.h"
91 #include "clutter-debug.h"
92 #include "clutter-enum-types.h"
93 #include "clutter-layout-meta.h"
94 #include "clutter-private.h"
95 #include "clutter-types.h"
97 #define CLUTTER_TYPE_TABLE_CHILD (clutter_table_child_get_type ())
98 #define CLUTTER_TABLE_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TABLE_CHILD, ClutterTableChild))
99 #define CLUTTER_IS_TABLE_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TABLE_CHILD))
101 #define CLUTTER_TABLE_LAYOUT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_TABLE_LAYOUT, ClutterTableLayoutPrivate))
103 typedef struct _ClutterTableChild ClutterTableChild;
104 typedef struct _ClutterLayoutMetaClass ClutterTableChildClass;
106 typedef struct _DimensionData {
115 struct _ClutterTableLayoutPrivate
117 ClutterContainer *container;
133 struct _ClutterTableChild
135 ClutterLayoutMeta parent_instance;
143 ClutterTableAlignment x_align;
144 ClutterTableAlignment y_align;
159 PROP_CHILD_COLUMN_SPAN,
177 GType clutter_table_child_get_type (void);
179 G_DEFINE_TYPE (ClutterTableChild,
181 CLUTTER_TYPE_LAYOUT_META);
183 G_DEFINE_TYPE (ClutterTableLayout,
184 clutter_table_layout,
185 CLUTTER_TYPE_LAYOUT_MANAGER);
192 table_child_set_position (ClutterTableChild *self,
196 gboolean row_changed = FALSE, col_changed = FALSE;
198 if (self->col != col)
205 if (self->row != row)
212 if (row_changed || col_changed)
214 ClutterLayoutManager *layout;
216 layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
217 clutter_layout_manager_layout_changed (layout);
219 g_object_freeze_notify (G_OBJECT (self));
222 g_object_notify (G_OBJECT (self), "row");
225 g_object_notify (G_OBJECT (self), "column");
227 g_object_thaw_notify (G_OBJECT (self));
232 table_child_set_span (ClutterTableChild *self,
236 gboolean row_changed = FALSE, col_changed = FALSE;
238 if (self->col_span != col_span)
240 self->col_span = col_span;
245 if (self->row_span != row_span)
247 self->row_span = row_span;
252 if (row_changed || col_changed)
254 ClutterLayoutManager *layout;
256 layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
257 clutter_layout_manager_layout_changed (layout);
260 g_object_notify (G_OBJECT (self), "row-span");
263 g_object_notify (G_OBJECT (self), "column-span");
268 table_child_set_align (ClutterTableChild *self,
269 ClutterTableAlignment x_align,
270 ClutterTableAlignment y_align)
272 gboolean x_changed = FALSE, y_changed = FALSE;
274 if (self->x_align != x_align)
276 self->x_align = x_align;
281 if (self->y_align != y_align)
283 self->y_align = y_align;
288 if (x_changed || y_changed)
290 ClutterLayoutManager *layout;
292 layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
293 clutter_layout_manager_layout_changed (layout);
295 g_object_freeze_notify (G_OBJECT (self));
298 g_object_notify (G_OBJECT (self), "x-align");
301 g_object_notify (G_OBJECT (self), "y-align");
303 g_object_thaw_notify (G_OBJECT (self));
308 table_child_set_fill (ClutterTableChild *self,
312 gboolean x_changed = FALSE, y_changed = FALSE;
317 if (self->x_fill != x_fill)
319 self->x_fill = x_fill;
324 if (self->y_fill != y_fill)
326 self->y_fill = y_fill;
331 if (x_changed || y_changed)
333 ClutterLayoutManager *layout;
335 layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
336 clutter_layout_manager_layout_changed (layout);
338 g_object_freeze_notify (G_OBJECT (self));
341 g_object_notify (G_OBJECT (self), "x-fill");
344 g_object_notify (G_OBJECT (self), "y-fill");
346 g_object_thaw_notify (G_OBJECT (self));
351 table_child_set_expand (ClutterTableChild *self,
355 gboolean x_changed = FALSE, y_changed = FALSE;
357 x_expand = !!x_expand;
358 y_expand = !!y_expand;
360 if (self->x_expand != x_expand)
362 self->x_expand = x_expand;
367 if (self->y_expand != y_expand)
369 self->y_expand = y_expand;
374 if (x_changed || y_changed)
376 ClutterLayoutManager *layout;
378 layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
379 clutter_layout_manager_layout_changed (layout);
381 g_object_freeze_notify (G_OBJECT (self));
384 g_object_notify (G_OBJECT (self), "x-expand");
387 g_object_notify (G_OBJECT (self), "y-expand");
389 g_object_thaw_notify (G_OBJECT (self));
394 clutter_table_child_set_property (GObject *gobject,
399 ClutterTableChild *self = CLUTTER_TABLE_CHILD (gobject);
403 case PROP_CHILD_COLUMN:
404 table_child_set_position (self,
405 g_value_get_int (value),
410 table_child_set_position (self,
412 g_value_get_int (value));
415 case PROP_CHILD_COLUMN_SPAN:
416 table_child_set_span (self,
417 g_value_get_int (value),
421 case PROP_CHILD_ROW_SPAN:
422 table_child_set_span (self,
424 g_value_get_int (value));
427 case PROP_CHILD_X_ALIGN:
428 table_child_set_align (self,
429 g_value_get_enum (value),
433 case PROP_CHILD_Y_ALIGN:
434 table_child_set_align (self,
436 g_value_get_enum (value));
439 case PROP_CHILD_X_FILL:
440 table_child_set_fill (self,
441 g_value_get_boolean (value),
445 case PROP_CHILD_Y_FILL:
446 table_child_set_fill (self,
448 g_value_get_boolean (value));
451 case PROP_CHILD_X_EXPAND:
452 table_child_set_expand (self,
453 g_value_get_boolean (value),
457 case PROP_CHILD_Y_EXPAND:
458 table_child_set_expand (self,
460 g_value_get_boolean (value));
464 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
470 clutter_table_child_get_property (GObject *gobject,
475 ClutterTableChild *self = CLUTTER_TABLE_CHILD (gobject);
480 g_value_set_int (value, self->row);
483 case PROP_CHILD_COLUMN:
484 g_value_set_int (value, self->col);
487 case PROP_CHILD_ROW_SPAN:
488 g_value_set_int (value, self->row_span);
491 case PROP_CHILD_COLUMN_SPAN:
492 g_value_set_int (value, self->col_span);
495 case PROP_CHILD_X_ALIGN:
496 g_value_set_enum (value, self->x_align);
499 case PROP_CHILD_Y_ALIGN:
500 g_value_set_enum (value, self->y_align);
503 case PROP_CHILD_X_FILL:
504 g_value_set_boolean (value, self->x_fill);
507 case PROP_CHILD_Y_FILL:
508 g_value_set_boolean (value, self->y_fill);
511 case PROP_CHILD_X_EXPAND:
512 g_value_set_boolean (value, self->x_expand);
515 case PROP_CHILD_Y_EXPAND:
516 g_value_set_boolean (value, self->y_expand);
520 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
526 clutter_table_child_class_init (ClutterTableChildClass *klass)
528 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
531 gobject_class->set_property = clutter_table_child_set_property;
532 gobject_class->get_property = clutter_table_child_get_property;
534 pspec = g_param_spec_int ("column",
536 P_("The column the widget resides in"),
539 CLUTTER_PARAM_READWRITE);
540 g_object_class_install_property (gobject_class, PROP_CHILD_COLUMN, pspec);
542 pspec = g_param_spec_int ("row",
544 P_("The row the widget resides in"),
547 CLUTTER_PARAM_READWRITE);
548 g_object_class_install_property (gobject_class, PROP_CHILD_ROW, pspec);
550 pspec = g_param_spec_int ("column-span",
552 P_("The number of columns the widget should span"),
555 CLUTTER_PARAM_READWRITE);
556 g_object_class_install_property (gobject_class, PROP_CHILD_COLUMN_SPAN, pspec);
558 pspec = g_param_spec_int ("row-span",
560 P_("The number of rows the widget should span"),
563 CLUTTER_PARAM_READWRITE);
564 g_object_class_install_property (gobject_class, PROP_CHILD_ROW_SPAN, pspec);
566 pspec = g_param_spec_boolean ("x-expand",
567 P_("Horizontal Expand"),
568 P_("Allocate extra space for the child in horizontal axis"),
570 CLUTTER_PARAM_READWRITE);
571 g_object_class_install_property (gobject_class, PROP_CHILD_X_EXPAND, pspec);
573 pspec = g_param_spec_boolean ("y-expand",
574 P_("Vertical Expand"),
575 P_("Allocate extra space for the child in vertical axis"),
577 CLUTTER_PARAM_READWRITE);
578 g_object_class_install_property (gobject_class, PROP_CHILD_Y_EXPAND, pspec);
580 pspec = g_param_spec_boolean ("x-fill",
581 P_("Horizontal Fill"),
582 P_("Whether the child should receive priority when the container is allocating spare space on the horizontal axis"),
584 CLUTTER_PARAM_READWRITE);
585 g_object_class_install_property (gobject_class, PROP_CHILD_X_FILL, pspec);
587 pspec = g_param_spec_boolean ("y-fill",
589 P_("Whether the child should receive priority when the container is allocating spare space on the vertical axis"),
591 CLUTTER_PARAM_READWRITE);
592 g_object_class_install_property (gobject_class, PROP_CHILD_Y_FILL, pspec);
595 * ClutterTableLayout:x-align:
597 * The horizontal alignment of the actor within the cell
601 pspec = g_param_spec_enum ("x-align",
602 P_("Horizontal Alignment"),
603 P_("Horizontal alignment of the actor within the cell"),
604 CLUTTER_TYPE_TABLE_ALIGNMENT,
605 CLUTTER_TABLE_ALIGNMENT_CENTER,
606 CLUTTER_PARAM_READWRITE);
607 g_object_class_install_property (gobject_class, PROP_CHILD_X_ALIGN, pspec);
610 * ClutterTableLayout:y-align:
612 * The vertical alignment of the actor within the cell
616 pspec = g_param_spec_enum ("y-align",
617 P_("Vertical Alignment"),
618 P_("Vertical alignment of the actor within the cell"),
619 CLUTTER_TYPE_TABLE_ALIGNMENT,
620 CLUTTER_TABLE_ALIGNMENT_CENTER,
621 CLUTTER_PARAM_READWRITE);
622 g_object_class_install_property (gobject_class, PROP_CHILD_Y_ALIGN, pspec);
626 clutter_table_child_init (ClutterTableChild *self)
631 self->x_align = CLUTTER_TABLE_ALIGNMENT_CENTER;
632 self->y_align = CLUTTER_TABLE_ALIGNMENT_CENTER;
634 self->x_expand = TRUE;
635 self->y_expand = TRUE;
642 clutter_table_layout_get_child_meta_type (ClutterLayoutManager *manager)
644 return CLUTTER_TYPE_TABLE_CHILD;
648 clutter_table_layout_set_container (ClutterLayoutManager *layout,
649 ClutterContainer *container)
651 ClutterTableLayoutPrivate *priv = CLUTTER_TABLE_LAYOUT (layout)->priv;
653 priv->container = container;
658 update_row_col (ClutterTableLayout *layout,
659 ClutterContainer *container)
661 ClutterTableLayoutPrivate *priv = layout->priv;
662 ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (layout);
663 ClutterActor *actor, *child;
668 if (container == NULL)
671 actor = CLUTTER_ACTOR (container);
672 for (child = clutter_actor_get_first_child (actor);
674 child = clutter_actor_get_next_sibling (child))
676 ClutterTableChild *meta;
679 CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager,
683 n_cols = MAX (n_cols, meta->col + meta->col_span);
684 n_rows = MAX (n_rows, meta->row + meta->row_span);
688 priv->n_cols = n_cols;
689 priv->n_rows = n_rows;
694 calculate_col_widths (ClutterTableLayout *self,
695 ClutterContainer *container,
698 ClutterTableLayoutPrivate *priv = self->priv;
699 ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (self);
700 ClutterActor *actor, *child;
702 DimensionData *columns;
703 ClutterOrientation orientation = CLUTTER_ORIENTATION_HORIZONTAL;
705 update_row_col (self, container);
706 g_array_set_size (priv->columns, 0);
707 g_array_set_size (priv->columns, priv->n_cols);
708 columns = (DimensionData *) (void *) priv->columns->data;
710 /* reset the visibility of all columns */
711 priv->visible_cols = 0;
712 for (i = 0; i < priv->n_cols; i++)
714 columns[i].expand = FALSE;
715 columns[i].visible = FALSE;
718 actor = CLUTTER_ACTOR (container);
720 /* STAGE ONE: calculate column widths for non-spanned children */
721 for (child = clutter_actor_get_first_child (actor);
723 child = clutter_actor_get_next_sibling (child))
725 ClutterTableChild *meta;
727 gfloat c_min, c_pref;
729 if (!CLUTTER_ACTOR_IS_VISIBLE (child))
733 CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager,
737 if (meta->col_span > 1)
740 col = &columns[meta->col];
745 priv->visible_cols += 1;
748 clutter_actor_get_preferred_width (child, -1, &c_min, &c_pref);
750 col->min_size = MAX (col->min_size, c_min);
751 col->pref_size = MAX (col->pref_size, c_pref);
755 col->expand = clutter_actor_needs_expand (child, orientation) ||
760 /* STAGE TWO: take spanning children into account */
761 for (child = clutter_actor_get_first_child (actor);
763 child = clutter_actor_get_next_sibling (child))
765 ClutterTableChild *meta;
766 gfloat c_min, c_pref;
767 gfloat min_width, pref_width;
768 gint start_col, end_col;
771 if (!CLUTTER_ACTOR_IS_VISIBLE (child))
775 CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager,
779 if (meta->col_span < 2)
782 start_col = meta->col;
783 end_col = meta->col + meta->col_span - 1;
785 clutter_actor_get_preferred_width (child, -1, &c_min, &c_pref);
787 /* check there is enough room for this actor */
791 for (i = start_col; i <= end_col; i++)
793 min_width += columns[i].min_size;
794 pref_width += columns[i].pref_size;
796 if (columns[i].expand)
799 if (!columns[i].visible)
801 columns[i].visible = TRUE;
802 priv->visible_cols += 1;
805 if (!columns[i].expand)
807 columns[i].expand = clutter_actor_needs_expand (child,
812 min_width += priv->col_spacing * (meta->col_span - 1);
813 pref_width += priv->col_spacing * (meta->col_span - 1);
815 /* see calculate_row_heights() for comments */
817 if (c_min > min_width)
821 /* we can start from preferred width and decrease */
822 if (pref_width > c_min)
824 for (i = start_col; i <= end_col; i++)
825 columns[i].final_size = columns[i].pref_size;
827 while (pref_width > c_min)
829 for (i = start_col; i <= end_col; i++)
831 if (columns[i].final_size > columns[i].min_size)
833 columns[i].final_size--;
839 for (i = start_col; i <= end_col; i++)
840 columns[i].min_size = columns[i].final_size;
845 /* we can expand from preferred size */
848 expand_by = c_pref - pref_width;
850 for (i = start_col; i <= end_col; i++)
854 if (columns[i].expand)
855 columns[i].min_size = columns[i].pref_size
856 + expand_by / n_expand;
859 columns[i].min_size = columns[i].pref_size
860 + expand_by / meta->col_span;
866 /* calculate final widths */
869 gfloat min_width, pref_width;
876 for (i = 0; i < self->priv->n_cols; i++)
878 pref_width += columns[i].pref_size;
879 min_width += columns[i].min_size;
880 if (columns[i].expand)
884 pref_width += priv->col_spacing * (priv->n_cols - 1);
885 min_width += priv->col_spacing * (priv->n_cols - 1);
887 if (for_width <= min_width)
889 /* erk, we can't shrink this! */
890 for (i = 0; i < priv->n_cols; i++)
891 columns[i].final_size = columns[i].min_size;
896 if (for_width == pref_width)
899 for (i = 0; i < self->priv->n_cols; i++)
900 columns[i].final_size = columns[i].pref_size;
905 /* for_width is between min_width and pref_width */
906 if (for_width < pref_width && for_width > min_width)
910 /* shrink columns until they reach min_width */
912 /* start with all columns at preferred size */
913 for (i = 0; i < self->priv->n_cols; i++)
914 columns[i].final_size = columns[i].pref_size;
918 while (width > for_width)
920 for (i = 0; i < self->priv->n_cols; i++)
922 if (columns[i].final_size > columns[i].min_size)
924 columns[i].final_size--;
934 if (for_width > pref_width)
936 gfloat extra_width = for_width - pref_width;
940 remaining = (gint) extra_width % n_expand;
942 remaining = (gint) extra_width % priv->n_cols;
944 for (i = 0; i < self->priv->n_cols; i++)
946 if (columns[i].expand)
948 columns[i].final_size = columns[i].pref_size
949 + (extra_width / n_expand);
952 columns[i].final_size = columns[i].pref_size;
955 /* distribute the remainder among children */
959 columns[i].final_size++;
969 calculate_row_heights (ClutterTableLayout *self,
970 ClutterContainer *container,
973 ClutterTableLayoutPrivate *priv = self->priv;
974 ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (self);
975 ClutterActor *actor, *child;
977 DimensionData *rows, *columns;
978 ClutterOrientation orientation = CLUTTER_ORIENTATION_VERTICAL;
980 update_row_col (self, container);
981 g_array_set_size (priv->rows, 0);
982 g_array_set_size (priv->rows, self->priv->n_rows);
984 rows = (DimensionData *) (void *) priv->rows->data;
985 columns = (DimensionData *) (void *) priv->columns->data;
987 /* reset the visibility of all rows */
988 priv->visible_rows = 0;
989 for (i = 0; i < priv->n_rows; i++)
991 rows[i].expand = FALSE;
992 rows[i].visible = FALSE;
995 actor = CLUTTER_ACTOR (container);
997 /* STAGE ONE: calculate row heights for non-spanned children */
998 for (child = clutter_actor_get_first_child (actor);
1000 child = clutter_actor_get_next_sibling (child))
1002 ClutterTableChild *meta;
1004 gfloat c_min, c_pref;
1006 if (!CLUTTER_ACTOR_IS_VISIBLE (child))
1010 CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager,
1014 if (meta->row_span > 1)
1017 row = &rows[meta->row];
1021 row->visible = TRUE;
1022 priv->visible_rows += 1;
1025 clutter_actor_get_preferred_height (child, columns[meta->col].final_size,
1028 row->min_size = MAX (row->min_size, c_min);
1029 row->pref_size = MAX (row->pref_size, c_pref);
1033 row->expand = clutter_actor_needs_expand (child, orientation) ||
1038 /* STAGE TWO: take spanning children into account */
1039 for (child = clutter_actor_get_first_child (actor);
1041 child = clutter_actor_get_next_sibling (child))
1043 ClutterTableChild *meta;
1044 gfloat c_min, c_pref;
1045 gfloat min_height, pref_height;
1046 gint start_row, end_row;
1049 if (!CLUTTER_ACTOR_IS_VISIBLE (child))
1053 CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager,
1057 if (meta->row_span < 2)
1060 start_row = meta->row;
1061 end_row = meta->row + meta->row_span - 1;
1063 clutter_actor_get_preferred_height (child, columns[meta->col].final_size,
1067 /* check there is enough room for this actor */
1071 for (i = start_row; i <= end_row; i++)
1073 min_height += rows[i].min_size;
1074 pref_height += rows[i].pref_size;
1079 if (!rows[i].visible)
1081 rows[i].visible = TRUE;
1082 priv->visible_rows += 1;
1085 if (!rows[i].expand)
1087 rows[i].expand = clutter_actor_needs_expand (child,
1093 min_height += priv->row_spacing * (meta->row_span - 1);
1094 pref_height += priv->row_spacing * (meta->row_span - 1);
1096 /* 1) If the minimum height of the rows spanned is less than the
1097 * minimum height of the child that is spanning them, then we
1098 * must increase the minimum height of the rows spanned.
1100 * 2) If the preferred height of the spanned rows is more than
1101 * the minimum height of the spanning child, then we can start
1102 * at this size and decrease each row evenly.
1104 * 3) If the preferred height of the rows is more than the minimum
1105 * height of the spanned child, then we can start at the preferred
1106 * height and expand.
1110 if (c_min > min_height)
1114 /* we can start from preferred height and decrease */
1115 if (pref_height > c_min)
1117 for (i = start_row; i <= end_row; i++)
1118 rows[i].final_size = rows[i].pref_size;
1120 while (pref_height > c_min)
1122 for (i = start_row; i <= end_row; i++)
1124 if (rows[i].final_size > rows[i].min_size)
1126 rows[i].final_size--;
1132 for (i = start_row; i <= end_row; i++)
1133 rows[i].min_size = rows[i].final_size;
1138 /* we can expand from preferred size */
1139 gfloat expand_by = c_pref - pref_height;
1141 for (i = start_row; i <= end_row; i++)
1146 rows[i].min_size = rows[i].pref_size
1147 + expand_by / n_expand;
1150 rows[i].min_size = rows[i].pref_size
1151 + expand_by / meta->row_span;
1157 /* calculate final heights */
1158 if (for_height >= 0)
1160 gfloat min_height, pref_height;
1167 for (i = 0; i < self->priv->n_rows; i++)
1169 pref_height += rows[i].pref_size;
1170 min_height += rows[i].min_size;
1175 pref_height += priv->row_spacing * (priv->n_rows - 1);
1176 min_height += priv->row_spacing * (priv->n_rows - 1);
1178 if (for_height <= min_height)
1180 /* erk, we can't shrink this! */
1181 for (i = 0; i < self->priv->n_rows; i++)
1182 rows[i].final_size = rows[i].min_size;
1187 if (for_height == pref_height)
1190 for (i = 0; i < self->priv->n_rows; i++)
1191 rows[i].final_size = rows[i].pref_size;
1196 /* for_height is between min_height and pref_height */
1197 if (for_height < pref_height && for_height > min_height)
1201 /* shrink rows until they reach min_height */
1203 /* start with all rows at preferred size */
1204 for (i = 0; i < self->priv->n_rows; i++)
1205 rows[i].final_size = rows[i].pref_size;
1207 height = pref_height;
1209 while (height > for_height)
1211 for (i = 0; i < priv->n_rows; i++)
1213 if (rows[i].final_size > rows[i].min_size)
1215 rows[i].final_size--;
1225 if (for_height > pref_height)
1227 gfloat extra_height = for_height - pref_height;
1231 remaining = (gint) extra_height % n_expand;
1233 remaining = (gint) extra_height % self->priv->n_rows;
1235 for (i = 0; i < self->priv->n_rows; i++)
1239 rows[i].final_size = rows[i].pref_size
1240 + (extra_height / n_expand);
1243 rows[i].final_size = rows[i].pref_size;
1246 /* distribute the remainder among children */
1250 rows[i].final_size++;
1260 calculate_table_dimensions (ClutterTableLayout *self,
1261 ClutterContainer *container,
1265 calculate_col_widths (self, container, for_width);
1266 calculate_row_heights (self, container, for_height);
1270 clutter_table_layout_get_preferred_width (ClutterLayoutManager *layout,
1271 ClutterContainer *container,
1273 gfloat *min_width_p,
1274 gfloat *natural_width_p)
1276 ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout);
1277 ClutterTableLayoutPrivate *priv = self->priv;
1278 gfloat total_min_width, total_pref_width;
1279 DimensionData *columns;
1282 update_row_col (self, container);
1283 if (priv->n_cols < 1)
1286 *natural_width_p = 0;
1290 calculate_table_dimensions (self, container, -1, for_height);
1291 columns = (DimensionData *) (void *) priv->columns->data;
1293 total_min_width = (priv->visible_cols - 1) * (float) priv->col_spacing;
1294 total_pref_width = total_min_width;
1296 for (i = 0; i < priv->n_cols; i++)
1298 total_min_width += columns[i].min_size;
1299 total_pref_width += columns[i].pref_size;
1303 *min_width_p = total_min_width;
1305 if (natural_width_p)
1306 *natural_width_p = total_pref_width;
1310 clutter_table_layout_get_preferred_height (ClutterLayoutManager *layout,
1311 ClutterContainer *container,
1313 gfloat *min_height_p,
1314 gfloat *natural_height_p)
1316 ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout);
1317 ClutterTableLayoutPrivate *priv = self->priv;
1318 gfloat total_min_height, total_pref_height;
1319 DimensionData *rows;
1322 update_row_col (self, container);
1323 if (priv->n_rows < 1)
1326 *natural_height_p = 0;
1330 calculate_table_dimensions (self, container, for_width, -1);
1331 rows = (DimensionData *) (void *) priv->rows->data;
1333 total_min_height = (priv->visible_rows - 1) * (float) priv->row_spacing;
1334 total_pref_height = total_min_height;
1336 for (i = 0; i < self->priv->n_rows; i++)
1338 total_min_height += rows[i].min_size;
1339 total_pref_height += rows[i].pref_size;
1343 *min_height_p = total_min_height;
1345 if (natural_height_p)
1346 *natural_height_p = total_pref_height;
1350 get_table_alignment_factor (ClutterTableAlignment alignment)
1354 case CLUTTER_TABLE_ALIGNMENT_START:
1357 case CLUTTER_TABLE_ALIGNMENT_CENTER:
1360 case CLUTTER_TABLE_ALIGNMENT_END:
1368 clutter_table_layout_allocate (ClutterLayoutManager *layout,
1369 ClutterContainer *container,
1370 const ClutterActorBox *box,
1371 ClutterAllocationFlags flags)
1373 ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout);
1374 ClutterTableLayoutPrivate *priv = self->priv;
1375 ClutterActor *actor, *child;
1376 gint row_spacing, col_spacing;
1378 DimensionData *rows, *columns;
1379 gboolean use_animations;
1380 ClutterAnimationMode easing_mode;
1381 guint easing_duration, easing_delay;
1384 update_row_col (self, container);
1385 if (priv->n_cols < 1 || priv->n_rows < 1)
1388 actor = CLUTTER_ACTOR (container);
1390 if (clutter_actor_get_n_children (actor) == 0)
1393 col_spacing = (priv->col_spacing);
1394 row_spacing = (priv->row_spacing);
1396 calculate_table_dimensions (self, container,
1400 rows = (DimensionData *) (void *) priv->rows->data;
1401 columns = (DimensionData *) (void *) priv->columns->data;
1403 use_animations = clutter_layout_manager_get_easing_state (layout,
1408 for (child = clutter_actor_get_first_child (actor);
1410 child = clutter_actor_get_next_sibling (child))
1412 gint row, col, row_span, col_span;
1413 gint col_width, row_height;
1414 ClutterTableChild *meta;
1415 ClutterActorBox childbox;
1416 gint child_x, child_y;
1417 gdouble x_align, y_align;
1418 gboolean x_fill, y_fill;
1420 if (!CLUTTER_ACTOR_IS_VISIBLE (child))
1424 CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (layout,
1428 /* get child properties */
1431 row_span = meta->row_span;
1432 col_span = meta->col_span;
1433 x_align = get_table_alignment_factor (meta->x_align);
1434 y_align = get_table_alignment_factor (meta->y_align);
1435 x_fill = meta->x_fill;
1436 y_fill = meta->y_fill;
1438 /* initialise the width and height */
1439 col_width = columns[col].final_size;
1440 row_height = rows[row].final_size;
1442 /* Add the widths of the spanned columns:
1444 * First check that we have a non-zero span. Then we loop over each of
1445 * the columns that we're spanning but we stop short if we go past the
1446 * number of columns in the table. This is necessary to avoid accessing
1447 * uninitialised memory. We add the spacing in here too since we only
1448 * want to add as much spacing as times we successfully span.
1450 if (col + col_span > priv->n_cols)
1451 g_warning (G_STRLOC ": column-span exceeds number of columns");
1452 if (row + row_span > priv->n_rows)
1453 g_warning (G_STRLOC ": row-span exceeds number of rows");
1457 for (i = col + 1; i < col + col_span && i < priv->n_cols; i++)
1459 col_width += columns[i].final_size;
1460 col_width += col_spacing;
1464 /* add the height of the spanned rows */
1467 for (i = row + 1; i < row + row_span && i < priv->n_rows; i++)
1469 row_height += rows[i].final_size;
1470 row_height += row_spacing;
1474 /* calculate child x */
1475 child_x = clutter_actor_box_get_x (box);
1476 for (i = 0; i < col; i++)
1478 if (columns[i].visible)
1480 child_x += columns[i].final_size;
1481 child_x += col_spacing;
1485 /* calculate child y */
1486 child_y = clutter_actor_box_get_y (box);
1487 for (i = 0; i < row; i++)
1489 if (rows[i].visible)
1491 child_y += rows[i].final_size;
1492 child_y += row_spacing;
1496 /* set up childbox */
1497 childbox.x1 = (float) child_x;
1498 childbox.x2 = (float) MAX (0, child_x + col_width);
1500 childbox.y1 = (float) child_y;
1501 childbox.y2 = (float) MAX (0, child_y + row_height);
1505 clutter_actor_save_easing_state (child);
1506 clutter_actor_set_easing_mode (child, easing_mode);
1507 clutter_actor_set_easing_duration (child, easing_duration);
1508 clutter_actor_set_easing_delay (child, easing_delay);
1511 if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL) ||
1512 clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL))
1513 clutter_actor_allocate (child, &childbox, flags);
1515 clutter_actor_allocate_align_fill (child, &childbox,
1521 clutter_actor_restore_easing_state (child);
1526 clutter_table_layout_set_property (GObject *gobject,
1528 const GValue *value,
1531 ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (gobject);
1535 case PROP_COLUMN_SPACING:
1536 clutter_table_layout_set_column_spacing (self, g_value_get_uint (value));
1539 case PROP_ROW_SPACING:
1540 clutter_table_layout_set_row_spacing (self, g_value_get_uint (value));
1544 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
1550 clutter_table_layout_get_property (GObject *gobject,
1555 ClutterTableLayoutPrivate *priv = CLUTTER_TABLE_LAYOUT (gobject)->priv;
1559 case PROP_ROW_SPACING:
1560 g_value_set_uint (value, priv->row_spacing);
1563 case PROP_COLUMN_SPACING:
1564 g_value_set_uint (value, priv->col_spacing);
1568 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
1574 clutter_table_layout_finalize (GObject *gobject)
1576 ClutterTableLayoutPrivate *priv = CLUTTER_TABLE_LAYOUT (gobject)->priv;
1578 g_array_free (priv->columns, TRUE);
1579 g_array_free (priv->rows, TRUE);
1581 G_OBJECT_CLASS (clutter_table_layout_parent_class)->finalize (gobject);
1585 clutter_table_layout_class_init (ClutterTableLayoutClass *klass)
1587 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1588 ClutterLayoutManagerClass *layout_class;
1591 layout_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass);
1593 gobject_class->set_property = clutter_table_layout_set_property;
1594 gobject_class->get_property = clutter_table_layout_get_property;
1595 gobject_class->finalize = clutter_table_layout_finalize;
1597 layout_class->get_preferred_width =
1598 clutter_table_layout_get_preferred_width;
1599 layout_class->get_preferred_height =
1600 clutter_table_layout_get_preferred_height;
1601 layout_class->allocate = clutter_table_layout_allocate;
1602 layout_class->set_container = clutter_table_layout_set_container;
1603 layout_class->get_child_meta_type =
1604 clutter_table_layout_get_child_meta_type;
1606 g_type_class_add_private (klass, sizeof (ClutterTableLayoutPrivate));
1609 * ClutterTableLayout:column-spacing:
1611 * The spacing between columns of the #ClutterTableLayout, in pixels
1615 pspec = g_param_spec_uint ("column-spacing",
1616 P_("Column Spacing"),
1617 P_("Spacing between columns"),
1619 CLUTTER_PARAM_READWRITE);
1620 g_object_class_install_property (gobject_class, PROP_COLUMN_SPACING, pspec);
1623 * ClutterTableLayout:row-spacing:
1625 * The spacing between rows of the #ClutterTableLayout, in pixels
1629 pspec = g_param_spec_uint ("row-spacing",
1631 P_("Spacing between rows"),
1633 CLUTTER_PARAM_READWRITE);
1634 g_object_class_install_property (gobject_class, PROP_ROW_SPACING, pspec);
1636 /* a leftover to be compatible to the previous implementation */
1637 pspec = g_param_spec_uint ("easing-duration",
1638 P_("Easing Duration"),
1639 P_("The duration of the animations"),
1641 CLUTTER_PARAM_READWRITE);
1642 g_object_class_install_property (gobject_class, PROP_EASING_DURATION, pspec);
1646 clutter_table_layout_init (ClutterTableLayout *layout)
1648 ClutterTableLayoutPrivate *priv;
1650 layout->priv = priv = CLUTTER_TABLE_LAYOUT_GET_PRIVATE (layout);
1652 priv->row_spacing = 0;
1653 priv->col_spacing = 0;
1655 priv->columns = g_array_new (FALSE, TRUE, sizeof (DimensionData));
1656 priv->rows = g_array_new (FALSE, TRUE, sizeof (DimensionData));
1660 * clutter_table_layout_new:
1662 * Creates a new #ClutterTableLayout layout manager
1664 * Return value: the newly created #ClutterTableLayout
1668 ClutterLayoutManager *
1669 clutter_table_layout_new (void)
1671 return g_object_new (CLUTTER_TYPE_TABLE_LAYOUT, NULL);
1675 * clutter_table_layout_set_column_spacing:
1676 * @layout: a #ClutterTableLayout
1677 * @spacing: the spacing between columns of the layout, in pixels
1679 * Sets the spacing between columns of @layout
1684 clutter_table_layout_set_column_spacing (ClutterTableLayout *layout,
1687 ClutterTableLayoutPrivate *priv;
1689 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
1691 priv = layout->priv;
1693 if (priv->col_spacing != spacing)
1695 ClutterLayoutManager *manager;
1697 priv->col_spacing = spacing;
1699 manager = CLUTTER_LAYOUT_MANAGER (layout);
1700 clutter_layout_manager_layout_changed (manager);
1702 g_object_notify (G_OBJECT (layout), "column-spacing");
1707 * clutter_table_layout_get_column_spacing:
1708 * @layout: a #ClutterTableLayout
1710 * Retrieves the spacing set using clutter_table_layout_set_column_spacing()
1712 * Return value: the spacing between columns of the #ClutterTableLayout
1717 clutter_table_layout_get_column_spacing (ClutterTableLayout *layout)
1719 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), 0);
1721 return layout->priv->col_spacing;
1725 * clutter_table_layout_set_row_spacing:
1726 * @layout: a #ClutterTableLayout
1727 * @spacing: the spacing between rows of the layout, in pixels
1729 * Sets the spacing between rows of @layout
1734 clutter_table_layout_set_row_spacing (ClutterTableLayout *layout,
1737 ClutterTableLayoutPrivate *priv;
1739 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
1741 priv = layout->priv;
1743 if (priv->row_spacing != spacing)
1745 ClutterLayoutManager *manager;
1747 priv->row_spacing = spacing;
1749 manager = CLUTTER_LAYOUT_MANAGER (layout);
1750 clutter_layout_manager_layout_changed (manager);
1752 g_object_notify (G_OBJECT (layout), "row-spacing");
1757 * clutter_table_layout_get_row_spacing:
1758 * @layout: a #ClutterTableLayout
1760 * Retrieves the spacing set using clutter_table_layout_set_row_spacing()
1762 * Return value: the spacing between rows of the #ClutterTableLayout
1767 clutter_table_layout_get_row_spacing (ClutterTableLayout *layout)
1769 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), 0);
1771 return layout->priv->row_spacing;
1775 * clutter_table_layout_pack:
1776 * @layout: a #ClutterTableLayout
1777 * @actor: a #ClutterActor
1778 * @column: the column the @actor should be put, or -1 to append
1779 * @row: the row the @actor should be put, or -1 to append
1781 * Packs @actor inside the #ClutterContainer associated to @layout
1782 * at the given row and column.
1787 clutter_table_layout_pack (ClutterTableLayout *layout,
1788 ClutterActor *actor,
1792 ClutterTableLayoutPrivate *priv;
1793 ClutterLayoutManager *manager;
1794 ClutterLayoutMeta *meta;
1796 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
1797 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1799 priv = layout->priv;
1801 if (priv->container == NULL)
1803 g_warning ("The layout of type '%s' must be associated to "
1804 "a ClutterContainer before adding children",
1805 G_OBJECT_TYPE_NAME (layout));
1809 update_row_col (CLUTTER_TABLE_LAYOUT (layout), priv->container);
1811 clutter_container_add_actor (priv->container, actor);
1813 manager = CLUTTER_LAYOUT_MANAGER (layout);
1814 meta = clutter_layout_manager_get_child_meta (manager,
1817 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
1820 row = priv->n_rows + 1;
1823 column = priv->n_cols + 1;
1825 table_child_set_position (CLUTTER_TABLE_CHILD (meta), column, row);
1829 * clutter_table_layout_set_span:
1830 * @layout: a #ClutterTableLayout
1831 * @actor: a #ClutterActor child of @layout
1832 * @column_span: Column span for @actor
1833 * @row_span: Row span for @actor
1835 * Sets the row and column span for @actor
1841 clutter_table_layout_set_span (ClutterTableLayout *layout,
1842 ClutterActor *actor,
1846 ClutterTableLayoutPrivate *priv;
1847 ClutterLayoutManager *manager;
1848 ClutterLayoutMeta *meta;
1850 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
1851 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1853 priv = layout->priv;
1855 if (priv->container == NULL)
1857 g_warning ("The layout of type '%s' must be associated to "
1858 "a ClutterContainer before querying layout "
1860 G_OBJECT_TYPE_NAME (layout));
1864 manager = CLUTTER_LAYOUT_MANAGER (layout);
1865 meta = clutter_layout_manager_get_child_meta (manager,
1870 g_warning ("No layout meta found for the child of type '%s' "
1871 "inside the layout manager of type '%s'",
1872 G_OBJECT_TYPE_NAME (actor),
1873 G_OBJECT_TYPE_NAME (manager));
1877 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
1879 table_child_set_span (CLUTTER_TABLE_CHILD (meta), column_span, row_span);
1883 * clutter_table_layout_get_span:
1884 * @layout: a #ClutterTableLayout
1885 * @actor: a #ClutterActor child of @layout
1886 * @column_span: (out): return location for the col span
1887 * @row_span: (out): return location for the row span
1889 * Retrieves the row and column span for @actor as set using
1890 * clutter_table_layout_pack() or clutter_table_layout_set_span()
1895 clutter_table_layout_get_span (ClutterTableLayout *layout,
1896 ClutterActor *actor,
1900 ClutterTableLayoutPrivate *priv;
1901 ClutterLayoutManager *manager;
1902 ClutterLayoutMeta *meta;
1904 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
1905 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1907 priv = layout->priv;
1909 if (priv->container == NULL)
1911 g_warning ("The layout of type '%s' must be associated to "
1912 "a ClutterContainer before querying layout "
1914 G_OBJECT_TYPE_NAME (layout));
1918 manager = CLUTTER_LAYOUT_MANAGER (layout);
1919 meta = clutter_layout_manager_get_child_meta (manager,
1924 g_warning ("No layout meta found for the child of type '%s' "
1925 "inside the layout manager of type '%s'",
1926 G_OBJECT_TYPE_NAME (actor),
1927 G_OBJECT_TYPE_NAME (manager));
1931 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
1934 *column_span = CLUTTER_TABLE_CHILD (meta)->col_span;
1937 *row_span = CLUTTER_TABLE_CHILD (meta)->row_span;
1941 * clutter_table_layout_set_alignment:
1942 * @layout: a #ClutterTableLayout
1943 * @actor: a #ClutterActor child of @layout
1944 * @x_align: Horizontal alignment policy for @actor
1945 * @y_align: Vertical alignment policy for @actor
1947 * Sets the horizontal and vertical alignment policies for @actor
1953 clutter_table_layout_set_alignment (ClutterTableLayout *layout,
1954 ClutterActor *actor,
1955 ClutterTableAlignment x_align,
1956 ClutterTableAlignment y_align)
1958 ClutterTableLayoutPrivate *priv;
1959 ClutterLayoutManager *manager;
1960 ClutterLayoutMeta *meta;
1962 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
1963 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1965 priv = layout->priv;
1967 if (priv->container == NULL)
1969 g_warning ("The layout of type '%s' must be associated to "
1970 "a ClutterContainer before querying layout "
1972 G_OBJECT_TYPE_NAME (layout));
1976 manager = CLUTTER_LAYOUT_MANAGER (layout);
1977 meta = clutter_layout_manager_get_child_meta (manager,
1982 g_warning ("No layout meta found for the child of type '%s' "
1983 "inside the layout manager of type '%s'",
1984 G_OBJECT_TYPE_NAME (actor),
1985 G_OBJECT_TYPE_NAME (manager));
1989 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
1991 table_child_set_align (CLUTTER_TABLE_CHILD (meta), x_align, y_align);
1995 * clutter_table_layout_get_alignment:
1996 * @layout: a #ClutterTableLayout
1997 * @actor: a #ClutterActor child of @layout
1998 * @x_align: (out): return location for the horizontal alignment policy
1999 * @y_align: (out): return location for the vertical alignment policy
2001 * Retrieves the horizontal and vertical alignment policies for @actor
2002 * as set using clutter_table_layout_pack() or
2003 * clutter_table_layout_set_alignment().
2008 clutter_table_layout_get_alignment (ClutterTableLayout *layout,
2009 ClutterActor *actor,
2010 ClutterTableAlignment *x_align,
2011 ClutterTableAlignment *y_align)
2013 ClutterTableLayoutPrivate *priv;
2014 ClutterLayoutManager *manager;
2015 ClutterLayoutMeta *meta;
2017 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2018 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
2020 priv = layout->priv;
2022 if (priv->container == NULL)
2024 g_warning ("The layout of type '%s' must be associated to "
2025 "a ClutterContainer before querying layout "
2027 G_OBJECT_TYPE_NAME (layout));
2031 manager = CLUTTER_LAYOUT_MANAGER (layout);
2032 meta = clutter_layout_manager_get_child_meta (manager,
2037 g_warning ("No layout meta found for the child of type '%s' "
2038 "inside the layout manager of type '%s'",
2039 G_OBJECT_TYPE_NAME (actor),
2040 G_OBJECT_TYPE_NAME (manager));
2044 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
2047 *x_align = CLUTTER_TABLE_CHILD (meta)->x_align;
2050 *y_align = CLUTTER_TABLE_CHILD (meta)->y_align;
2054 * clutter_table_layout_set_fill:
2055 * @layout: a #ClutterTableLayout
2056 * @actor: a #ClutterActor child of @layout
2057 * @x_fill: whether @actor should fill horizontally the allocated space
2058 * @y_fill: whether @actor should fill vertically the allocated space
2060 * Sets the horizontal and vertical fill policies for @actor
2066 clutter_table_layout_set_fill (ClutterTableLayout *layout,
2067 ClutterActor *actor,
2071 ClutterTableLayoutPrivate *priv;
2072 ClutterLayoutManager *manager;
2073 ClutterLayoutMeta *meta;
2075 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2076 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
2078 priv = layout->priv;
2080 if (priv->container == NULL)
2082 g_warning ("The layout of type '%s' must be associated to "
2083 "a ClutterContainer before querying layout "
2085 G_OBJECT_TYPE_NAME (layout));
2089 manager = CLUTTER_LAYOUT_MANAGER (layout);
2090 meta = clutter_layout_manager_get_child_meta (manager,
2095 g_warning ("No layout meta found for the child of type '%s' "
2096 "inside the layout manager of type '%s'",
2097 G_OBJECT_TYPE_NAME (actor),
2098 G_OBJECT_TYPE_NAME (manager));
2102 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
2104 table_child_set_fill (CLUTTER_TABLE_CHILD (meta), x_fill, y_fill);
2108 * clutter_table_layout_get_fill:
2109 * @layout: a #ClutterTableLayout
2110 * @actor: a #ClutterActor child of @layout
2111 * @x_fill: (out): return location for the horizontal fill policy
2112 * @y_fill: (out): return location for the vertical fill policy
2114 * Retrieves the horizontal and vertical fill policies for @actor
2115 * as set using clutter_table_layout_pack() or clutter_table_layout_set_fill()
2120 clutter_table_layout_get_fill (ClutterTableLayout *layout,
2121 ClutterActor *actor,
2125 ClutterTableLayoutPrivate *priv;
2126 ClutterLayoutManager *manager;
2127 ClutterLayoutMeta *meta;
2129 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2130 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
2132 priv = layout->priv;
2134 if (priv->container == NULL)
2136 g_warning ("The layout of type '%s' must be associated to "
2137 "a ClutterContainer before querying layout "
2139 G_OBJECT_TYPE_NAME (layout));
2143 manager = CLUTTER_LAYOUT_MANAGER (layout);
2144 meta = clutter_layout_manager_get_child_meta (manager,
2149 g_warning ("No layout meta found for the child of type '%s' "
2150 "inside the layout manager of type '%s'",
2151 G_OBJECT_TYPE_NAME (actor),
2152 G_OBJECT_TYPE_NAME (manager));
2156 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
2159 *x_fill = CLUTTER_TABLE_CHILD (meta)->x_fill;
2162 *y_fill = CLUTTER_TABLE_CHILD (meta)->y_fill;
2167 * clutter_table_layout_set_expand:
2168 * @layout: a #ClutterTableLayout
2169 * @actor: a #ClutterActor child of @layout
2170 * @x_expand: whether @actor should allocate extra space horizontally
2171 * @y_expand: whether @actor should allocate extra space vertically
2173 * Sets the horizontal and vertical expand policies for @actor
2179 clutter_table_layout_set_expand (ClutterTableLayout *layout,
2180 ClutterActor *actor,
2184 ClutterTableLayoutPrivate *priv;
2185 ClutterLayoutManager *manager;
2186 ClutterLayoutMeta *meta;
2188 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2189 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
2191 priv = layout->priv;
2193 if (priv->container == NULL)
2195 g_warning ("The layout of type '%s' must be associated to "
2196 "a ClutterContainer before querying layout "
2198 G_OBJECT_TYPE_NAME (layout));
2202 manager = CLUTTER_LAYOUT_MANAGER (layout);
2203 meta = clutter_layout_manager_get_child_meta (manager,
2208 g_warning ("No layout meta found for the child of type '%s' "
2209 "inside the layout manager of type '%s'",
2210 G_OBJECT_TYPE_NAME (actor),
2211 G_OBJECT_TYPE_NAME (manager));
2215 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
2217 table_child_set_expand (CLUTTER_TABLE_CHILD (meta), x_expand, y_expand);
2221 * clutter_table_layout_get_expand:
2222 * @layout: a #ClutterTableLayout
2223 * @actor: a #ClutterActor child of @layout
2224 * @x_expand: (out): return location for the horizontal expand policy
2225 * @y_expand: (out): return location for the vertical expand policy
2227 * Retrieves the horizontal and vertical expand policies for @actor
2228 * as set using clutter_table_layout_pack() or clutter_table_layout_set_expand()
2233 clutter_table_layout_get_expand (ClutterTableLayout *layout,
2234 ClutterActor *actor,
2238 ClutterTableLayoutPrivate *priv;
2239 ClutterLayoutManager *manager;
2240 ClutterLayoutMeta *meta;
2242 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2243 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
2245 priv = layout->priv;
2247 if (priv->container == NULL)
2249 g_warning ("The layout of type '%s' must be associated to "
2250 "a ClutterContainer before querying layout "
2252 G_OBJECT_TYPE_NAME (layout));
2256 manager = CLUTTER_LAYOUT_MANAGER (layout);
2257 meta = clutter_layout_manager_get_child_meta (manager,
2262 g_warning ("No layout meta found for the child of type '%s' "
2263 "inside the layout manager of type '%s'",
2264 G_OBJECT_TYPE_NAME (actor),
2265 G_OBJECT_TYPE_NAME (manager));
2269 g_assert (CLUTTER_IS_TABLE_CHILD (meta));
2272 *x_expand = CLUTTER_TABLE_CHILD (meta)->x_expand;
2275 *y_expand = CLUTTER_TABLE_CHILD (meta)->y_expand;
2279 * clutter_table_layout_set_use_animations:
2280 * @layout: a #ClutterTableLayout
2281 * @animate: %TRUE if the @layout should use animations
2283 * Sets whether @layout should animate changes in the layout properties
2285 * The duration of the animations is controlled by
2286 * clutter_table_layout_set_easing_duration(); the easing mode to be used
2287 * by the animations is controlled by clutter_table_layout_set_easing_mode()
2291 * Deprecated: 1.12: #ClutterTableLayout will honour the
2292 * #ClutterLayoutManager:use-animations property
2295 clutter_table_layout_set_use_animations (ClutterTableLayout *layout,
2298 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2300 clutter_layout_manager_set_use_animations (CLUTTER_LAYOUT_MANAGER (layout),
2305 * clutter_table_layout_get_use_animations:
2306 * @layout: a #ClutterTableLayout
2308 * Retrieves whether @layout should animate changes in the layout properties
2310 * Since clutter_table_layout_set_use_animations()
2312 * Return value: %TRUE if the animations should be used, %FALSE otherwise
2316 * Deprecated: 1.12: #ClutterTable will honour the
2317 * #ClutterLayoutManager:use-animations property
2320 clutter_table_layout_get_use_animations (ClutterTableLayout *layout)
2322 ClutterLayoutManager *manager;
2324 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), FALSE);
2326 manager = CLUTTER_LAYOUT_MANAGER (layout);
2328 return clutter_layout_manager_get_use_animations (manager);
2332 * clutter_table_layout_set_easing_mode:
2333 * @layout: a #ClutterTableLayout
2334 * @mode: an easing mode, either from #ClutterAnimationMode or a logical id
2335 * from clutter_alpha_register_func()
2337 * Sets the easing mode to be used by @layout when animating changes in layout
2340 * Use clutter_table_layout_set_use_animations() to enable and disable the
2345 * Deprecated: 1.12: #ClutterTableLayout will honour the
2346 * #ClutterLayoutManager:easing-mode property
2349 clutter_table_layout_set_easing_mode (ClutterTableLayout *layout,
2352 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2354 clutter_layout_manager_set_easing_mode (CLUTTER_LAYOUT_MANAGER (layout),
2359 * clutter_table_layout_get_easing_mode:
2360 * @layout: a #ClutterTableLayout
2362 * Retrieves the easing mode set using clutter_table_layout_set_easing_mode()
2364 * Return value: an easing mode
2368 * Deprecated: 1.12: #ClutterTableLayout will honour the
2369 * #ClutterLayoutManager:easing-mode property
2372 clutter_table_layout_get_easing_mode (ClutterTableLayout *layout)
2374 ClutterLayoutManager *manager;
2376 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout),
2377 CLUTTER_EASE_OUT_CUBIC);
2379 manager = CLUTTER_LAYOUT_MANAGER (layout);
2381 return clutter_layout_manager_get_easing_mode (manager);
2385 * clutter_table_layout_set_easing_duration:
2386 * @layout: a #ClutterTableLayout
2387 * @msecs: the duration of the animations, in milliseconds
2389 * Sets the duration of the animations used by @layout when animating changes
2390 * in the layout properties
2392 * Use clutter_table_layout_set_use_animations() to enable and disable the
2397 * Deprecated: 1.12: #ClutterTableLayout will honour the
2398 * #ClutterLayoutManager:easing-duration property
2401 clutter_table_layout_set_easing_duration (ClutterTableLayout *layout,
2404 g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout));
2406 clutter_layout_manager_set_easing_duration (CLUTTER_LAYOUT_MANAGER (layout),
2411 * clutter_table_layout_get_easing_duration:
2412 * @layout: a #ClutterTableLayout
2414 * Retrieves the duration set using clutter_table_layout_set_easing_duration()
2416 * Return value: the duration of the animations, in milliseconds
2423 clutter_table_layout_get_easing_duration (ClutterTableLayout *layout)
2425 ClutterLayoutManager *manager;
2427 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), 500);
2429 manager = CLUTTER_LAYOUT_MANAGER (layout);
2431 return clutter_layout_manager_get_easing_duration (manager);
2436 * clutter_table_layout_get_row_count:
2437 * @layout: A #ClutterTableLayout
2439 * Retrieve the current number rows in the @layout
2441 * Returns: the number of rows
2446 clutter_table_layout_get_row_count (ClutterTableLayout *layout)
2448 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), -1);
2450 update_row_col (layout, layout->priv->container);
2451 return CLUTTER_TABLE_LAYOUT (layout)->priv->n_rows;
2455 * clutter_table_layout_get_column_count:
2456 * @layout: A #ClutterTableLayout
2458 * Retrieve the current number of columns in @layout
2460 * Returns: the number of columns
2465 clutter_table_layout_get_column_count (ClutterTableLayout *layout)
2467 g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), -1);
2469 update_row_col (layout, layout->priv->container);
2470 return CLUTTER_TABLE_LAYOUT (layout)->priv->n_cols;