From e494f102cfcd3798797cfc2ecc346da433a000ef Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Sun, 31 Oct 2010 13:06:10 +0900 Subject: [PATCH] Cleaned up GtkCellAreaIter implementation to use arrays to store grouped cell information. --- gtk/gtkcellareabox.c | 180 ++++++------ gtk/gtkcellareaboxiter.c | 602 ++++++++++++++++++++++++--------------- gtk/gtkcellareaboxiter.h | 26 +- 3 files changed, 462 insertions(+), 346 deletions(-) diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c index 273da69700..a341dd7f08 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 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 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); -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); struct _GtkCellAreaBoxPrivate { @@ -387,14 +391,53 @@ 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; priv->iters = g_slist_remove (priv->iters, dead_iter); } +static void +init_iter_group (GtkCellAreaBox *box, + GtkCellAreaBoxIter *iter) +{ + GtkCellAreaBoxPrivate *priv = box->priv; + gint n_groups, *expand_groups, i; + GList *l; + + 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++) + { + CellGroup *group = l->data; + + expand_groups[i] = group->expand; + } + + gtk_cell_area_box_init_groups (iter, n_groups, expand_groups); + g_free (expand_groups); +} + +static void +init_iter_groups (GtkCellAreaBox *box) +{ + GtkCellAreaBoxPrivate *priv = box->priv; + GSList *l; + + /* When the box's groups are reconstructed, iters need to + * be reinitialized. + */ + for (l = priv->iters; l; l = l->next) + { + GtkCellAreaBoxIter *iter = l->data; + + init_iter_group (box, iter); + } +} + static void flush_iters (GtkCellAreaBox *box) { @@ -412,79 +455,6 @@ flush_iters (GtkCellAreaBox *box) } } - -/* 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) -{ - 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); - - /* 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, group_list = priv->groups; group_list; group_list = group_list->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--; - } - } - - position += allocs[group->id].size; - position += priv->spacing; - } - - 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 779315c178..d16aa968db 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; @@ -79,6 +82,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) { @@ -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; @@ -131,27 +138,6 @@ gtk_cell_area_box_iter_class_init (GtkCellAreaBoxIterClass *class) g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxIterPrivate)); } -/************************************************************* - * 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 * *************************************************************/ @@ -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)); - 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); + 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); + } + } + + 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_iter_push_group_width (GtkCellAreaBoxIter *box_iter, - gint group_id, - gint minimum_width, - gint natural_width) +gtk_cell_area_box_init_groups (GtkCellAreaBoxIter *box_iter, + guint n_groups, + gboolean *expand_groups) { GtkCellAreaBoxIterPrivate *priv; - CachedSize *size; + 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; - size = g_hash_table_lookup (priv->base_widths, GINT_TO_POINTER (group_id)); + g_array_set_size (priv->base_widths, n_groups); + g_array_set_size (priv->base_heights, n_groups); - if (!size) + /* Now set the expand info */ + for (i = 0; i < n_groups; i++) { - 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); + 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_idx, + gint minimum_width, + gint natural_width) +{ + GtkCellAreaBoxIterPrivate *priv; + BaseSize *size; + + g_return_if_fail (GTK_IS_CELL_AREA_BOX_ITER (box_iter)); + + priv = box_iter->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_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)); + g_return_if_fail (group_idx < priv->base_widths->len); - if (size) - { - if (minimum_width) - *minimum_width = size->min_size; + size = &g_array_index (priv->base_widths, BaseSize, group_idx); - if (natural_width) - *natural_width = size->nat_size; - } - else - { - if (minimum_width) - *minimum_width = -1; - - 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); - g_hash_table_foreach (priv->widths, (GHFunc)fill_requested_sizes, widths); + 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; + } + + 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); - g_hash_table_foreach (priv->heights, (GHFunc)fill_requested_sizes, heights); + 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; + } + + if (n_heights) + *n_heights = priv->base_heights->len; return heights; } diff --git a/gtk/gtkcellareaboxiter.h b/gtk/gtkcellareaboxiter.h index 631a67cd90..73b4166ec3 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);