Cleaned up GtkCellAreaIter implementation to use arrays to store grouped cell information.

This commit is contained in:
Tristan Van Berkom 2010-10-31 13:06:10 +09:00
parent b12e7a8115
commit e494f102cf
3 changed files with 462 additions and 346 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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);