[gtk+/treeview-refactor] Cleaned up GtkCellAreaIter implementation to use arrays to store grouped cell information.
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/treeview-refactor] Cleaned up GtkCellAreaIter implementation to use arrays to store grouped cell information.
- Date: Sun, 31 Oct 2010 04:06:05 +0000 (UTC)
commit e494f102cfcd3798797cfc2ecc346da433a000ef
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sun Oct 31 13:06:10 2010 +0900
Cleaned up GtkCellAreaIter implementation to use arrays to store grouped cell information.
gtk/gtkcellareabox.c | 176 ++++++--------
gtk/gtkcellareaboxiter.c | 598 ++++++++++++++++++++++++++++------------------
gtk/gtkcellareaboxiter.h | 26 +-
3 files changed, 458 insertions(+), 342 deletions(-)
---
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index 273da69..a341dd7 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -115,24 +115,28 @@ typedef struct {
guint expand : 1;
} CellGroup;
-static CellInfo *cell_info_new (GtkCellRenderer *renderer,
- GtkPackType pack,
- gboolean expand,
- gboolean align);
-static void cell_info_free (CellInfo *info);
-static gint cell_info_find (CellInfo *info,
- GtkCellRenderer *renderer);
-
-static CellGroup *cell_group_new (guint id);
-static void cell_group_free (CellGroup *group);
-
-static GList *list_consecutive_cells (GtkCellAreaBox *box);
-static GList *construct_cell_groups (GtkCellAreaBox *box);
-static gint count_expand_groups (GtkCellAreaBox *box);
-static gint count_expand_cells (CellGroup *group);
-static void iter_weak_notify (GtkCellAreaBox *box,
- GtkCellAreaIter *dead_iter);
-static void flush_iters (GtkCellAreaBox *box);
+static CellInfo *cell_info_new (GtkCellRenderer *renderer,
+ GtkPackType pack,
+ gboolean expand,
+ gboolean align);
+static void cell_info_free (CellInfo *info);
+static gint cell_info_find (CellInfo *info,
+ GtkCellRenderer *renderer);
+
+static CellGroup *cell_group_new (guint id);
+static void cell_group_free (CellGroup *group);
+
+static GList *list_consecutive_cells (GtkCellAreaBox *box);
+static GList *construct_cell_groups (GtkCellAreaBox *box);
+static gint count_expand_groups (GtkCellAreaBox *box);
+static gint count_expand_cells (CellGroup *group);
+static void iter_weak_notify (GtkCellAreaBox *box,
+ GtkCellAreaBoxIter *dead_iter);
+static void flush_iters (GtkCellAreaBox *box);
+static void init_iter_groups (GtkCellAreaBox *box);
+static void init_iter_group (GtkCellAreaBox *box,
+ GtkCellAreaBoxIter *iter);
+
struct _GtkCellAreaBoxPrivate
{
@@ -387,8 +391,8 @@ count_expand_cells (CellGroup *group)
}
static void
-iter_weak_notify (GtkCellAreaBox *box,
- GtkCellAreaIter *dead_iter)
+iter_weak_notify (GtkCellAreaBox *box,
+ GtkCellAreaBoxIter *dead_iter)
{
GtkCellAreaBoxPrivate *priv = box->priv;
@@ -396,95 +400,61 @@ iter_weak_notify (GtkCellAreaBox *box,
}
static void
-flush_iters (GtkCellAreaBox *box)
+init_iter_group (GtkCellAreaBox *box,
+ GtkCellAreaBoxIter *iter)
{
GtkCellAreaBoxPrivate *priv = box->priv;
- GSList *l;
+ gint n_groups, *expand_groups, i;
+ GList *l;
- /* When the box layout changes, iters need to
- * be flushed and sizes for the box get requested again
- */
- for (l = priv->iters; l; l = l->next)
+ n_groups = g_list_length (priv->groups);
+ expand_groups = g_new (gboolean, n_groups);
+
+ for (i = 0, l = priv->groups; l; l = l->next, i++)
{
- GtkCellAreaIter *iter = l->data;
+ CellGroup *group = l->data;
- gtk_cell_area_iter_flush (iter);
+ expand_groups[i] = group->expand;
}
-}
+ gtk_cell_area_box_init_groups (iter, n_groups, expand_groups);
+ g_free (expand_groups);
+}
-/* XXX This guy makes an allocation to be stored and retrieved from the iter */
-GtkCellAreaBoxAllocation *
-gtk_cell_area_box_allocate (GtkCellAreaBox *box,
- GtkCellAreaBoxIter *iter,
- gint size,
- gint *n_allocs)
+static void
+init_iter_groups (GtkCellAreaBox *box)
{
GtkCellAreaBoxPrivate *priv = box->priv;
- CellGroup *group;
- GList *group_list;
- GtkRequestedSize *orientation_sizes;
- gint n_groups, n_expand_groups, i;
- gint avail_size = size;
- gint extra_size, extra_extra;
- gint position;
- GtkCellAreaBoxAllocation *allocs;
-
- n_expand_groups = count_expand_groups (box);
-
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- orientation_sizes = gtk_cell_area_box_iter_get_widths (iter, &n_groups);
- else
- orientation_sizes = gtk_cell_area_box_iter_get_heights (iter, &n_groups);
-
- /* First start by naturally allocating space among groups of cells */
- avail_size -= (n_groups - 1) * priv->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);
+ GSList *l;
- /* Calculate/distribute expand for groups */
- if (n_expand_groups > 0)
+ /* When the box's groups are reconstructed, iters need to
+ * be reinitialized.
+ */
+ for (l = priv->iters; l; l = l->next)
{
- extra_size = avail_size / n_expand_groups;
- extra_extra = avail_size % n_expand_groups;
+ GtkCellAreaBoxIter *iter = l->data;
+
+ init_iter_group (box, iter);
}
- else
- extra_size = extra_extra = 0;
+}
- allocs = g_new (GtkCellAreaBoxAllocation, n_groups);
+static void
+flush_iters (GtkCellAreaBox *box)
+{
+ GtkCellAreaBoxPrivate *priv = box->priv;
+ GSList *l;
- for (position = 0, group_list = priv->groups; group_list; group_list = group_list->next)
+ /* When the box layout changes, iters need to
+ * be flushed and sizes for the box get requested again
+ */
+ for (l = priv->iters; l; l = l->next)
{
- group = group_list->data;
-
- allocs[group->id].position = position;
- allocs[group->id].size = orientation_sizes[group->id].minimum_size;
-
- if (group->expand)
- {
- allocs[group->id].size += extra_size;
- if (extra_extra)
- {
- allocs[group->id].size++;
- extra_extra--;
- }
- }
+ GtkCellAreaIter *iter = l->data;
- position += allocs[group->id].size;
- position += priv->spacing;
+ gtk_cell_area_iter_flush (iter);
}
-
- g_free (orientation_sizes);
-
- if (n_allocs)
- *n_allocs = n_groups;
-
- return allocs;
}
-
/*************************************************************
* GObjectClass *
*************************************************************/
@@ -519,6 +489,12 @@ gtk_cell_area_box_set_property (GObject *object,
switch (prop_id)
{
+ case PROP_ORIENTATION:
+ box->priv->orientation = g_value_get_enum (value);
+
+ /* Notify that size needs to be requested again */
+ flush_iters (box);
+ break;
case PROP_SPACING:
gtk_cell_area_box_set_spacing (box, g_value_get_int (value));
break;
@@ -538,6 +514,9 @@ gtk_cell_area_box_get_property (GObject *object,
switch (prop_id)
{
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, box->priv->orientation);
+ break;
case PROP_SPACING:
g_value_set_int (value, gtk_cell_area_box_get_spacing (box));
break;
@@ -582,8 +561,8 @@ gtk_cell_area_box_remove (GtkCellArea *area,
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
- /* Notify that size needs to be requested again */
- flush_iters (box);
+ /* Reinitialize groups on iters */
+ init_iter_groups (box);
}
else
g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
@@ -640,6 +619,9 @@ gtk_cell_area_box_create_iter (GtkCellArea *area)
g_object_weak_ref (G_OBJECT (iter), (GWeakNotify)iter_weak_notify, box);
+ /* Tell the new group about our cell layout */
+ init_iter_group (box, GTK_CELL_AREA_BOX_ITER (iter));
+
return iter;
}
@@ -1141,8 +1123,8 @@ gtk_cell_area_box_layout_reorder (GtkCellLayout *cell_layout,
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
- /* Notify that size needs to be requested again */
- flush_iters (box);
+ /* Reinitialize groups on iters */
+ init_iter_groups (box);
}
}
@@ -1185,8 +1167,8 @@ gtk_cell_area_box_pack_start (GtkCellAreaBox *box,
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
- /* Notify that size needs to be requested again */
- flush_iters (box);
+ /* Reinitialize groups on iters */
+ init_iter_groups (box);
}
void
@@ -1219,8 +1201,8 @@ gtk_cell_area_box_pack_end (GtkCellAreaBox *box,
g_list_free (priv->groups);
priv->groups = construct_cell_groups (box);
- /* Notify that size needs to be requested again */
- flush_iters (box);
+ /* Reinitialize groups on iters */
+ init_iter_groups (box);
}
gint
diff --git a/gtk/gtkcellareaboxiter.c b/gtk/gtkcellareaboxiter.c
index 779315c..d16aa96 100644
--- a/gtk/gtkcellareaboxiter.c
+++ b/gtk/gtkcellareaboxiter.c
@@ -49,22 +49,25 @@ static void gtk_cell_area_box_iter_allocate_width (GtkCel
static void gtk_cell_area_box_iter_allocate_height (GtkCellAreaIter *iter,
gint height);
-
+static void free_cache_array (GArray *array);
/* CachedSize management */
typedef struct {
- gint min_size;
- gint nat_size;
+ gint min_size;
+ gint nat_size;
} CachedSize;
-static CachedSize *cached_size_new (gint min_size, gint nat_size);
-static void cached_size_free (CachedSize *size);
+typedef struct {
+ gint min_size;
+ gint nat_size;
+ gboolean expand;
+} BaseSize;
struct _GtkCellAreaBoxIterPrivate
{
/* Table of per renderer CachedSizes */
- GHashTable *base_widths;
- GHashTable *base_heights;
+ GArray *base_widths;
+ GArray *base_heights;
/* Table of per height/width hash tables of per renderer CachedSizes */
GHashTable *widths;
@@ -80,6 +83,12 @@ struct _GtkCellAreaBoxIterPrivate
G_DEFINE_TYPE (GtkCellAreaBoxIter, gtk_cell_area_box_iter, GTK_TYPE_CELL_AREA_ITER);
static void
+free_cache_array (GArray *array)
+{
+ g_array_free (array, TRUE);
+}
+
+static void
gtk_cell_area_box_iter_init (GtkCellAreaBoxIter *box_iter)
{
GtkCellAreaBoxIterPrivate *priv;
@@ -89,15 +98,13 @@ gtk_cell_area_box_iter_init (GtkCellAreaBoxIter *box_iter)
GtkCellAreaBoxIterPrivate);
priv = box_iter->priv;
- priv->base_widths = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)cached_size_free);
- priv->base_heights = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)cached_size_free);
+ 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)g_hash_table_destroy);
+ NULL, (GDestroyNotify)free_cache_array);
priv->heights = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)g_hash_table_destroy);
+ NULL, (GDestroyNotify)free_cache_array);
priv->alloc_width = 0;
priv->alloc_height = 0;
@@ -132,27 +139,6 @@ gtk_cell_area_box_iter_class_init (GtkCellAreaBoxIterClass *class)
}
/*************************************************************
- * Cached Sizes *
- *************************************************************/
-static CachedSize *
-cached_size_new (gint min_size,
- gint nat_size)
-{
- CachedSize *size = g_slice_new (CachedSize);
-
- size->min_size = min_size;
- size->nat_size = nat_size;
-
- return size;
-}
-
-static void
-cached_size_free (CachedSize *size)
-{
- g_slice_free (CachedSize, size);
-}
-
-/*************************************************************
* GObjectClass *
*************************************************************/
static void
@@ -161,8 +147,8 @@ gtk_cell_area_box_iter_finalize (GObject *object)
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (object);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
- g_hash_table_destroy (priv->base_widths);
- g_hash_table_destroy (priv->base_heights);
+ 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);
@@ -179,8 +165,15 @@ gtk_cell_area_box_iter_flush_preferred_width (GtkCellAreaIter *iter)
{
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
-
- g_hash_table_remove_all (priv->base_widths);
+ 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_ITER_GET_CLASS
(gtk_cell_area_box_iter_parent_class)->flush_preferred_width (iter);
@@ -208,8 +201,15 @@ gtk_cell_area_box_iter_flush_preferred_height (GtkCellAreaIter *iter)
{
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
-
- g_hash_table_remove_all (priv->base_heights);
+ 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_ITER_GET_CLASS
(gtk_cell_area_box_iter_parent_class)->flush_preferred_height (iter);
@@ -243,49 +243,43 @@ gtk_cell_area_box_iter_flush_allocation (GtkCellAreaIter *iter)
priv->n_orientation_allocs = 0;
}
-typedef struct {
- gint min_size;
- gint nat_size;
- gint spacing;
-} AccumData;
-
-static void
-sum_base_size (gpointer group_id,
- CachedSize *size,
- AccumData *accum)
-{
- if (accum->min_size > 0)
- {
- accum->min_size += accum->spacing;
- accum->nat_size += accum->spacing;
- }
-
- accum->min_size += size->min_size;
- accum->nat_size += size->nat_size;
-}
-
-static void
-sum_for_size (gpointer group_id,
- CachedSize *size,
- AccumData *accum)
-{
- accum->min_size = MAX (accum->min_size, size->min_size);
- accum->nat_size = MAX (accum->nat_size, size->nat_size);
-}
-
static void
gtk_cell_area_box_iter_sum_preferred_width (GtkCellAreaIter *iter)
{
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
GtkCellArea *area;
- AccumData accum = { 0, };
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
- area = gtk_cell_area_iter_get_area (iter);
- accum.spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ area = gtk_cell_area_iter_get_area (iter);
+ 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)
+ {
+ if (min_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);
+ }
+ }
- g_hash_table_foreach (priv->base_widths, (GHFunc)sum_base_size, &accum);
- gtk_cell_area_iter_push_preferred_width (iter, accum.min_size, accum.nat_size);
+ gtk_cell_area_iter_push_preferred_width (iter, min_size, nat_size);
}
static void
@@ -294,15 +288,43 @@ gtk_cell_area_box_iter_sum_preferred_height_for_width (GtkCellAreaIter *iter,
{
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
- GHashTable *group_table;
- AccumData accum = { 0, };
+ GArray *group_array;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
- group_table = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (width));
+ group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (width));
- if (group_table)
+ if (group_array)
{
- g_hash_table_foreach (priv->base_widths, (GHFunc)sum_for_size, &accum);
- gtk_cell_area_iter_push_preferred_height_for_width (iter, width, accum.min_size, accum.nat_size);
+ area = gtk_cell_area_iter_get_area (iter);
+ 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)
+ {
+ if (min_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_iter_push_preferred_height_for_width (iter, width, min_size, nat_size);
}
}
@@ -312,13 +334,37 @@ gtk_cell_area_box_iter_sum_preferred_height (GtkCellAreaIter *iter)
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
GtkCellArea *area;
- AccumData accum = { 0, };
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
- area = gtk_cell_area_iter_get_area (iter);
- accum.spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ area = gtk_cell_area_iter_get_area (iter);
+ spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
- g_hash_table_foreach (priv->base_heights, (GHFunc)sum_base_size, &accum);
- gtk_cell_area_iter_push_preferred_width (iter, accum.min_size, accum.nat_size);
+ for (i = 0; i < priv->base_heights->len; i++)
+ {
+ BaseSize *size = &g_array_index (priv->base_heights, BaseSize, i);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ if (min_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_iter_push_preferred_height (iter, min_size, nat_size);
}
static void
@@ -327,18 +373,118 @@ gtk_cell_area_box_iter_sum_preferred_width_for_height (GtkCellAreaIter *iter,
{
GtkCellAreaBoxIter *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
GtkCellAreaBoxIterPrivate *priv = box_iter->priv;
- GHashTable *group_table;
- AccumData accum = { 0, };
+ GArray *group_array;
+ GtkCellArea *area;
+ GtkOrientation orientation;
+ gint spacing, i;
+ gint min_size = 0, nat_size = 0;
- group_table = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (height));
+ group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (height));
- if (group_table)
+ if (group_array)
{
- g_hash_table_foreach (priv->base_widths, (GHFunc)sum_for_size, &accum);
- gtk_cell_area_iter_push_preferred_width_for_height (iter, height, accum.min_size, accum.nat_size);
+ area = gtk_cell_area_iter_get_area (iter);
+ 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)
+ {
+ if (min_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_iter_push_preferred_width_for_height (iter, height, min_size, nat_size);
}
}
+static GtkCellAreaBoxAllocation *
+allocate_for_orientation (GtkCellAreaBoxIter *iter,
+ GtkOrientation orientation,
+ gint spacing,
+ gint size)
+{
+ GtkCellAreaBoxIterPrivate *priv = iter->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;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ orientation_sizes = gtk_cell_area_box_iter_get_widths (iter, &n_groups);
+ else
+ orientation_sizes = gtk_cell_area_box_iter_get_heights (iter, &n_groups);
+
+ /* Count groups that expand */
+ for (i = 0; i < n_groups; i++)
+ {
+ BaseSize *size = &g_array_index (priv->base_widths, BaseSize, i);
+
+ 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].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;
+ }
+
+ g_free (orientation_sizes);
+
+ return allocs;
+}
+
static void
gtk_cell_area_box_iter_allocate_width (GtkCellAreaIter *iter,
gint width)
@@ -353,11 +499,10 @@ gtk_cell_area_box_iter_allocate_width (GtkCellAreaIter *iter,
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- g_free (priv->orientation_allocs);
+ gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
- priv->orientation_allocs =
- gtk_cell_area_box_allocate (GTK_CELL_AREA_BOX (area), box_iter, width,
- &priv->n_orientation_allocs);
+ g_free (priv->orientation_allocs);
+ priv->orientation_allocs = allocate_for_orientation (box_iter, orientation, spacing, width);
}
GTK_CELL_AREA_ITER_GET_CLASS (iter)->allocate_width (iter, width);
@@ -377,11 +522,10 @@ gtk_cell_area_box_iter_allocate_height (GtkCellAreaIter *iter,
if (orientation == GTK_ORIENTATION_VERTICAL)
{
- g_free (priv->orientation_allocs);
+ gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
- priv->orientation_allocs =
- gtk_cell_area_box_allocate (GTK_CELL_AREA_BOX (area), box_iter, height,
- &priv->n_orientation_allocs);
+ g_free (priv->orientation_allocs);
+ priv->orientation_allocs = allocate_for_orientation (box_iter, orientation, spacing, height);
}
GTK_CELL_AREA_ITER_GET_CLASS (iter)->allocate_height (iter, height);
@@ -390,188 +534,179 @@ gtk_cell_area_box_iter_allocate_height (GtkCellAreaIter *iter,
/*************************************************************
* API *
*************************************************************/
+void
+gtk_cell_area_box_init_groups (GtkCellAreaBoxIter *box_iter,
+ guint n_groups,
+ gboolean *expand_groups)
+{
+ GtkCellAreaBoxIterPrivate *priv;
+ gint i;
+
+ g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
+ 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_iter_flush (GTK_CELL_AREA_ITER (box_iter));
+
+ priv = box_iter->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_iter_push_group_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint minimum_width,
gint natural_width)
{
GtkCellAreaBoxIterPrivate *priv;
- CachedSize *size;
+ BaseSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- size = g_hash_table_lookup (priv->base_widths, GINT_TO_POINTER (group_id));
+ g_return_if_fail (group_idx < priv->base_widths->len);
- if (!size)
- {
- size = cached_size_new (minimum_width, natural_width);
- g_hash_table_insert (priv->base_widths, GINT_TO_POINTER (group_id), size);
- }
- else
- {
- 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, 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_iter_push_group_height_for_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_width,
gint minimum_height,
gint natural_height)
{
GtkCellAreaBoxIterPrivate *priv;
- GHashTable *group_table;
+ GArray *group_array;
CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- group_table = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+ g_return_if_fail (group_idx < priv->base_widths->len);
- if (!group_table)
+ group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+ if (!group_array)
{
- group_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)cached_size_free);
+ 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_table);
+ g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), group_array);
}
- size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
-
- if (!size)
- {
- size = cached_size_new (minimum_height, natural_height);
- g_hash_table_insert (group_table, GINT_TO_POINTER (group_id), size);
- }
- else
- {
- size->min_size = MAX (size->min_size, minimum_height);
- size->nat_size = MAX (size->nat_size, natural_height);
- }
+ 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_iter_push_group_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint minimum_height,
gint natural_height)
{
GtkCellAreaBoxIterPrivate *priv;
- CachedSize *size;
+ BaseSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- size = g_hash_table_lookup (priv->base_heights, GINT_TO_POINTER (group_id));
+ g_return_if_fail (group_idx < priv->base_heights->len);
- if (!size)
- {
- size = cached_size_new (minimum_height, natural_height);
- g_hash_table_insert (priv->base_widths, GINT_TO_POINTER (group_id), size);
- }
- else
- {
- 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, 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_iter_push_group_width_for_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_height,
gint minimum_width,
gint natural_width)
{
GtkCellAreaBoxIterPrivate *priv;
- GHashTable *group_table;
+ GArray *group_array;
CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- group_table = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+ g_return_if_fail (group_idx < priv->base_widths->len);
- if (!group_table)
+ group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+ if (!group_array)
{
- group_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)cached_size_free);
+ 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_table);
+ g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), group_array);
}
- size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
-
- if (!size)
- {
- size = cached_size_new (minimum_width, natural_width);
- g_hash_table_insert (group_table, GINT_TO_POINTER (group_id), size);
- }
- else
- {
- size->min_size = MAX (size->min_size, minimum_width);
- size->nat_size = MAX (size->nat_size, natural_width);
- }
+ 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_iter_get_group_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint *minimum_width,
gint *natural_width)
{
GtkCellAreaBoxIterPrivate *priv;
- CachedSize *size;
+ BaseSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- size = g_hash_table_lookup (priv->base_widths, GINT_TO_POINTER (group_id));
-
- if (size)
- {
- if (minimum_width)
- *minimum_width = size->min_size;
+ g_return_if_fail (group_idx < priv->base_widths->len);
- if (natural_width)
- *natural_width = size->nat_size;
- }
- else
- {
- if (minimum_width)
- *minimum_width = -1;
+ size = &g_array_index (priv->base_widths, BaseSize, group_idx);
- if (natural_width)
- *natural_width = -1;
- }
+ if (minimum_width)
+ *minimum_width = size->min_size;
+
+ if (natural_width)
+ *natural_width = size->nat_size;
}
void
gtk_cell_area_box_iter_get_group_height_for_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_width,
gint *minimum_height,
gint *natural_height)
{
GtkCellAreaBoxIterPrivate *priv;
- GHashTable *group_table;
- CachedSize *size = NULL;
+ GArray *group_array;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- group_table = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+ g_return_if_fail (group_idx < priv->base_widths->len);
- if (group_table)
- size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
+ group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
- if (size)
+ if (group_array)
{
+ CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
+
if (minimum_height)
*minimum_height = size->min_size;
@@ -590,57 +725,48 @@ gtk_cell_area_box_iter_get_group_height_for_width (GtkCellAreaBoxIter *box_iter,
void
gtk_cell_area_box_iter_get_group_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint *minimum_height,
gint *natural_height)
{
GtkCellAreaBoxIterPrivate *priv;
- CachedSize *size;
+ BaseSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- size = g_hash_table_lookup (priv->base_heights, GINT_TO_POINTER (group_id));
+ g_return_if_fail (group_idx < priv->base_heights->len);
- if (size)
- {
- if (minimum_height)
- *minimum_height = size->min_size;
+ size = &g_array_index (priv->base_heights, BaseSize, group_idx);
- if (natural_height)
- *natural_height = size->nat_size;
- }
- else
- {
- if (minimum_height)
- *minimum_height = -1;
-
- if (natural_height)
- *natural_height = -1;
- }
+ if (minimum_height)
+ *minimum_height = size->min_size;
+
+ if (natural_height)
+ *natural_height = size->nat_size;
}
void
gtk_cell_area_box_iter_get_group_width_for_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_height,
gint *minimum_width,
gint *natural_width)
{
GtkCellAreaBoxIterPrivate *priv;
- GHashTable *group_table;
- CachedSize *size = NULL;
+ GArray *group_array;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter));
priv = box_iter->priv;
- group_table = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+ g_return_if_fail (group_idx < priv->base_widths->len);
- if (group_table)
- size = g_hash_table_lookup (group_table, GINT_TO_POINTER (group_id));
+ group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
- if (size)
+ if (group_array)
{
+ CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
+
if (minimum_width)
*minimum_width = size->min_size;
@@ -657,33 +783,31 @@ gtk_cell_area_box_iter_get_group_width_for_height (GtkCellAreaBoxIter *box_iter,
}
}
-static void
-fill_requested_sizes (gpointer group_id_ptr,
- CachedSize *cached_size,
- GtkRequestedSize *requested)
-{
- gint group_id = GPOINTER_TO_INT (group_id_ptr);
-
- requested[group_id].data = group_id_ptr;
- requested[group_id].minimum_size = cached_size->min_size;
- requested[group_id].natural_size = cached_size->nat_size;
-}
-
GtkRequestedSize *
gtk_cell_area_box_iter_get_widths (GtkCellAreaBoxIter *box_iter,
gint *n_widths)
{
GtkCellAreaBoxIterPrivate *priv;
GtkRequestedSize *widths;
+ BaseSize *size;
+ gint i;
g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter), NULL);
priv = box_iter->priv;
- *n_widths = g_hash_table_size (priv->widths);
- widths = g_new (GtkRequestedSize, *n_widths);
+ widths = g_new (GtkRequestedSize, priv->base_widths->len);
+
+ for (i = 0; i < priv->base_widths->len; i++)
+ {
+ size = &g_array_index (priv->base_widths, BaseSize, i);
+ widths[i].data = GINT_TO_POINTER (i);
+ widths[i].minimum_size = size->min_size;
+ widths[i].natural_size = size->nat_size;
+ }
- g_hash_table_foreach (priv->widths, (GHFunc)fill_requested_sizes, widths);
+ if (n_widths)
+ *n_widths = priv->base_widths->len;
return widths;
}
@@ -694,15 +818,25 @@ gtk_cell_area_box_iter_get_heights (GtkCellAreaBoxIter *box_iter,
{
GtkCellAreaBoxIterPrivate *priv;
GtkRequestedSize *heights;
+ BaseSize *size;
+ gint i;
g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter), NULL);
priv = box_iter->priv;
- *n_heights = g_hash_table_size (priv->heights);
- heights = g_new (GtkRequestedSize, *n_heights);
+ heights = g_new (GtkRequestedSize, priv->base_heights->len);
+
+ for (i = 0; i < priv->base_heights->len; i++)
+ {
+ size = &g_array_index (priv->base_heights, BaseSize, i);
+ heights[i].data = GINT_TO_POINTER (i);
+ heights[i].minimum_size = size->min_size;
+ heights[i].natural_size = size->nat_size;
+ }
- g_hash_table_foreach (priv->heights, (GHFunc)fill_requested_sizes, heights);
+ if (n_heights)
+ *n_heights = priv->base_heights->len;
return heights;
}
diff --git a/gtk/gtkcellareaboxiter.h b/gtk/gtkcellareaboxiter.h
index 631a67c..73b4166 100644
--- a/gtk/gtkcellareaboxiter.h
+++ b/gtk/gtkcellareaboxiter.h
@@ -62,48 +62,53 @@ struct _GtkCellAreaBoxIterClass
GType gtk_cell_area_box_iter_get_type (void) G_GNUC_CONST;
+/* Initialize group array dimensions */
+void gtk_cell_area_box_init_groups (GtkCellAreaBoxIter *box_iter,
+ guint n_groups,
+ gboolean *expand_groups);
+
/* Update cell-group sizes */
void gtk_cell_area_box_iter_push_group_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint minimum_width,
gint natural_width);
void gtk_cell_area_box_iter_push_group_height_for_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_width,
gint minimum_height,
gint natural_height);
void gtk_cell_area_box_iter_push_group_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint minimum_height,
gint natural_height);
void gtk_cell_area_box_iter_push_group_width_for_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_height,
gint minimum_width,
gint natural_width);
/* Fetch cell-group sizes */
void gtk_cell_area_box_iter_get_group_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint *minimum_width,
gint *natural_width);
void gtk_cell_area_box_iter_get_group_height_for_width (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_width,
gint *minimum_height,
gint *natural_height);
void gtk_cell_area_box_iter_get_group_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint *minimum_height,
gint *natural_height);
void gtk_cell_area_box_iter_get_group_width_for_height (GtkCellAreaBoxIter *box_iter,
- gint group_id,
+ gint group_idx,
gint for_height,
gint *minimum_width,
gint *natural_width);
@@ -119,11 +124,6 @@ typedef struct {
gint size;
} GtkCellAreaBoxAllocation;
-GtkCellAreaBoxAllocation *gtk_cell_area_box_allocate (GtkCellAreaBox *box,
- GtkCellAreaBoxIter *iter,
- gint size,
- gint *n_allocs);
-
G_CONST_RETURN GtkCellAreaBoxAllocation *
gtk_cell_area_box_iter_get_orientation_allocs (GtkCellAreaBoxIter *iter,
gint *n_allocs);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]