static void st_table_calculate_dimensions (StTable *table, gfloat for_width, gfloat for_height) { st_table_calculate_col_widths (table, for_width); st_table_calculate_row_heights (table, for_height); }
static void st_table_get_preferred_height (ClutterActor *self, gfloat for_width, gfloat *min_height_p, gfloat *natural_height_p) { gint *min_heights, *pref_heights; gfloat total_min_height, total_pref_height; StTablePrivate *priv = ST_TABLE (self)->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); gint i; gint *min_widths; ClutterActor *child; /* We only support height-for-width allocation. So if we are called * width-for-height, calculate heights based on our natural width */ if (for_width < 0) { float natural_width; clutter_actor_get_preferred_width (self, -1, NULL, &natural_width); for_width = natural_width; } if (priv->n_rows < 1) { *min_height_p = 0; *natural_height_p = 0; return; } st_theme_node_adjust_for_width (theme_node, &for_width); /* Setting size to zero and then what we want it to be causes a clear if * clear flag is set (which it should be.) */ g_array_set_size (priv->min_heights, 0); g_array_set_size (priv->pref_heights, 0); g_array_set_size (priv->min_heights, priv->n_rows); g_array_set_size (priv->pref_heights, priv->n_rows); /* use min_widths to help allocation of height-for-width widgets */ min_widths = st_table_calculate_col_widths (ST_TABLE (self), for_width); min_heights = (gint *) priv->min_heights->data; pref_heights = (gint *) priv->pref_heights->data; /* calculate minimum row heights */ for (child = clutter_actor_get_first_child (self); child != NULL; child = clutter_actor_get_next_sibling (child)) { gint row, col, col_span, cell_width, row_span; gfloat min, pref; StTableChild *meta; meta = (StTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child); if (!meta->allocate_hidden && !CLUTTER_ACTOR_IS_VISIBLE (child)) continue; /* get child properties */ row = meta->row; col = meta->col; col_span = meta->col_span; row_span = meta->row_span; cell_width = 0; for (i = 0; i < col_span && col + i < priv->n_cols; i++) cell_width += min_widths[col + i]; _st_actor_get_preferred_height (child, (float) cell_width, meta->x_fill, &min, &pref); if (row_span == 1 && min > min_heights[row]) min_heights[row] = min; if (row_span == 1 && pref > pref_heights[row]) pref_heights[row] = pref; } /* start off with row spacing */ total_min_height = (priv->n_rows - 1) * (float) (priv->row_spacing); total_pref_height = total_min_height; for (i = 0; i < priv->n_rows; i++) { total_min_height += min_heights[i]; total_pref_height += pref_heights[i]; } if (min_height_p) *min_height_p = total_min_height; if (natural_height_p) *natural_height_p = total_pref_height; st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); }
static void st_table_preferred_allocate (ClutterActor *self, const ClutterActorBox *content_box, gboolean flags) { gint row_spacing, col_spacing; gint i; gint *col_widths, *row_heights; StTable *table; StTablePrivate *priv; gboolean ltr; ClutterActor *child; table = ST_TABLE (self); priv = ST_TABLE (self)->priv; col_spacing = (priv->col_spacing); row_spacing = (priv->row_spacing); col_widths = st_table_calculate_col_widths (table, (int) (content_box->x2 - content_box->x1)); row_heights = st_table_calculate_row_heights (table, (int) (content_box->y2 - content_box->y1), col_widths); ltr = (clutter_actor_get_text_direction (self) == CLUTTER_TEXT_DIRECTION_LTR); for (child = clutter_actor_get_first_child (self); child != NULL; child = clutter_actor_get_next_sibling (child)) { gint row, col, row_span, col_span; gint col_width, row_height; StTableChild *meta; ClutterActorBox childbox; gint child_x, child_y; gdouble x_align_f, y_align_f; meta = (StTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child); if (!meta->allocate_hidden && !CLUTTER_ACTOR_IS_VISIBLE (child)) continue; /* get child properties */ col = meta->col; row = meta->row; row_span = meta->row_span; col_span = meta->col_span; _st_get_align_factors (meta->x_align, meta->y_align, &x_align_f, &y_align_f); /* initialise the width and height */ col_width = col_widths[col]; row_height = row_heights[row]; /* Add the widths of the spanned columns: * * First check that we have a non-zero span. Then we loop over each of * the columns that we're spanning but we stop short if we go past the * number of columns in the table. This is necessary to avoid accessing * uninitialised memory. We add the spacing in here too since we only * want to add as much spacing as times we successfully span. */ if (col + col_span > priv->n_cols) g_warning ("StTable: col-span exceeds number of columns"); #if 0 if (row + row_span > priv->n_rows) g_warning ("StTable: row-span exceeds number of rows"); #endif if (col_span > 1) { for (i = col + 1; i < col + col_span && i < priv->n_cols; i++) { col_width += col_widths[i]; col_width += col_spacing; } } /* add the height of the spanned rows */ if (row_span > 1) { for (i = row + 1; i < row + row_span && i < priv->n_rows; i++) { row_height += row_heights[i]; row_height += row_spacing; } } /* calculate child x */ if (ltr) { child_x = (int) content_box->x1 + col_spacing * col; for (i = 0; i < col; i++) child_x += col_widths[i]; } else { child_x = (int) content_box->x2 - col_spacing * col; for (i = 0; i < col; i++) child_x -= col_widths[i]; } /* calculate child y */ child_y = (int) content_box->y1 + row_spacing * row; for (i = 0; i < row; i++) child_y += row_heights[i]; /* set up childbox */ if (ltr) { childbox.x1 = (float) child_x; childbox.x2 = (float) MAX (0, child_x + col_width); } else { childbox.x2 = (float) child_x; childbox.x1 = (float) MAX (0, child_x - col_width); } childbox.y1 = (float) child_y; childbox.y2 = (float) MAX (0, child_y + row_height); clutter_actor_allocate_align_fill (child, &childbox, x_align_f, y_align_f, meta->x_fill, meta->y_fill, flags); } }