summaryrefslogtreecommitdiff
path: root/gtk/gtkcellareaboxcontext.c
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2010-11-13 16:23:01 +0900
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2010-11-13 16:23:01 +0900
commit1bca6349fb5b5b8130e5a7a7cad275cfc12e7346 (patch)
tree7464395bbca302770852edf0b329a422a3616788 /gtk/gtkcellareaboxcontext.c
parentbef95590891a7c7c7a85e559093aee9ada4129f0 (diff)
downloadgtk+-1bca6349fb5b5b8130e5a7a7cad275cfc12e7346.tar.gz
Mass rename GtkCellAreaIter --> GtkCellAreaContext
Diffstat (limited to 'gtk/gtkcellareaboxcontext.c')
-rw-r--r--gtk/gtkcellareaboxcontext.c886
1 files changed, 886 insertions, 0 deletions
diff --git a/gtk/gtkcellareaboxcontext.c b/gtk/gtkcellareaboxcontext.c
new file mode 100644
index 0000000000..e0501e6944
--- /dev/null
+++ b/gtk/gtkcellareaboxcontext.c
@@ -0,0 +1,886 @@
+/* gtkcellareaboxcontext.c
+ *
+ * Copyright (C) 2010 Openismus GmbH
+ *
+ * Authors:
+ * Tristan Van Berkom <tristanvb@openismus.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "gtkintl.h"
+#include "gtkcellareabox.h"
+#include "gtkcellareaboxcontext.h"
+#include "gtkorientable.h"
+
+/* GObjectClass */
+static void gtk_cell_area_box_context_finalize (GObject *object);
+
+/* GtkCellAreaContextClass */
+static void gtk_cell_area_box_context_flush_preferred_width (GtkCellAreaContext *context);
+static void gtk_cell_area_box_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
+ gint width);
+static void gtk_cell_area_box_context_flush_preferred_height (GtkCellAreaContext *context);
+static void gtk_cell_area_box_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
+ gint height);
+static void gtk_cell_area_box_context_flush_allocation (GtkCellAreaContext *context);
+static void gtk_cell_area_box_context_sum_preferred_width (GtkCellAreaContext *context);
+static void gtk_cell_area_box_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
+ gint width);
+static void gtk_cell_area_box_context_sum_preferred_height (GtkCellAreaContext *context);
+static void gtk_cell_area_box_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
+ gint height);
+static void gtk_cell_area_box_context_allocate_width (GtkCellAreaContext *context,
+ gint width);
+static void gtk_cell_area_box_context_allocate_height (GtkCellAreaContext *context,
+ gint height);
+
+static void free_cache_array (GArray *array);
+
+/* CachedSize management */
+typedef struct {
+ gint min_size;
+ gint nat_size;
+} CachedSize;
+
+typedef struct {
+ gint min_size;
+ gint nat_size;
+ gboolean expand;
+} BaseSize;
+
+struct _GtkCellAreaBoxContextPrivate
+{
+ /* Table of per renderer CachedSizes */
+ GArray *base_widths;
+ GArray *base_heights;
+
+ /* Table of per height/width hash tables of per renderer CachedSizes */
+ GHashTable *widths;
+ GHashTable *heights;
+
+ /* Allocation info for this context if any */
+ gint alloc_width;
+ gint alloc_height;
+ gint n_orientation_allocs;
+ GtkCellAreaBoxAllocation *orientation_allocs;
+};
+
+G_DEFINE_TYPE (GtkCellAreaBoxContext, gtk_cell_area_box_context, GTK_TYPE_CELL_AREA_CONTEXT);
+
+static void
+free_cache_array (GArray *array)
+{
+ g_array_free (array, TRUE);
+}
+
+static void
+gtk_cell_area_box_context_init (GtkCellAreaBoxContext *box_context)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+
+ box_context->priv = G_TYPE_INSTANCE_GET_PRIVATE (box_context,
+ GTK_TYPE_CELL_AREA_BOX_CONTEXT,
+ GtkCellAreaBoxContextPrivate);
+ priv = box_context->priv;
+
+ priv->base_widths = g_array_new (FALSE, TRUE, sizeof (BaseSize));
+ priv->base_heights = g_array_new (FALSE, TRUE, sizeof (BaseSize));
+
+ priv->widths = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify)free_cache_array);
+ priv->heights = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify)free_cache_array);
+
+ priv->alloc_width = 0;
+ priv->alloc_height = 0;
+ priv->orientation_allocs = NULL;
+ priv->n_orientation_allocs = 0;
+}
+
+static void
+gtk_cell_area_box_context_class_init (GtkCellAreaBoxContextClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkCellAreaContextClass *context_class = GTK_CELL_AREA_CONTEXT_CLASS (class);
+
+ /* GObjectClass */
+ object_class->finalize = gtk_cell_area_box_context_finalize;
+
+ context_class->flush_preferred_width = gtk_cell_area_box_context_flush_preferred_width;
+ context_class->flush_preferred_height_for_width = gtk_cell_area_box_context_flush_preferred_height_for_width;
+ context_class->flush_preferred_height = gtk_cell_area_box_context_flush_preferred_height;
+ context_class->flush_preferred_width_for_height = gtk_cell_area_box_context_flush_preferred_width_for_height;
+ context_class->flush_allocation = gtk_cell_area_box_context_flush_allocation;
+
+ context_class->sum_preferred_width = gtk_cell_area_box_context_sum_preferred_width;
+ context_class->sum_preferred_height_for_width = gtk_cell_area_box_context_sum_preferred_height_for_width;
+ context_class->sum_preferred_height = gtk_cell_area_box_context_sum_preferred_height;
+ context_class->sum_preferred_width_for_height = gtk_cell_area_box_context_sum_preferred_width_for_height;
+
+ context_class->allocate_width = gtk_cell_area_box_context_allocate_width;
+ context_class->allocate_height = gtk_cell_area_box_context_allocate_height;
+
+ g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxContextPrivate));
+}
+
+/*************************************************************
+ * GObjectClass *
+ *************************************************************/
+static void
+gtk_cell_area_box_context_finalize (GObject *object)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (object);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+
+ g_array_free (priv->base_widths, TRUE);
+ g_array_free (priv->base_heights, TRUE);
+ g_hash_table_destroy (priv->widths);
+ g_hash_table_destroy (priv->heights);
+
+ g_free (priv->orientation_allocs);
+
+ G_OBJECT_CLASS (gtk_cell_area_box_context_parent_class)->finalize (object);
+}
+
+/*************************************************************
+ * GtkCellAreaContextClass *
+ *************************************************************/
+static void
+gtk_cell_area_box_context_flush_preferred_width (GtkCellAreaContext *context)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ gint i;
+
+ for (i = 0; i < priv->base_widths->len; i++)
+ {
+ BaseSize *size = &g_array_index (priv->base_widths, BaseSize, i);
+
+ size->min_size = 0;
+ size->nat_size = 0;
+ }
+
+ GTK_CELL_AREA_CONTEXT_CLASS
+ (gtk_cell_area_box_context_parent_class)->flush_preferred_width (context);
+}
+
+static void
+gtk_cell_area_box_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
+ gint width)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+
+ /* Flush all sizes for special -1 value */
+ if (width < 0)
+ g_hash_table_remove_all (priv->heights);
+ else
+ g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
+
+ GTK_CELL_AREA_CONTEXT_CLASS
+ (gtk_cell_area_box_context_parent_class)->flush_preferred_height_for_width (context, width);
+}
+
+static void
+gtk_cell_area_box_context_flush_preferred_height (GtkCellAreaContext *context)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ gint i;
+
+ for (i = 0; i < priv->base_heights->len; i++)
+ {
+ BaseSize *size = &g_array_index (priv->base_heights, BaseSize, i);
+
+ size->min_size = 0;
+ size->nat_size = 0;
+ }
+
+ GTK_CELL_AREA_CONTEXT_CLASS
+ (gtk_cell_area_box_context_parent_class)->flush_preferred_height (context);
+}
+
+static void
+gtk_cell_area_box_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
+ gint height)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+
+ /* Flush all sizes for special -1 value */
+ if (height < 0)
+ g_hash_table_remove_all (priv->widths);
+ else
+ g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
+
+ GTK_CELL_AREA_CONTEXT_CLASS
+ (gtk_cell_area_box_context_parent_class)->flush_preferred_width_for_height (context, height);
+}
+
+static void
+gtk_cell_area_box_context_flush_allocation (GtkCellAreaContext *context)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+
+ g_free (priv->orientation_allocs);
+ priv->orientation_allocs = NULL;
+ priv->n_orientation_allocs = 0;
+}
+
+static void
+gtk_cell_area_box_context_sum_preferred_width (GtkCellAreaContext *context)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
+
+ area = gtk_cell_area_context_get_area (context);
+ spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+
+ for (i = 0; i < priv->base_widths->len; i++)
+ {
+ BaseSize *size = &g_array_index (priv->base_widths, BaseSize, i);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ /* Dont add spacing for 0 size groups, they can be 0 size because
+ * they contain only invisible cells for this round of requests
+ */
+ if (min_size > 0 && size->nat_size > 0)
+ {
+ min_size += spacing;
+ nat_size += spacing;
+ }
+
+ min_size += size->min_size;
+ nat_size += size->nat_size;
+ }
+ else
+ {
+ min_size = MAX (min_size, size->min_size);
+ nat_size = MAX (nat_size, size->nat_size);
+ }
+ }
+
+ gtk_cell_area_context_push_preferred_width (context, min_size, nat_size);
+}
+
+static void
+gtk_cell_area_box_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
+ gint width)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GArray *group_array;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
+
+ group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (width));
+
+ if (group_array)
+ {
+ area = gtk_cell_area_context_get_area (context);
+ spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+
+ for (i = 0; i < group_array->len; i++)
+ {
+ CachedSize *size = &g_array_index (group_array, CachedSize, i);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ /* Dont add spacing for 0 size groups, they can be 0 size because
+ * they contain only invisible cells for this round of requests
+ */
+ if (min_size > 0 && size->nat_size > 0)
+ {
+ min_size += spacing;
+ nat_size += spacing;
+ }
+
+ min_size += size->min_size;
+ nat_size += size->nat_size;
+ }
+ else
+ {
+ min_size = MAX (min_size, size->min_size);
+ nat_size = MAX (nat_size, size->nat_size);
+ }
+ }
+
+ gtk_cell_area_context_push_preferred_height_for_width (context, width, min_size, nat_size);
+ }
+}
+
+static void
+gtk_cell_area_box_context_sum_preferred_height (GtkCellAreaContext *context)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
+
+ area = gtk_cell_area_context_get_area (context);
+ spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+
+ for (i = 0; i < priv->base_heights->len; i++)
+ {
+ BaseSize *size = &g_array_index (priv->base_heights, BaseSize, i);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ /* Dont add spacing for 0 size groups, they can be 0 size because
+ * they contain only invisible cells for this round of requests
+ */
+ if (min_size > 0 && size->nat_size > 0)
+ {
+ min_size += spacing;
+ nat_size += spacing;
+ }
+
+ min_size += size->min_size;
+ nat_size += size->nat_size;
+ }
+ else
+ {
+ min_size = MAX (min_size, size->min_size);
+ nat_size = MAX (nat_size, size->nat_size);
+ }
+ }
+
+ gtk_cell_area_context_push_preferred_height (context, min_size, nat_size);
+}
+
+static void
+gtk_cell_area_box_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
+ gint height)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GArray *group_array;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
+
+ group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (height));
+
+ if (group_array)
+ {
+ area = gtk_cell_area_context_get_area (context);
+ spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+
+ for (i = 0; i < group_array->len; i++)
+ {
+ CachedSize *size = &g_array_index (group_array, CachedSize, i);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ /* Dont add spacing for 0 size groups, they can be 0 size because
+ * they contain only invisible cells for this round of requests
+ */
+ if (min_size > 0 && size->nat_size > 0)
+ {
+ min_size += spacing;
+ nat_size += spacing;
+ }
+
+ min_size += size->min_size;
+ nat_size += size->nat_size;
+ }
+ else
+ {
+ min_size = MAX (min_size, size->min_size);
+ nat_size = MAX (nat_size, size->nat_size);
+ }
+ }
+
+ gtk_cell_area_context_push_preferred_width_for_height (context, height, min_size, nat_size);
+ }
+}
+
+static GtkRequestedSize *
+gtk_cell_area_box_context_get_requests (GtkCellAreaBoxContext *box_context,
+ GtkOrientation orientation,
+ gint *n_requests)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ GtkRequestedSize *requests;
+ GArray *base_array;
+ BaseSize *size;
+ gint visible_groups = 0;
+ gint i, j;
+
+ g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context), NULL);
+
+ priv = box_context->priv;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ base_array = priv->base_widths;
+ else
+ base_array = priv->base_heights;
+
+ for (i = 0; i < base_array->len; i++)
+ {
+ size = &g_array_index (base_array, BaseSize, i);
+
+ if (size->nat_size > 0)
+ visible_groups++;
+ }
+
+ requests = g_new (GtkRequestedSize, visible_groups);
+
+ for (j = 0, i = 0; i < base_array->len; i++)
+ {
+ size = &g_array_index (base_array, BaseSize, i);
+
+ if (size->nat_size > 0)
+ {
+ requests[j].data = GINT_TO_POINTER (i);
+ requests[j].minimum_size = size->min_size;
+ requests[j].natural_size = size->nat_size;
+ j++;
+ }
+ }
+
+ if (n_requests)
+ *n_requests = visible_groups;
+
+ return requests;
+}
+
+static GtkCellAreaBoxAllocation *
+allocate_for_orientation (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint spacing,
+ gint size,
+ gint *n_allocs)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GtkRequestedSize *orientation_sizes;
+ GtkCellAreaBoxAllocation *allocs;
+ gint n_expand_groups = 0;
+ gint i, n_groups, position;
+ gint extra_size, extra_extra;
+ gint avail_size = size;
+
+ orientation_sizes =
+ gtk_cell_area_box_context_get_requests (context, orientation, &n_groups);
+
+ /* Count groups that expand */
+ for (i = 0; i < n_groups; i++)
+ {
+ BaseSize *size;
+ gint group_idx = GPOINTER_TO_INT (orientation_sizes[i].data);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ size = &g_array_index (priv->base_widths, BaseSize, group_idx);
+ else
+ size = &g_array_index (priv->base_heights, BaseSize, group_idx);
+
+ if (size->expand)
+ n_expand_groups++;
+ }
+
+ /* First start by naturally allocating space among groups */
+ avail_size -= (n_groups - 1) * spacing;
+ for (i = 0; i < n_groups; i++)
+ avail_size -= orientation_sizes[i].minimum_size;
+
+ avail_size = gtk_distribute_natural_allocation (avail_size, n_groups, orientation_sizes);
+
+ /* Calculate/distribute expand for groups */
+ if (n_expand_groups > 0)
+ {
+ extra_size = avail_size / n_expand_groups;
+ extra_extra = avail_size % n_expand_groups;
+ }
+ else
+ extra_size = extra_extra = 0;
+
+ allocs = g_new (GtkCellAreaBoxAllocation, n_groups);
+
+ for (position = 0, i = 0; i < n_groups; i++)
+ {
+ BaseSize *base_size = &g_array_index (priv->base_widths, BaseSize, i);
+
+ allocs[i].group_idx = GPOINTER_TO_INT (orientation_sizes[i].data);
+ allocs[i].position = position;
+ allocs[i].size = orientation_sizes[i].minimum_size;
+
+ if (base_size->expand)
+ {
+ allocs[i].size += extra_size;
+ if (extra_extra)
+ {
+ allocs[i].size++;
+ extra_extra--;
+ }
+ }
+
+ position += allocs[i].size;
+ position += spacing;
+ }
+
+ if (n_allocs)
+ *n_allocs = n_groups;
+
+ g_free (orientation_sizes);
+
+ return allocs;
+}
+
+static void
+gtk_cell_area_box_context_allocate_width (GtkCellAreaContext *context,
+ gint width)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+
+ area = gtk_cell_area_context_get_area (context);
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+
+ g_free (priv->orientation_allocs);
+ priv->orientation_allocs = allocate_for_orientation (box_context, orientation, spacing, width,
+ &priv->n_orientation_allocs);
+ }
+
+ GTK_CELL_AREA_CONTEXT_CLASS (gtk_cell_area_box_context_parent_class)->allocate_width (context, width);
+}
+
+static void
+gtk_cell_area_box_context_allocate_height (GtkCellAreaContext *context,
+ gint height)
+{
+ GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+
+ area = gtk_cell_area_context_get_area (context);
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+
+ g_free (priv->orientation_allocs);
+ priv->orientation_allocs = allocate_for_orientation (box_context, orientation, spacing, height,
+ &priv->n_orientation_allocs);
+ }
+
+ GTK_CELL_AREA_CONTEXT_CLASS (gtk_cell_area_box_context_parent_class)->allocate_height (context, height);
+}
+
+/*************************************************************
+ * API *
+ *************************************************************/
+void
+gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
+ guint n_groups,
+ gboolean *expand_groups)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+ g_return_if_fail (n_groups == 0 || expand_groups != NULL);
+
+ /* When the group dimensions change, all info must be flushed
+ * Note this already clears the min/nat values on the BaseSizes
+ */
+ gtk_cell_area_context_flush (GTK_CELL_AREA_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_array_set_size (priv->base_widths, n_groups);
+ g_array_set_size (priv->base_heights, n_groups);
+
+ /* Now set the expand info */
+ for (i = 0; i < n_groups; i++)
+ {
+ BaseSize *base_width = &g_array_index (priv->base_widths, BaseSize, i);
+ BaseSize *base_height = &g_array_index (priv->base_heights, BaseSize, i);
+
+ base_width->expand = expand_groups[i];
+ base_height->expand = expand_groups[i];
+ }
+}
+
+void
+gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint minimum_width,
+ gint natural_width)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ BaseSize *size;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_widths->len);
+
+ size = &g_array_index (priv->base_widths, BaseSize, group_idx);
+ size->min_size = MAX (size->min_size, minimum_width);
+ size->nat_size = MAX (size->nat_size, natural_width);
+}
+
+void
+gtk_cell_area_box_context_push_group_height_for_width (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint for_width,
+ gint minimum_height,
+ gint natural_height)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ GArray *group_array;
+ CachedSize *size;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_widths->len);
+
+ group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+ if (!group_array)
+ {
+ group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ g_array_set_size (group_array, priv->base_heights->len);
+
+ g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), group_array);
+ }
+
+ size = &g_array_index (group_array, CachedSize, group_idx);
+ size->min_size = MAX (size->min_size, minimum_height);
+ size->nat_size = MAX (size->nat_size, natural_height);
+}
+
+void
+gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint minimum_height,
+ gint natural_height)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ BaseSize *size;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_heights->len);
+
+ size = &g_array_index (priv->base_heights, BaseSize, group_idx);
+ size->min_size = MAX (size->min_size, minimum_height);
+ size->nat_size = MAX (size->nat_size, natural_height);
+}
+
+void
+gtk_cell_area_box_context_push_group_width_for_height (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint for_height,
+ gint minimum_width,
+ gint natural_width)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ GArray *group_array;
+ CachedSize *size;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_widths->len);
+
+ group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+ if (!group_array)
+ {
+ group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ g_array_set_size (group_array, priv->base_heights->len);
+
+ g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), group_array);
+ }
+
+ size = &g_array_index (group_array, CachedSize, group_idx);
+ size->min_size = MAX (size->min_size, minimum_width);
+ size->nat_size = MAX (size->nat_size, natural_width);
+}
+
+void
+gtk_cell_area_box_context_get_group_width (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ BaseSize *size;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_widths->len);
+
+ size = &g_array_index (priv->base_widths, BaseSize, group_idx);
+
+ if (minimum_width)
+ *minimum_width = size->min_size;
+
+ if (natural_width)
+ *natural_width = size->nat_size;
+}
+
+void
+gtk_cell_area_box_context_get_group_height_for_width (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint for_width,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ GArray *group_array;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_widths->len);
+
+ group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+
+ if (group_array)
+ {
+ CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
+
+ if (minimum_height)
+ *minimum_height = size->min_size;
+
+ if (natural_height)
+ *natural_height = size->nat_size;
+ }
+ else
+ {
+ if (minimum_height)
+ *minimum_height = -1;
+
+ if (natural_height)
+ *natural_height = -1;
+ }
+}
+
+void
+gtk_cell_area_box_context_get_group_height (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ BaseSize *size;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_heights->len);
+
+ size = &g_array_index (priv->base_heights, BaseSize, group_idx);
+
+ if (minimum_height)
+ *minimum_height = size->min_size;
+
+ if (natural_height)
+ *natural_height = size->nat_size;
+}
+
+void
+gtk_cell_area_box_context_get_group_width_for_height (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint for_height,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+ GArray *group_array;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+ priv = box_context->priv;
+ g_return_if_fail (group_idx < priv->base_widths->len);
+
+ group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+
+ if (group_array)
+ {
+ CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
+
+ if (minimum_width)
+ *minimum_width = size->min_size;
+
+ if (natural_width)
+ *natural_width = size->nat_size;
+ }
+ else
+ {
+ if (minimum_width)
+ *minimum_width = -1;
+
+ if (natural_width)
+ *natural_width = -1;
+ }
+}
+
+GtkRequestedSize *
+gtk_cell_area_box_context_get_widths (GtkCellAreaBoxContext *box_context,
+ gint *n_widths)
+{
+ return gtk_cell_area_box_context_get_requests (box_context, GTK_ORIENTATION_HORIZONTAL, n_widths);
+}
+
+GtkRequestedSize *
+gtk_cell_area_box_context_get_heights (GtkCellAreaBoxContext *box_context,
+ gint *n_heights)
+{
+ return gtk_cell_area_box_context_get_requests (box_context, GTK_ORIENTATION_VERTICAL, n_heights);
+}
+
+G_CONST_RETURN GtkCellAreaBoxAllocation *
+gtk_cell_area_box_context_get_orientation_allocs (GtkCellAreaBoxContext *context,
+ gint *n_allocs)
+{
+ GtkCellAreaBoxContextPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (context), NULL);
+
+ priv = context->priv;
+
+ *n_allocs = priv->n_orientation_allocs;
+
+ return priv->orientation_allocs;
+}