#include "config.h"
#include "gtkintl.h"
#include "gtkcellareabox.h"
-#include "gtkcellareaboxcontext.h"
+#include "gtkcellareaboxcontextprivate.h"
#include "gtkorientable.h"
/* GObjectClass */
-static void gtk_cell_area_box_context_finalize (GObject *object);
+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);
+static void _gtk_cell_area_box_context_reset (GtkCellAreaContext *context);
+static void _gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height);
+static void _gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+ gint height,
+ gint *minimum_width,
+ gint *natural_width);
+
+
+
+/* Internal functions */
+static void _gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size);
+static void free_cache_array (GArray *array);
+static GArray *group_array_new (GtkCellAreaBoxContext *context);
+static GArray *get_array (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint for_size);
+static gboolean group_expands (GtkCellAreaBoxContext *context,
+ gint group_idx);
+static gint count_expand_groups (GtkCellAreaBoxContext *context);
+
/* CachedSize management */
typedef struct {
gint nat_size;
} CachedSize;
-typedef struct {
- gint min_size;
- gint nat_size;
- gboolean expand;
-} BaseSize;
-
struct _GtkCellAreaBoxContextPrivate
{
/* Table 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;
+ /* Whether each group expands */
+ gboolean *expand;
+
+ /* Whether each group is aligned */
+ gboolean *align;
};
-G_DEFINE_TYPE (GtkCellAreaBoxContext, gtk_cell_area_box_context, GTK_TYPE_CELL_AREA_CONTEXT);
+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 GArray *
+group_array_new (GtkCellAreaBoxContext *context)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GArray *group_array;
+
+ group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ g_array_set_size (group_array, priv->base_widths->len);
+
+ return group_array;
+}
+
+static GArray *
+get_array (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint for_size)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GArray *array;
+
+ if (for_size < 0)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ array = priv->base_widths;
+ else
+ array = priv->base_heights;
+ }
+ else
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_size));
+
+ if (!array)
+ array = priv->base_widths;
+ }
+ else
+ {
+ array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_size));
+
+ if (!array)
+ array = priv->base_heights;
+ }
+ }
+
+ return array;
+}
+
+static gboolean
+group_expands (GtkCellAreaBoxContext *context,
+ gint group_idx)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+
+ g_assert (group_idx >= 0 && group_idx < priv->base_widths->len);
+
+ return priv->expand[group_idx];
+}
+
+static gint
+count_expand_groups (GtkCellAreaBoxContext *context)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ gint i, expand = 0;
+
+ for (i = 0; i < priv->base_widths->len; i++)
+ {
+ if (priv->expand[i])
+ expand++;
+ }
+
+ return expand;
+}
+
static void
-gtk_cell_area_box_context_init (GtkCellAreaBoxContext *box_context)
+_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);
+ 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->base_widths = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ priv->base_heights = g_array_new (FALSE, TRUE, sizeof (CachedSize));
priv->widths = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)free_cache_array);
+ 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;
+ NULL, (GDestroyNotify)free_cache_array);
}
static void
-gtk_cell_area_box_context_class_init (GtkCellAreaBoxContextClass *class)
+_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;
+ 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;
+ context_class->reset = _gtk_cell_area_box_context_reset;
+ context_class->get_preferred_height_for_width = _gtk_cell_area_box_context_get_preferred_height_for_width;
+ context_class->get_preferred_width_for_height = _gtk_cell_area_box_context_get_preferred_width_for_height;
g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxContextPrivate));
}
* GObjectClass *
*************************************************************/
static void
-gtk_cell_area_box_context_finalize (GObject *object)
+_gtk_cell_area_box_context_finalize (GObject *object)
{
GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (object);
GtkCellAreaBoxContextPrivate *priv = box_context->priv;
g_hash_table_destroy (priv->widths);
g_hash_table_destroy (priv->heights);
- g_free (priv->orientation_allocs);
+ g_free (priv->expand);
+ g_free (priv->align);
- G_OBJECT_CLASS (gtk_cell_area_box_context_parent_class)->finalize (object);
+ G_OBJECT_CLASS (_gtk_cell_area_box_context_parent_class)->finalize (object);
}
/*************************************************************
- * GtkCellAreaContextClass *
+ * GtkCellAreaContextClass *
*************************************************************/
static void
-gtk_cell_area_box_context_flush_preferred_width (GtkCellAreaContext *context)
+_gtk_cell_area_box_context_reset (GtkCellAreaContext *context)
{
GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ CachedSize *size;
gint i;
for (i = 0; i < priv->base_widths->len; i++)
{
- BaseSize *size = &g_array_index (priv->base_widths, BaseSize, i);
+ size = &g_array_index (priv->base_widths, CachedSize, 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 = &g_array_index (priv->base_heights, CachedSize, 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));
+ /* Reset context sizes as well */
+ g_hash_table_remove_all (priv->widths);
+ g_hash_table_remove_all (priv->heights);
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;
+ (_gtk_cell_area_box_context_parent_class)->reset (context);
}
static void
-gtk_cell_area_box_context_sum_preferred_width (GtkCellAreaContext *context)
+_gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size)
{
- 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++)
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GtkCellAreaBox *area;
+ GtkOrientation box_orientation;
+ GArray *array;
+ gint spacing, i, last_aligned_group_idx;
+ gint min_size = 0, nat_size = 0;
+
+ area = (GtkCellAreaBox *)gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (context));
+ spacing = gtk_cell_area_box_get_spacing (area);
+ box_orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+ array = get_array (context, orientation, for_size);
+
+ /* Get the last visible aligned group
+ * (we need to get space at least up till this group) */
+ for (i = array->len - 1; i >= 0; 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);
- }
+ if (priv->align[i] &&
+ _gtk_cell_area_box_group_visible (area, i))
+ break;
}
+ last_aligned_group_idx = i >= 0 ? i : 0;
- 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)
+ for (i = 0; i < array->len; i++)
{
- 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);
+ CachedSize *size = &g_array_index (array, CachedSize, i);
+
+ if (box_orientation == orientation)
+ {
+ if (i > last_aligned_group_idx &&
+ !_gtk_cell_area_box_group_visible (area, i))
+ continue;
+
+ /* 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);
+ }
}
-}
-
-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++)
+ if (for_size < 0)
{
- 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;
- }
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_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 (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
}
- gtk_cell_area_context_push_preferred_height (context, min_size, nat_size);
+ if (minimum_size)
+ *minimum_size = min_size;
+ if (natural_size)
+ *natural_size = nat_size;
}
static void
-gtk_cell_area_box_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
- gint height)
+_gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+ gint width,
+ gint *minimum_height,
+ gint *natural_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);
- }
+ _gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_VERTICAL,
+ width, minimum_height, natural_height);
}
-static GtkRequestedSize *
-gtk_cell_area_box_context_get_requests (GtkCellAreaBoxContext *box_context,
- GtkOrientation orientation,
- gint *n_requests)
+static void
+_gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+ gint height,
+ gint *minimum_width,
+ gint *natural_width)
{
- 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;
+ _gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_HORIZONTAL,
+ height, minimum_width, natural_width);
}
-static GtkCellAreaBoxAllocation *
-allocate_for_orientation (GtkCellAreaBoxContext *context,
- GtkOrientation orientation,
- gint spacing,
- gint size,
- gint *n_allocs)
+/*************************************************************
+ * API *
+ *************************************************************/
+static void
+copy_size_array (GArray *src_array,
+ GArray *dest_array)
{
- 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);
+ gint i;
- /* 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++)
+ for (i = 0; i < src_array->len; 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--;
- }
- }
+ CachedSize *src = &g_array_index (src_array, CachedSize, i);
+ CachedSize *dest = &g_array_index (dest_array, CachedSize, i);
- position += allocs[i].size;
- position += spacing;
+ memcpy (dest, src, sizeof (CachedSize));
}
-
- 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)
+for_size_copy (gpointer key,
+ GArray *size_array,
+ GHashTable *dest_hash)
{
- 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));
+ GArray *new_array;
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ new_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ g_array_set_size (new_array, size_array->len);
- g_free (priv->orientation_allocs);
- priv->orientation_allocs = allocate_for_orientation (box_context, orientation, spacing, width,
- &priv->n_orientation_allocs);
- }
+ copy_size_array (size_array, new_array);
- GTK_CELL_AREA_CONTEXT_CLASS (gtk_cell_area_box_context_parent_class)->allocate_width (context, width);
+ g_hash_table_insert (dest_hash, key, new_array);
}
-static void
-gtk_cell_area_box_context_allocate_height (GtkCellAreaContext *context,
- gint height)
+GtkCellAreaBoxContext *
+_gtk_cell_area_box_context_copy (GtkCellAreaBox *box,
+ GtkCellAreaBoxContext *context)
{
- GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
- GtkCellAreaBoxContextPrivate *priv = box_context->priv;
- GtkCellArea *area;
- GtkOrientation orientation;
+ GtkCellAreaBoxContext *copy;
- area = gtk_cell_area_context_get_area (context);
- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+ copy = g_object_new (GTK_TYPE_CELL_AREA_BOX_CONTEXT,
+ "area", box, NULL);
- if (orientation == GTK_ORIENTATION_VERTICAL)
- {
- gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ _gtk_cell_area_box_init_groups (copy,
+ context->priv->base_widths->len,
+ context->priv->expand,
+ context->priv->align);
+
+ /* Copy the base arrays */
+ copy_size_array (context->priv->base_widths,
+ copy->priv->base_widths);
+ copy_size_array (context->priv->base_heights,
+ copy->priv->base_heights);
+
+ /* Copy each for size */
+ g_hash_table_foreach (context->priv->heights,
+ (GHFunc)for_size_copy, copy->priv->heights);
+ g_hash_table_foreach (context->priv->widths,
+ (GHFunc)for_size_copy, copy->priv->widths);
- 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);
+ return copy;
}
-/*************************************************************
- * API *
- *************************************************************/
void
-gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
- guint n_groups,
- gboolean *expand_groups)
+_gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
+ guint n_groups,
+ gboolean *expand_groups,
+ gboolean *align_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
+ /* When the group dimensions change, all info must be reset
+ * Note this already clears the min/nat values on the CachedSizes
*/
- gtk_cell_area_context_flush (GTK_CELL_AREA_CONTEXT (box_context));
+ gtk_cell_area_context_reset (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);
+ g_free (priv->expand);
+ priv->expand = g_memdup (expand_groups, n_groups * sizeof (gboolean));
- base_width->expand = expand_groups[i];
- base_height->expand = expand_groups[i];
- }
+ g_free (priv->align);
+ priv->align = g_memdup (align_groups, n_groups * sizeof (gboolean));
}
void
-gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
- gint group_idx,
- gint minimum_width,
- gint natural_width)
+_gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint minimum_width,
+ gint natural_width)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ CachedSize *size;
+ gboolean grew = FALSE;
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);
+ size = &g_array_index (priv->base_widths, CachedSize, group_idx);
+ if (minimum_width > size->min_size)
+ {
+ size->min_size = minimum_width;
+ grew = TRUE;
+ }
+ if (natural_width > size->nat_size)
+ {
+ size->nat_size = natural_width;
+ grew = TRUE;
+ }
+
+ if (grew)
+ _gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL, -1, NULL, NULL);
}
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)
+_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;
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);
-
+ group_array = group_array_new (box_context);
g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), group_array);
}
}
void
-gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
- gint group_idx,
- gint minimum_height,
- gint natural_height)
+_gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint minimum_height,
+ gint natural_height)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ CachedSize *size;
+ gboolean grew = FALSE;
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);
+ size = &g_array_index (priv->base_heights, CachedSize, group_idx);
+ if (minimum_height > size->min_size)
+ {
+ size->min_size = minimum_height;
+ grew = TRUE;
+ }
+ if (natural_height > size->nat_size)
+ {
+ size->nat_size = natural_height;
+ grew = TRUE;
+ }
+
+ if (grew)
+ _gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL, -1, NULL, NULL);
}
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)
+_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;
+ GArray *group_array;
+ CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
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);
-
+ group_array = group_array_new (box_context);
g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), group_array);
}
}
void
-gtk_cell_area_box_context_get_group_width (GtkCellAreaBoxContext *box_context,
- gint group_idx,
- gint *minimum_width,
- gint *natural_width)
+_gtk_cell_area_box_context_get_group_width (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint *minimum_width,
+ gint *natural_width)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ 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);
- size = &g_array_index (priv->base_widths, BaseSize, group_idx);
+ size = &g_array_index (priv->base_widths, CachedSize, 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)
+_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;
CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
if (minimum_height)
- *minimum_height = size->min_size;
+ *minimum_height = size->min_size;
if (natural_height)
- *natural_height = size->nat_size;
+ *natural_height = size->nat_size;
}
else
{
if (minimum_height)
- *minimum_height = -1;
+ *minimum_height = -1;
if (natural_height)
- *natural_height = -1;
+ *natural_height = -1;
}
}
void
-gtk_cell_area_box_context_get_group_height (GtkCellAreaBoxContext *box_context,
- gint group_idx,
- gint *minimum_height,
- gint *natural_height)
+_gtk_cell_area_box_context_get_group_height (GtkCellAreaBoxContext *box_context,
+ gint group_idx,
+ gint *minimum_height,
+ gint *natural_height)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ 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_heights->len);
- size = &g_array_index (priv->base_heights, BaseSize, group_idx);
+ size = &g_array_index (priv->base_heights, CachedSize, 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)
+_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;
CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
if (minimum_width)
- *minimum_width = size->min_size;
+ *minimum_width = size->min_size;
if (natural_width)
- *natural_width = size->nat_size;
+ *natural_width = size->nat_size;
}
else
{
if (minimum_width)
- *minimum_width = -1;
+ *minimum_width = -1;
if (natural_width)
- *natural_width = -1;
+ *natural_width = -1;
}
}
+static GtkRequestedSize *
+_gtk_cell_area_box_context_get_requests (GtkCellAreaBoxContext *box_context,
+ GtkCellAreaBox *area,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *n_requests)
+{
+ GtkCellAreaBoxContextPrivate *priv = box_context->priv;
+ GtkRequestedSize *requests;
+ GArray *array;
+ CachedSize *size;
+ gint visible_groups = 0;
+ gint last_aligned_group_idx = 0;
+ gint i, j;
+
+ /* Get the last visible aligned group
+ * (we need to get space at least up till this group) */
+ for (i = priv->base_widths->len - 1; i >= 0; i--)
+ {
+ if (priv->align[i] &&
+ _gtk_cell_area_box_group_visible (area, i))
+ break;
+ }
+ last_aligned_group_idx = i >= 0 ? i : 0;
+
+ priv = box_context->priv;
+ array = get_array (box_context, orientation, for_size);
+
+ for (i = 0; i < array->len; i++)
+ {
+ size = &g_array_index (array, CachedSize, i);
+
+ if (size->nat_size > 0 &&
+ (i <= last_aligned_group_idx ||
+ _gtk_cell_area_box_group_visible (area, i)))
+ visible_groups++;
+ }
+
+ requests = g_new (GtkRequestedSize, visible_groups);
+
+ for (j = 0, i = 0; i < array->len; i++)
+ {
+ size = &g_array_index (array, CachedSize, i);
+
+ if (size->nat_size > 0 &&
+ (i <= last_aligned_group_idx ||
+ _gtk_cell_area_box_group_visible (area, i)))
+ {
+ 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,
+ GtkCellAreaBox *area,
+ GtkOrientation orientation,
+ gint spacing,
+ gint size,
+ gint for_size,
+ gint *n_allocs)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GtkCellAreaBoxAllocation *allocs;
+ GtkRequestedSize *sizes;
+ gint n_expand_groups = 0;
+ gint i, n_groups, position, vis_position;
+ gint extra_size, extra_extra;
+ gint avail_size = size;
+
+ sizes = _gtk_cell_area_box_context_get_requests (context, area, orientation, for_size, &n_groups);
+ n_expand_groups = count_expand_groups (context);
+
+ /* First start by naturally allocating space among groups */
+ avail_size -= (n_groups - 1) * spacing;
+ for (i = 0; i < n_groups; i++)
+ avail_size -= sizes[i].minimum_size;
+
+ if (avail_size > 0)
+ avail_size = gtk_distribute_natural_allocation (avail_size, n_groups, sizes);
+ else
+ avail_size = 0;
+
+ /* 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 (vis_position = 0, position = 0, i = 0; i < n_groups; i++)
+ {
+ allocs[i].group_idx = GPOINTER_TO_INT (sizes[i].data);
+
+ if (priv->align[allocs[i].group_idx])
+ vis_position = position;
+
+ allocs[i].position = vis_position;
+ allocs[i].size = sizes[i].minimum_size;
+
+ if (group_expands (context, allocs[i].group_idx))
+ {
+ allocs[i].size += extra_size;
+ if (extra_extra)
+ {
+ allocs[i].size++;
+ extra_extra--;
+ }
+ }
+
+ position += allocs[i].size;
+ position += spacing;
+
+ if (_gtk_cell_area_box_group_visible (area, allocs[i].group_idx))
+ {
+ vis_position += allocs[i].size;
+ vis_position += spacing;
+ }
+ }
+
+ if (n_allocs)
+ *n_allocs = n_groups;
+
+ g_free (sizes);
+
+ return allocs;
+}
+
GtkRequestedSize *
-gtk_cell_area_box_context_get_widths (GtkCellAreaBoxContext *box_context,
- gint *n_widths)
+_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);
+ GtkCellAreaBox *area = (GtkCellAreaBox *)gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (box_context));
+
+ return _gtk_cell_area_box_context_get_requests (box_context, area, GTK_ORIENTATION_HORIZONTAL, -1, n_widths);
}
GtkRequestedSize *
-gtk_cell_area_box_context_get_heights (GtkCellAreaBoxContext *box_context,
- gint *n_heights)
+_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);
+ GtkCellAreaBox *area = (GtkCellAreaBox *)gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (box_context));
+
+ return _gtk_cell_area_box_context_get_requests (box_context, area, GTK_ORIENTATION_VERTICAL, -1, n_heights);
}
-G_CONST_RETURN GtkCellAreaBoxAllocation *
-gtk_cell_area_box_context_get_orientation_allocs (GtkCellAreaBoxContext *context,
- gint *n_allocs)
+GtkCellAreaBoxAllocation *
+_gtk_cell_area_box_context_get_orientation_allocs (GtkCellAreaBoxContext *context,
+ gint *n_allocs)
{
- GtkCellAreaBoxContextPrivate *priv;
+ GtkCellAreaContext *ctx = GTK_CELL_AREA_CONTEXT (context);
+ GtkCellAreaBox *area;
+ GtkOrientation orientation;
+ gint spacing, width, height, alloc_count = 0;
+ GtkCellAreaBoxAllocation *allocs = NULL;
- g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (context), NULL);
-
- priv = context->priv;
+ area = (GtkCellAreaBox *)gtk_cell_area_context_get_area (ctx);
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+ spacing = gtk_cell_area_box_get_spacing (area);
+
+ gtk_cell_area_context_get_allocation (ctx, &width, &height);
- *n_allocs = priv->n_orientation_allocs;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL && width > 0)
+ allocs = allocate_for_orientation (context, area, orientation,
+ spacing, width, height,
+ &alloc_count);
+ else if (orientation == GTK_ORIENTATION_VERTICAL && height > 0)
+ allocs = allocate_for_orientation (context, area, orientation,
+ spacing, height, width,
+ &alloc_count);
- return priv->orientation_allocs;
+ *n_allocs = alloc_count;
+
+ return allocs;
}