diff options
author | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2010-11-26 21:26:24 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2010-11-26 21:38:10 +0900 |
commit | 487223d480578457f924470c1a1d73eb261eefd7 (patch) | |
tree | e6888ecfc4a29875b54e5ba349a47f36ccc183fd /gtk/gtkcellareacontext.c | |
parent | fa3c8f182edcddcfb948513fbdadeeec2e059fe0 (diff) | |
download | gtk+-487223d480578457f924470c1a1d73eb261eefd7.tar.gz |
Finally really support rendering of cells in an unallocated context.
What this means is basically that a vertically oriented GtkCellAreaBox
will render cells properly even if the height is not constant for every
for of data in the said GtkCellAreaContext (i.e. the height was not allocated
by gtk_cell_area_context_allocate).
This is done completely on the fly and so is much more heavy duty
at render time (considerably slower but not visibly noticable in
lightweight views like GtkTreeMenu). Note that cell alignments
are not possible in an unallocated orientation, each row of data
individually receives only enough space to render the independant
row and no space is reserved for alignments if the size is not
a constant size across rows in the same context.
Diffstat (limited to 'gtk/gtkcellareacontext.c')
-rw-r--r-- | gtk/gtkcellareacontext.c | 415 |
1 files changed, 16 insertions, 399 deletions
diff --git a/gtk/gtkcellareacontext.c b/gtk/gtkcellareacontext.c index 61646708db..5a3ee8b28a 100644 --- a/gtk/gtkcellareacontext.c +++ b/gtk/gtkcellareacontext.c @@ -28,7 +28,6 @@ #include "gtkprivate.h" /* GObjectClass */ -static void gtk_cell_area_context_finalize (GObject *object); static void gtk_cell_area_context_dispose (GObject *object); static void gtk_cell_area_context_get_property (GObject *object, guint prop_id, @@ -41,26 +40,12 @@ static void gtk_cell_area_context_set_property (GObject /* GtkCellAreaContextClass */ static void gtk_cell_area_context_real_flush_preferred_width (GtkCellAreaContext *context); -static void gtk_cell_area_context_real_flush_preferred_height_for_width (GtkCellAreaContext *context, - gint width); static void gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context); -static void gtk_cell_area_context_real_flush_preferred_width_for_height (GtkCellAreaContext *context, - gint height); static void gtk_cell_area_context_real_flush_allocation (GtkCellAreaContext *context); -static void gtk_cell_area_context_real_allocate_width (GtkCellAreaContext *context, - gint width); -static void gtk_cell_area_context_real_allocate_height (GtkCellAreaContext *context, +static void gtk_cell_area_context_real_allocate (GtkCellAreaContext *context, + gint width, gint height); -/* CachedSize management */ -typedef struct { - 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); - struct _GtkCellAreaContextPrivate { GtkCellArea *cell_area; @@ -71,9 +56,6 @@ struct _GtkCellAreaContextPrivate gint nat_height; gint alloc_width; gint alloc_height; - - GHashTable *widths; - GHashTable *heights; }; enum { @@ -85,14 +67,6 @@ enum { PROP_NAT_HEIGHT }; -enum { - SIGNAL_WIDTH_CHANGED, - SIGNAL_HEIGHT_CHANGED, - LAST_SIGNAL -}; - -static guint cell_area_context_signals[LAST_SIGNAL] = { 0 }; - G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT); static void @@ -109,10 +83,6 @@ gtk_cell_area_context_init (GtkCellAreaContext *context) priv->nat_width = -1; priv->min_height = -1; priv->nat_height = -1; - priv->widths = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify)cached_size_free); - priv->heights = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, (GDestroyNotify)cached_size_free); } static void @@ -121,45 +91,17 @@ gtk_cell_area_context_class_init (GtkCellAreaContextClass *class) GObjectClass *object_class = G_OBJECT_CLASS (class); /* GObjectClass */ - object_class->finalize = gtk_cell_area_context_finalize; object_class->dispose = gtk_cell_area_context_dispose; object_class->get_property = gtk_cell_area_context_get_property; object_class->set_property = gtk_cell_area_context_set_property; /* GtkCellAreaContextClass */ - class->flush_preferred_width = gtk_cell_area_context_real_flush_preferred_width; - class->flush_preferred_height_for_width = gtk_cell_area_context_real_flush_preferred_height_for_width; - class->flush_preferred_height = gtk_cell_area_context_real_flush_preferred_height; - class->flush_preferred_width_for_height = gtk_cell_area_context_real_flush_preferred_width_for_height; - class->flush_allocation = gtk_cell_area_context_real_flush_allocation; - - class->sum_preferred_width = NULL; - class->sum_preferred_height_for_width = NULL; - class->sum_preferred_height = NULL; - class->sum_preferred_width_for_height = NULL; - - class->allocate_width = gtk_cell_area_context_real_allocate_width; - class->allocate_height = gtk_cell_area_context_real_allocate_height; - - cell_area_context_signals[SIGNAL_HEIGHT_CHANGED] = - g_signal_new (I_("height-changed"), - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, /* Class offset (just a notification, no class handler) */ - NULL, NULL, - _gtk_marshal_VOID__INT_INT_INT, - G_TYPE_NONE, 3, - G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); - - cell_area_context_signals[SIGNAL_WIDTH_CHANGED] = - g_signal_new (I_("width-changed"), - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, /* Class offset (just a notification, no class handler) */ - NULL, NULL, - _gtk_marshal_VOID__INT_INT_INT, - G_TYPE_NONE, 3, - G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + class->flush_preferred_width = gtk_cell_area_context_real_flush_preferred_width; + class->flush_preferred_height = gtk_cell_area_context_real_flush_preferred_height; + class->flush_allocation = gtk_cell_area_context_real_flush_allocation; + class->sum_preferred_width = NULL; + class->sum_preferred_height = NULL; + class->allocate = gtk_cell_area_context_real_allocate; g_object_class_install_property (object_class, PROP_CELL_AREA, @@ -212,45 +154,10 @@ gtk_cell_area_context_class_init (GtkCellAreaContextClass *class) g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate)); } - - -/************************************************************* - * 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 -gtk_cell_area_context_finalize (GObject *object) -{ - GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object); - GtkCellAreaContextPrivate *priv = context->priv; - - g_hash_table_destroy (priv->widths); - g_hash_table_destroy (priv->heights); - - G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->finalize (object); -} - -static void gtk_cell_area_context_dispose (GObject *object) { GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object); @@ -336,40 +243,6 @@ gtk_cell_area_context_real_flush_preferred_width (GtkCellAreaContext *context) } static void -notify_invalid_height (gpointer width_ptr, - CachedSize *size, - GtkCellAreaContext *context) -{ - gint width = GPOINTER_TO_INT (width_ptr); - - /* Notify size invalidated */ - g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], - 0, width, -1, -1); -} - -static void -gtk_cell_area_context_real_flush_preferred_height_for_width (GtkCellAreaContext *context, - gint width) -{ - GtkCellAreaContextPrivate *priv = context->priv; - - /* Flush all sizes for special -1 value */ - if (width < 0) - { - g_hash_table_foreach (priv->heights, (GHFunc)notify_invalid_height, context); - g_hash_table_remove_all (priv->heights); - } - else - { - g_hash_table_remove (priv->heights, GINT_TO_POINTER (width)); - - /* Notify size invalidated */ - g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], - 0, width, -1, -1); - } -} - -static void gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context) { GtkCellAreaContextPrivate *priv = context->priv; @@ -384,40 +257,6 @@ gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context) } static void -notify_invalid_width (gpointer height_ptr, - CachedSize *size, - GtkCellAreaContext *context) -{ - gint height = GPOINTER_TO_INT (height_ptr); - - /* Notify size invalidated */ - g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], - 0, height, -1, -1); -} - -static void -gtk_cell_area_context_real_flush_preferred_width_for_height (GtkCellAreaContext *context, - gint height) -{ - GtkCellAreaContextPrivate *priv = context->priv; - - /* Flush all sizes for special -1 value */ - if (height < 0) - { - g_hash_table_foreach (priv->widths, (GHFunc)notify_invalid_width, context); - g_hash_table_remove_all (priv->widths); - } - else - { - g_hash_table_remove (priv->widths, GINT_TO_POINTER (height)); - - /* Notify size invalidated */ - g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], - 0, height, -1, -1); - } -} - -static void gtk_cell_area_context_real_flush_allocation (GtkCellAreaContext *context) { GtkCellAreaContextPrivate *priv = context->priv; @@ -427,24 +266,16 @@ gtk_cell_area_context_real_flush_allocation (GtkCellAreaContext *context) } static void -gtk_cell_area_context_real_allocate_width (GtkCellAreaContext *context, - gint width) -{ - GtkCellAreaContextPrivate *priv = context->priv; - - priv->alloc_width = width; -} - -static void -gtk_cell_area_context_real_allocate_height (GtkCellAreaContext *context, - gint height) +gtk_cell_area_context_real_allocate (GtkCellAreaContext *context, + gint width, + gint height) { GtkCellAreaContextPrivate *priv = context->priv; + priv->alloc_width = width; priv->alloc_height = height; } - /************************************************************* * API * *************************************************************/ @@ -466,9 +297,7 @@ gtk_cell_area_context_flush (GtkCellAreaContext *context) g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); gtk_cell_area_context_flush_preferred_width (context); - gtk_cell_area_context_flush_preferred_height_for_width (context, -1); gtk_cell_area_context_flush_preferred_height (context); - gtk_cell_area_context_flush_preferred_width_for_height (context, -1); gtk_cell_area_context_flush_allocation (context); } @@ -481,15 +310,6 @@ gtk_cell_area_context_flush_preferred_width (GtkCellAreaContext *context) } void -gtk_cell_area_context_flush_preferred_height_for_width (GtkCellAreaContext *context, - gint for_width) -{ - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_height_for_width (context, for_width); -} - -void gtk_cell_area_context_flush_preferred_height (GtkCellAreaContext *context) { g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); @@ -498,15 +318,6 @@ gtk_cell_area_context_flush_preferred_height (GtkCellAreaContext *context) } void -gtk_cell_area_context_flush_preferred_width_for_height (GtkCellAreaContext *context, - gint for_height) -{ - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_width_for_height (context, for_height); -} - -void gtk_cell_area_context_flush_allocation (GtkCellAreaContext *context) { g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); @@ -528,20 +339,6 @@ gtk_cell_area_context_sum_preferred_width (GtkCellAreaContext *context) } void -gtk_cell_area_context_sum_preferred_height_for_width (GtkCellAreaContext *context, - gint for_width) -{ - GtkCellAreaContextClass *class; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context); - - if (class->sum_preferred_height_for_width) - class->sum_preferred_height_for_width (context, for_width); -} - -void gtk_cell_area_context_sum_preferred_height (GtkCellAreaContext *context) { GtkCellAreaContextClass *class; @@ -555,8 +352,9 @@ gtk_cell_area_context_sum_preferred_height (GtkCellAreaContext *context) } void -gtk_cell_area_context_sum_preferred_width_for_height (GtkCellAreaContext *context, - gint for_height) +gtk_cell_area_context_allocate (GtkCellAreaContext *context, + gint width, + gint height) { GtkCellAreaContextClass *class; @@ -564,34 +362,7 @@ gtk_cell_area_context_sum_preferred_width_for_height (GtkCellAreaContext *contex class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context); - if (class->sum_preferred_width_for_height) - class->sum_preferred_width_for_height (context, for_height); -} - -void -gtk_cell_area_context_allocate_width (GtkCellAreaContext *context, - gint width) -{ - GtkCellAreaContextClass *class; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context); - - class->allocate_width (context, width); -} - -void -gtk_cell_area_context_allocate_height (GtkCellAreaContext *context, - gint height) -{ - GtkCellAreaContextClass *class; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context); - - class->allocate_height (context, height); + class->allocate (context, width, height); } void @@ -613,39 +384,6 @@ gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context, } void -gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context, - gint for_width, - gint *minimum_height, - gint *natural_height) -{ - GtkCellAreaContextPrivate *priv; - CachedSize *size; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - priv = context->priv; - - size = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width)); - - if (size) - { - if (minimum_height) - *minimum_height = size->min_size; - - if (natural_height) - *natural_height = size->nat_size; - } - else - { - if (minimum_height) - *minimum_height = -1; - - if (natural_height) - *natural_height = -1; - } -} - -void gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context, gint *minimum_height, gint *natural_height) @@ -664,39 +402,6 @@ gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context, } void -gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context, - gint for_height, - gint *minimum_width, - gint *natural_width) -{ - GtkCellAreaContextPrivate *priv; - CachedSize *size; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - priv = context->priv; - - size = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height)); - - if (size) - { - if (minimum_width) - *minimum_width = size->min_size; - - if (natural_width) - *natural_width = size->nat_size; - } - else - { - if (minimum_width) - *minimum_width = -1; - - if (natural_width) - *natural_width = -1; - } -} - -void gtk_cell_area_context_get_allocation (GtkCellAreaContext *context, gint *width, gint *height) @@ -745,50 +450,6 @@ gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context, } void -gtk_cell_area_context_push_preferred_height_for_width (GtkCellAreaContext *context, - gint for_width, - gint minimum_height, - gint natural_height) -{ - GtkCellAreaContextPrivate *priv; - CachedSize *size; - gboolean changed = FALSE; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - priv = context->priv; - - size = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width)); - - if (!size) - { - size = cached_size_new (minimum_height, natural_height); - - g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), size); - - changed = TRUE; - } - else - { - if (minimum_height > size->min_size) - { - size->min_size = minimum_height; - changed = TRUE; - } - - if (natural_height > size->nat_size) - { - size->nat_size = natural_height; - changed = TRUE; - } - } - - if (changed) - g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], 0, - for_width, size->min_size, size->nat_size); -} - -void gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context, gint minimum_height, gint natural_height) @@ -817,47 +478,3 @@ gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context, g_object_thaw_notify (G_OBJECT (context)); } - -void -gtk_cell_area_context_push_preferred_width_for_height (GtkCellAreaContext *context, - gint for_height, - gint minimum_width, - gint natural_width) -{ - GtkCellAreaContextPrivate *priv; - CachedSize *size; - gboolean changed = FALSE; - - g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context)); - - priv = context->priv; - - size = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height)); - - if (!size) - { - size = cached_size_new (minimum_width, natural_width); - - g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), size); - - changed = TRUE; - } - else - { - if (minimum_width > size->min_size) - { - size->min_size = minimum_width; - changed = TRUE; - } - - if (natural_width > size->nat_size) - { - size->nat_size = natural_width; - changed = TRUE; - } - } - - if (changed) - g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], 0, - for_height, size->min_size, size->nat_size); -} |