Added apis to GtkCellArea for GtkIconView purposes.

Added a few apis,

  - GtkCellAreaContext get_preferred_height_for_width &
    width for height apis and vfuncs, this lets the icon view
    request the collective (and aligned) height for width for
    a said row.

  - gtk_cell_area_copy_context() this creates a duplicate of
    an already created and requested context, this way the icon
    view uses a global context to request the widths of all rows
    and then makes a copy with all the stored alignments and
    uses a separate copy to calculate the height and alignments
    of each row separately.
This commit is contained in:
Tristan Van Berkom 2010-12-13 00:18:00 +09:00
parent ff39c76bfd
commit 0431dd67f8
7 changed files with 277 additions and 30 deletions

View File

@ -1924,6 +1924,46 @@ gtk_cell_area_create_context (GtkCellArea *area)
return NULL;
}
/**
* gtk_cell_area_copy_context:
* @area: a #GtkCellArea
* @context: the #GtkCellAreaContext to copy
*
* This is sometimes needed for cases where rows need to share
* alignments in one orientation but may be separately grouped
* in the opposing orientation.
*
* For instance, #GtkIconView creates all icons (rows) to have
* the same width and the cells theirin to have the same
* horizontal alignments. However each row of icons may have
* a separate collective height. #GtkIconView uses this to
* request the heights of each row based on a context which
* was already used to request all the row widths that are
* to be displayed.
*
* Return value: (transfer full): a newly created #GtkCellAreaContext copy of @context.
*
* Since: 3.0
*/
GtkCellAreaContext *
gtk_cell_area_copy_context (GtkCellArea *area,
GtkCellAreaContext *context)
{
GtkCellAreaClass *class;
g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
class = GTK_CELL_AREA_GET_CLASS (area);
if (class->copy_context)
return class->copy_context (area, context);
g_warning ("GtkCellAreaClass::copy_context not implemented for `%s'",
g_type_name (G_TYPE_FROM_INSTANCE (area)));
return NULL;
}
/**
* gtk_cell_area_get_request_mode:

View File

@ -202,6 +202,8 @@ struct _GtkCellAreaClass
/* Geometry */
GtkCellAreaContext *(* create_context) (GtkCellArea *area);
GtkCellAreaContext *(* copy_context) (GtkCellArea *area,
GtkCellAreaContext *context);
GtkSizeRequestMode (* get_request_mode) (GtkCellArea *area);
void (* get_preferred_width) (GtkCellArea *area,
GtkCellAreaContext *context,
@ -316,6 +318,8 @@ GtkCellRenderer *gtk_cell_area_get_cell_at_position (GtkCellArea
/* Geometry */
GtkCellAreaContext *gtk_cell_area_create_context (GtkCellArea *area);
GtkCellAreaContext *gtk_cell_area_copy_context (GtkCellArea *area,
GtkCellAreaContext *context);
GtkSizeRequestMode gtk_cell_area_get_request_mode (GtkCellArea *area);
void gtk_cell_area_get_preferred_width (GtkCellArea *area,
GtkCellAreaContext *context,

View File

@ -92,6 +92,8 @@ static void gtk_cell_area_box_get_cell_property (GtkCellArea
GValue *value,
GParamSpec *pspec);
static GtkCellAreaContext *gtk_cell_area_box_create_context (GtkCellArea *area);
static GtkCellAreaContext *gtk_cell_area_box_copy_context (GtkCellArea *area,
GtkCellAreaContext *context);
static GtkSizeRequestMode gtk_cell_area_box_get_request_mode (GtkCellArea *area);
static void gtk_cell_area_box_get_preferred_width (GtkCellArea *area,
GtkCellAreaContext *context,
@ -273,6 +275,7 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
area_class->get_cell_property = gtk_cell_area_box_get_cell_property;
area_class->create_context = gtk_cell_area_box_create_context;
area_class->copy_context = gtk_cell_area_box_copy_context;
area_class->get_request_mode = gtk_cell_area_box_get_request_mode;
area_class->get_preferred_width = gtk_cell_area_box_get_preferred_width;
area_class->get_preferred_height = gtk_cell_area_box_get_preferred_height;
@ -1301,6 +1304,23 @@ gtk_cell_area_box_create_context (GtkCellArea *area)
return context;
}
static GtkCellAreaContext *
gtk_cell_area_box_copy_context (GtkCellArea *area,
GtkCellAreaContext *context)
{
GtkCellAreaBox *box = GTK_CELL_AREA_BOX (area);
GtkCellAreaBoxPrivate *priv = box->priv;
GtkCellAreaContext *copy =
(GtkCellAreaContext *)gtk_cell_area_box_context_copy (GTK_CELL_AREA_BOX (area),
GTK_CELL_AREA_BOX_CONTEXT (context));
priv->contexts = g_slist_prepend (priv->contexts, copy);
g_object_weak_ref (G_OBJECT (copy), (GWeakNotify)context_weak_notify, box);
return copy;
}
static GtkSizeRequestMode
gtk_cell_area_box_get_request_mode (GtkCellArea *area)
{

View File

@ -35,10 +35,23 @@ static void gtk_cell_area_box_context_reset (GtkCellAreaCon
static void gtk_cell_area_box_context_allocate (GtkCellAreaContext *context,
gint width,
gint height);
static void gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
gint width,
gint *minimum_height,
gint *natural_height);
static void gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
gint height,
gint *minimum_width,
gint *natural_width);
/* Internal functions */
static void gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
GtkOrientation orientation);
static void gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
GtkOrientation orientation,
gint for_size,
gint *minimum_size,
gint *natural_size);
static void free_cache_array (GArray *array);
static GArray *group_array_new (GtkCellAreaBoxContext *context);
static GArray *get_array (GtkCellAreaBoxContext *context,
@ -190,8 +203,10 @@ gtk_cell_area_box_context_class_init (GtkCellAreaBoxContextClass *class)
/* GObjectClass */
object_class->finalize = gtk_cell_area_box_context_finalize;
context_class->reset = gtk_cell_area_box_context_reset;
context_class->allocate = gtk_cell_area_box_context_allocate;
context_class->reset = gtk_cell_area_box_context_reset;
context_class->allocate = gtk_cell_area_box_context_allocate;
context_class->get_preferred_height_for_width = gtk_cell_area_box_context_get_preferred_height_for_width;
context_class->get_preferred_width_for_height = gtk_cell_area_box_context_get_preferred_width_for_height;
g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxContextPrivate));
}
@ -402,7 +417,10 @@ gtk_cell_area_box_context_allocate (GtkCellAreaContext *context,
static void
gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
GtkOrientation orientation)
GtkOrientation orientation,
gint for_size,
gint *minimum_size,
gint *natural_size)
{
GtkCellArea *area;
GtkOrientation box_orientation;
@ -413,7 +431,7 @@ gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
area = gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (context));
spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
box_orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
array = get_array (context, orientation, -1);
array = get_array (context, orientation, for_size);
for (i = 0; i < array->len; i++)
{
@ -440,15 +458,100 @@ gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
}
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
else
gtk_cell_area_context_push_preferred_height (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
if (for_size < 0)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
else
gtk_cell_area_context_push_preferred_height (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
}
if (minimum_size)
*minimum_size = min_size;
if (natural_size)
*natural_size = nat_size;
}
static void
gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
gint width,
gint *minimum_height,
gint *natural_height)
{
gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_VERTICAL,
width, minimum_height, natural_height);
}
static void
gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
gint height,
gint *minimum_width,
gint *natural_width)
{
gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_HORIZONTAL,
height, minimum_width, natural_width);
}
/*************************************************************
* API *
*************************************************************/
static void
copy_size_array (GArray *src_array,
GArray *dest_array)
{
gint i;
for (i = 0; i < src_array->len; i++)
{
CachedSize *src = &g_array_index (src_array, CachedSize, i);
CachedSize *dest = &g_array_index (dest_array, CachedSize, i);
memcpy (dest, src, sizeof (CachedSize));
}
}
static void
for_size_copy (gpointer key,
GArray *size_array,
GHashTable *dest_hash)
{
GArray *new_array;
new_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
g_array_set_size (new_array, size_array->len);
copy_size_array (size_array, new_array);
g_hash_table_insert (dest_hash, key, new_array);
}
GtkCellAreaBoxContext *
gtk_cell_area_box_context_copy (GtkCellAreaBox *box,
GtkCellAreaBoxContext *box_context)
{
GtkCellAreaBoxContext *context;
context = g_object_new (GTK_TYPE_CELL_AREA_BOX_CONTEXT,
"area", box, NULL);
gtk_cell_area_box_init_groups (context,
box_context->priv->base_widths->len,
box_context->priv->expand);
/* Copy all the arrays */
copy_size_array (box_context->priv->base_widths,
context->priv->base_widths);
copy_size_array (box_context->priv->base_heights,
context->priv->base_heights);
g_hash_table_foreach (box_context->priv->heights,
(GHFunc)for_size_copy, context->priv->heights);
g_hash_table_foreach (box_context->priv->widths,
(GHFunc)for_size_copy, context->priv->widths);
return context;
}
void
gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
guint n_groups,
@ -500,7 +603,7 @@ gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
}
if (grew)
gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL);
gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL, -1, NULL, NULL);
}
void
@ -559,7 +662,7 @@ gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
}
if (grew)
gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL);
gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL, -1, NULL, NULL);
}
void

View File

@ -62,6 +62,10 @@ struct _GtkCellAreaBoxContextClass
GType gtk_cell_area_box_context_get_type (void) G_GNUC_CONST;
/* Create a duplicate of the context */
GtkCellAreaBoxContext *gtk_cell_area_box_context_copy (GtkCellAreaBox *box,
GtkCellAreaBoxContext *box_context);
/* Initialize group array dimensions */
void gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
guint n_groups,

View File

@ -489,6 +489,66 @@ gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
*natural_height = priv->nat_height;
}
/**
* gtk_cell_area_context_get_preferred_height_for_width:
* @context: a #GtkCellAreaContext
* @width: a proposed width for allocation
* @minimum_height: (out) (allow-none): location to store the minimum height, or %NULL
* @natural_height: (out) (allow-none): location to store the natural height, or %NULL
*
* Gets the accumulative preferred height for @width for all rows which have been
* requested for the same said @width with this context.
*
* After gtk_cell_area_context_reset() is called and/or before ever requesting
* the size of a #GtkCellArea, the returned values are -1.
*
* Since: 3.0
*/
void
gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
gint width,
gint *minimum_height,
gint *natural_height)
{
g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width)
GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width (context,
width,
minimum_height,
natural_height);
}
/**
* gtk_cell_area_context_get_preferred_width_for_height:
* @context: a #GtkCellAreaContext
* @height: a proposed height for allocation
* @minimum_width: (out) (allow-none): location to store the minimum width, or %NULL
* @natural_width: (out) (allow-none): location to store the natural width, or %NULL
*
* Gets the accumulative preferred width for @height for all rows which have
* been requested for the same said @height with this context.
*
* After gtk_cell_area_context_reset() is called and/or before ever requesting
* the size of a #GtkCellArea, the returned values are -1.
*
* Since: 3.0
*/
void
gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
gint height,
gint *minimum_width,
gint *natural_width)
{
g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height)
GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height (context,
height,
minimum_width,
natural_width);
}
/**
* gtk_cell_area_context_get_allocation:
* @context: a #GtkCellAreaContext

View File

@ -65,10 +65,18 @@ struct _GtkCellAreaContextClass
GObjectClass parent_class;
/*< public >*/
void (* allocate) (GtkCellAreaContext *context,
gint width,
gint height);
void (* reset) (GtkCellAreaContext *context);
void (* allocate) (GtkCellAreaContext *context,
gint width,
gint height);
void (* reset) (GtkCellAreaContext *context);
void (* get_preferred_height_for_width) (GtkCellAreaContext *context,
gint width,
gint *minimum_height,
gint *natural_height);
void (* get_preferred_width_for_height) (GtkCellAreaContext *context,
gint height,
gint *minimum_width,
gint *natural_width);
/*< private >*/
/* Padding for future expansion */
@ -81,22 +89,30 @@ struct _GtkCellAreaContextClass
GType gtk_cell_area_context_get_type (void) G_GNUC_CONST;
/* Main apis */
GtkCellArea *gtk_cell_area_context_get_area (GtkCellAreaContext *context);
void gtk_cell_area_context_allocate (GtkCellAreaContext *context,
gint width,
gint height);
void gtk_cell_area_context_reset (GtkCellAreaContext *context);
GtkCellArea *gtk_cell_area_context_get_area (GtkCellAreaContext *context);
void gtk_cell_area_context_allocate (GtkCellAreaContext *context,
gint width,
gint height);
void gtk_cell_area_context_reset (GtkCellAreaContext *context);
/* Apis for GtkCellArea clients to consult cached values for a series of GtkTreeModel rows */
void gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
gint *minimum_width,
gint *natural_width);
void gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
gint *minimum_height,
gint *natural_height);
void gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
gint *width,
gint *height);
void gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
gint *minimum_width,
gint *natural_width);
void gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
gint *minimum_height,
gint *natural_height);
void gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
gint width,
gint *minimum_height,
gint *natural_height);
void gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
gint height,
gint *minimum_width,
gint *natural_width);
void gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
gint *width,
gint *height);
/* Apis for GtkCellArea implementations to update cached values for multiple GtkTreeModel rows */
void gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context,