diff --git a/gtk/Makefile.am b/gtk/Makefile.am index eae08f0100..dd5c6e478a 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -170,6 +170,7 @@ gtk_public_h_sources = \ gtkcalendar.h \ gtkcellarea.h \ gtkcellareabox.h \ + gtkcellareaiter.h \ gtkcelleditable.h \ gtkcelllayout.h \ gtkcellrenderer.h \ @@ -434,6 +435,7 @@ gtk_base_c_sources = \ gtkcalendar.c \ gtkcellarea.c \ gtkcellareabox.c \ + gtkcellareaiter.c \ gtkcelleditable.c \ gtkcelllayout.c \ gtkcellrenderer.c \ diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c index c8a2c3e71d..37d101a4c6 100644 --- a/gtk/gtkcellarea.c +++ b/gtk/gtkcellarea.c @@ -30,11 +30,13 @@ static void gtk_cell_area_finalize (GObject /* GtkCellAreaClass */ static void gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height); static void gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, @@ -138,6 +140,7 @@ gtk_cell_area_class_init (GtkCellAreaClass *class) class->render = NULL; /* geometry */ + class->create_iter = NULL; class->get_request_mode = NULL; class->get_preferred_width = NULL; class->get_preferred_height = NULL; @@ -253,24 +256,26 @@ gtk_cell_area_dispose (GObject *object) *************************************************************/ static void gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height) { /* If the area doesnt do height-for-width, fallback on base preferred height */ - GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, widget, minimum_height, natural_height); + GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, iter, widget, minimum_height, natural_height); } static void gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, gint *natural_width) { /* If the area doesnt do width-for-height, fallback on base preferred width */ - GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, widget, minimum_width, natural_width); + GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, iter, widget, minimum_width, natural_width); } /************************************************************* @@ -520,6 +525,25 @@ gtk_cell_area_render (GtkCellArea *area, } /* Geometry */ +GtkCellAreaIter * +gtk_cell_area_create_iter (GtkCellArea *area) +{ + GtkCellAreaClass *class; + + g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL); + + class = GTK_CELL_AREA_GET_CLASS (area); + + if (class->create_iter) + return class->create_iter (area); + + g_warning ("GtkCellAreaClass::create_iter not implemented for `%s'", + g_type_name (G_TYPE_FROM_INSTANCE (area))); + + return NULL; +} + + GtkSizeRequestMode gtk_cell_area_get_request_mode (GtkCellArea *area) { @@ -541,6 +565,7 @@ gtk_cell_area_get_request_mode (GtkCellArea *area) void gtk_cell_area_get_preferred_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_size, gint *natural_size) @@ -553,7 +578,7 @@ gtk_cell_area_get_preferred_width (GtkCellArea *area, class = GTK_CELL_AREA_GET_CLASS (area); if (class->get_preferred_width) - class->get_preferred_width (area, widget, minimum_size, natural_size); + class->get_preferred_width (area, iter, widget, minimum_size, natural_size); else g_warning ("GtkCellAreaClass::get_preferred_width not implemented for `%s'", g_type_name (G_TYPE_FROM_INSTANCE (area))); @@ -561,6 +586,7 @@ gtk_cell_area_get_preferred_width (GtkCellArea *area, void gtk_cell_area_get_preferred_height_for_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, @@ -572,11 +598,12 @@ gtk_cell_area_get_preferred_height_for_width (GtkCellArea *area, g_return_if_fail (GTK_IS_WIDGET (widget)); class = GTK_CELL_AREA_GET_CLASS (area); - class->get_preferred_height_for_width (area, widget, width, minimum_height, natural_height); + class->get_preferred_height_for_width (area, iter, widget, width, minimum_height, natural_height); } void gtk_cell_area_get_preferred_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_size, gint *natural_size) @@ -589,7 +616,7 @@ gtk_cell_area_get_preferred_height (GtkCellArea *area, class = GTK_CELL_AREA_GET_CLASS (area); if (class->get_preferred_height) - class->get_preferred_height (area, widget, minimum_size, natural_size); + class->get_preferred_height (area, iter, widget, minimum_size, natural_size); else g_warning ("GtkCellAreaClass::get_preferred_height not implemented for `%s'", g_type_name (G_TYPE_FROM_INSTANCE (area))); @@ -597,6 +624,7 @@ gtk_cell_area_get_preferred_height (GtkCellArea *area, void gtk_cell_area_get_preferred_width_for_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, @@ -608,7 +636,7 @@ gtk_cell_area_get_preferred_width_for_height (GtkCellArea *area, g_return_if_fail (GTK_IS_WIDGET (widget)); class = GTK_CELL_AREA_GET_CLASS (area); - class->get_preferred_width_for_height (area, widget, height, minimum_width, natural_width); + class->get_preferred_width_for_height (area, iter, widget, height, minimum_width, natural_width); } void diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h index 145488302d..5a9c770f71 100644 --- a/gtk/gtkcellarea.h +++ b/gtk/gtkcellarea.h @@ -31,6 +31,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -88,21 +89,26 @@ struct _GtkCellAreaClass const GdkRectangle *cell_area); /* Geometry */ + GtkCellAreaIter *(* create_iter) (GtkCellArea *area); GtkSizeRequestMode (* get_request_mode) (GtkCellArea *area); void (* get_preferred_width) (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_size, gint *natural_size); void (* get_preferred_height_for_width) (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height); void (* get_preferred_height) (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_size, gint *natural_size); void (* get_preferred_width_for_height) (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, @@ -140,21 +146,26 @@ void gtk_cell_area_render (GtkCellArea const GdkRectangle *cell_area); /* Geometry */ +GtkCellAreaIter *gtk_cell_area_create_iter (GtkCellArea *area); GtkSizeRequestMode gtk_cell_area_get_request_mode (GtkCellArea *area); void gtk_cell_area_get_preferred_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_size, gint *natural_size); void gtk_cell_area_get_preferred_height_for_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height); void gtk_cell_area_get_preferred_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_size, gint *natural_size); void gtk_cell_area_get_preferred_width_for_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c index 80cb16e548..059dbf9e07 100644 --- a/gtk/gtkcellareabox.c +++ b/gtk/gtkcellareabox.c @@ -1,4 +1,4 @@ -/* gtkcellarea.c +/* gtkcellareabox.c * * Copyright (C) 2010 Openismus GmbH * @@ -54,21 +54,26 @@ static void gtk_cell_area_box_render (GtkCellArea GtkWidget *widget, const GdkRectangle *cell_area); -static GtkSizeRequestMode gtk_cell_area_box_get_request_mode (GtkCellArea *area); +static GtkCellAreaIter *gtk_cell_area_box_create_iter (GtkCellArea *area); +static GtkSizeRequestMode gtk_cell_area_box_get_request_mode (GtkCellArea *area); static void gtk_cell_area_box_get_preferred_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_width, gint *natural_width); static void gtk_cell_area_box_get_preferred_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_height, gint *natural_height); static void gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height); static void gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, @@ -153,6 +158,7 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class) area_class->event = gtk_cell_area_box_event; area_class->render = gtk_cell_area_box_render; + area_class->create_iter = gtk_cell_area_box_create_iter; 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; @@ -302,6 +308,12 @@ gtk_cell_area_box_render (GtkCellArea *area, } +static GtkCellAreaIter * +gtk_cell_area_box_create_iter (GtkCellArea *area) +{ + return NULL; +} + static GtkSizeRequestMode gtk_cell_area_box_get_request_mode (GtkCellArea *area) { @@ -315,6 +327,7 @@ gtk_cell_area_box_get_request_mode (GtkCellArea *area) static void gtk_cell_area_box_get_preferred_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_width, gint *natural_width) @@ -324,6 +337,7 @@ gtk_cell_area_box_get_preferred_width (GtkCellArea *area, static void gtk_cell_area_box_get_preferred_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint *minimum_height, gint *natural_height) @@ -334,6 +348,7 @@ gtk_cell_area_box_get_preferred_height (GtkCellArea *area, static void gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint width, gint *minimum_height, @@ -344,6 +359,7 @@ gtk_cell_area_box_get_preferred_height_for_width (GtkCellArea *area, static void gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea *area, + GtkCellAreaIter *iter, GtkWidget *widget, gint height, gint *minimum_width, @@ -353,7 +369,6 @@ gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea *area, } - /************************************************************* * GtkCellLayoutIface * *************************************************************/ diff --git a/gtk/gtkcellareaiter.c b/gtk/gtkcellareaiter.c new file mode 100644 index 0000000000..1c69a3003c --- /dev/null +++ b/gtk/gtkcellareaiter.c @@ -0,0 +1,607 @@ +/* gtkcellareaiter.c + * + * Copyright (C) 2010 Openismus GmbH + * + * Authors: + * Tristan Van Berkom + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" +#include "gtkintl.h" +#include "gtkmarshalers.h" +#include "gtkorientable.h" +#include "gtkcelllayout.h" +#include "gtkcellareaiter.h" + +/* GObjectClass */ +static void gtk_cell_area_iter_finalize (GObject *object); +static void gtk_cell_area_iter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +/* GtkCellAreaIterClass */ +static void gtk_cell_area_iter_real_flush_preferred_width (GtkCellAreaIter *iter); +static void gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter, + gint width); +static void gtk_cell_area_iter_real_flush_preferred_height (GtkCellAreaIter *iter); +static void gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter, + 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 _GtkCellAreaIterPrivate +{ + gint min_width; + gint nat_width; + gint min_height; + gint nat_height; + + GHashTable *widths; + GHashTable *heights; +}; + +enum { + PROP_0, + PROP_MIN_WIDTH, + PROP_NAT_WIDTH, + PROP_MIN_HEIGHT, + PROP_NAT_HEIGHT +}; + +enum { + SIGNAL_WIDTH_CHANGED, + SIGNAL_HEIGHT_CHANGED, + LAST_SIGNAL +}; + +static guint cell_area_iter_signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (GtkCellAreaIter, gtk_cell_area_iter, G_TYPE_OBJECT); + +static void +gtk_cell_area_iter_init (GtkCellAreaIter *iter) +{ + GtkCellAreaIterPrivate *priv; + + iter->priv = G_TYPE_INSTANCE_GET_PRIVATE (iter, + GTK_TYPE_CELL_AREA_ITER, + GtkCellAreaIterPrivate); + priv = iter->priv; + + priv->min_width = -1; + 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 +gtk_cell_area_iter_class_init (GtkCellAreaIterClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + /* GObjectClass */ + object_class->finalize = gtk_cell_area_iter_finalize; + object_class->get_property = gtk_cell_area_iter_get_property; + + class->flush_preferred_width = gtk_cell_area_iter_real_flush_preferred_width; + class->flush_preferred_height_for_width = gtk_cell_area_iter_real_flush_preferred_height_for_width; + class->flush_preferred_height = gtk_cell_area_iter_real_flush_preferred_height; + class->flush_preferred_width_for_height = gtk_cell_area_iter_real_flush_preferred_width_for_height; + + cell_area_iter_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_iter_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); + + g_object_class_install_property (object_class, + PROP_MIN_WIDTH, + g_param_spec_int ("minimum-width", + P_("Minimum Width"), + P_("Minimum cached width"), + -1, + G_MAXINT, + -1, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_NAT_WIDTH, + g_param_spec_int ("natural-width", + P_("Minimum Width"), + P_("Minimum cached width"), + -1, + G_MAXINT, + -1, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_MIN_HEIGHT, + g_param_spec_int ("minimum-height", + P_("Minimum Height"), + P_("Minimum cached height"), + -1, + G_MAXINT, + -1, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_NAT_HEIGHT, + g_param_spec_int ("natural-height", + P_("Minimum Height"), + P_("Minimum cached height"), + -1, + G_MAXINT, + -1, + G_PARAM_READABLE)); + + g_type_class_add_private (object_class, sizeof (GtkCellAreaIterPrivate)); +} + + + +/************************************************************* + * 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_iter_finalize (GObject *object) +{ + GtkCellAreaIter *iter = GTK_CELL_AREA_ITER (object); + GtkCellAreaIterPrivate *priv = iter->priv; + + g_hash_table_destroy (priv->widths); + g_hash_table_destroy (priv->heights); + + G_OBJECT_CLASS (gtk_cell_area_iter_parent_class)->finalize (object); +} + +static void +gtk_cell_area_iter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkCellAreaIter *iter = GTK_CELL_AREA_ITER (object); + GtkCellAreaIterPrivate *priv = iter->priv; + + switch (prop_id) + { + case PROP_MIN_WIDTH: + g_value_set_int (value, priv->min_width); + break; + case PROP_NAT_WIDTH: + g_value_set_int (value, priv->nat_width); + break; + case PROP_MIN_HEIGHT: + g_value_set_int (value, priv->min_height); + break; + case PROP_NAT_HEIGHT: + g_value_set_int (value, priv->nat_height); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/************************************************************* + * GtkCellAreaIterClass * + *************************************************************/ +static void +gtk_cell_area_iter_real_flush_preferred_width (GtkCellAreaIter *iter) +{ + GtkCellAreaIterPrivate *priv = iter->priv; + + priv->min_width = -1; + priv->nat_width = -1; + + g_object_freeze_notify (G_OBJECT (iter)); + g_object_notify (G_OBJECT (iter), "minimum-width"); + g_object_notify (G_OBJECT (iter), "natural-width"); + g_object_thaw_notify (G_OBJECT (iter)); +} + +static void +gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter, + gint width) +{ + GtkCellAreaIterPrivate *priv = iter->priv; + + /* Flush all sizes for special -1 value */ + if (width < 0) + g_hash_table_remove_all (priv->heights); + else + g_hash_table_remove (priv->heights, GINT_TO_POINTER (width)); + + /* XXX Should we bother signalling removed values as "size-changed" signals ? */ +} + +static void +gtk_cell_area_iter_real_flush_preferred_height (GtkCellAreaIter *iter) +{ + GtkCellAreaIterPrivate *priv = iter->priv; + + priv->min_height = -1; + priv->nat_height = -1; + + g_object_freeze_notify (G_OBJECT (iter)); + g_object_notify (G_OBJECT (iter), "minimum-height"); + g_object_notify (G_OBJECT (iter), "natural-height"); + g_object_thaw_notify (G_OBJECT (iter)); +} + +static void +gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter, + gint height) +{ + GtkCellAreaIterPrivate *priv = iter->priv; + + /* Flush all sizes for special -1 value */ + if (height < 0) + g_hash_table_remove_all (priv->widths); + else + g_hash_table_remove (priv->widths, GINT_TO_POINTER (height)); + + /* XXX Should we bother signalling removed values as "size-changed" signals ? */ +} + +/************************************************************* + * API * + *************************************************************/ + +void +gtk_cell_area_iter_get_preferred_width (GtkCellAreaIter *iter, + gint *minimum_width, + gint *natural_width) +{ + GtkCellAreaIterPrivate *priv; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->priv; + + if (minimum_width) + *minimum_width = priv->min_width; + + if (natural_width) + *natural_width = priv->nat_width; +} + +void +gtk_cell_area_iter_get_preferred_height_for_width (GtkCellAreaIter *iter, + gint for_width, + gint *minimum_height, + gint *natural_height) +{ + GtkCellAreaIterPrivate *priv; + CachedSize *size; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->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_iter_get_preferred_height (GtkCellAreaIter *iter, + gint *minimum_height, + gint *natural_height) +{ + GtkCellAreaIterPrivate *priv; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->priv; + + if (minimum_height) + *minimum_height = priv->min_height; + + if (natural_height) + *natural_height = priv->nat_height; +} + +void +gtk_cell_area_iter_get_preferred_width_for_height (GtkCellAreaIter *iter, + gint for_height, + gint *minimum_width, + gint *natural_width) +{ + GtkCellAreaIterPrivate *priv; + CachedSize *size; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->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_iter_push_preferred_width (GtkCellAreaIter *iter, + gint minimum_width, + gint natural_width) +{ + GtkCellAreaIterPrivate *priv; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->priv; + + g_object_freeze_notify (G_OBJECT (iter)); + + if (minimum_width > priv->min_width) + { + priv->min_width = minimum_width; + + g_object_notify (G_OBJECT (iter), "minimum-width"); + } + + if (natural_width > priv->nat_width) + { + priv->nat_width = natural_width; + + g_object_notify (G_OBJECT (iter), "natural-width"); + } + + g_object_thaw_notify (G_OBJECT (iter)); +} + +void +gtk_cell_area_iter_push_preferred_height_for_width (GtkCellAreaIter *iter, + gint for_width, + gint minimum_height, + gint natural_height) +{ + GtkCellAreaIterPrivate *priv; + CachedSize *size; + gboolean changed = FALSE; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->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 (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED], 0, + for_width, size->min_size, size->nat_size); +} + +void +gtk_cell_area_iter_push_preferred_height (GtkCellAreaIter *iter, + gint minimum_height, + gint natural_height) +{ + GtkCellAreaIterPrivate *priv; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->priv; + + g_object_freeze_notify (G_OBJECT (iter)); + + if (minimum_height > priv->min_height) + { + priv->min_height = minimum_height; + + g_object_notify (G_OBJECT (iter), "minimum-height"); + } + + if (natural_height > priv->nat_height) + { + priv->nat_height = natural_height; + + g_object_notify (G_OBJECT (iter), "natural-height"); + } + + g_object_thaw_notify (G_OBJECT (iter)); +} + +void +gtk_cell_area_iter_push_preferred_width_for_height (GtkCellAreaIter *iter, + gint for_height, + gint minimum_width, + gint natural_width) +{ + GtkCellAreaIterPrivate *priv; + CachedSize *size; + gboolean changed = FALSE; + + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + priv = iter->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 (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED], 0, + for_height, size->min_size, size->nat_size); +} + +void +gtk_cell_area_iter_flush (GtkCellAreaIter *iter) +{ + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + gtk_cell_area_iter_flush_preferred_width (iter); + gtk_cell_area_iter_flush_preferred_height_for_width (iter, -1); + gtk_cell_area_iter_flush_preferred_height (iter); + gtk_cell_area_iter_flush_preferred_width_for_height (iter, -1); +} + +void +gtk_cell_area_iter_flush_preferred_width (GtkCellAreaIter *iter) +{ + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + GTK_CELL_AREA_ITER_GET_CLASS (iter)->flush_preferred_width (iter); +} + +void +gtk_cell_area_iter_flush_preferred_height_for_width (GtkCellAreaIter *iter, + gint for_width) +{ + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + GTK_CELL_AREA_ITER_GET_CLASS (iter)->flush_preferred_height_for_width (iter, for_width); +} + +void +gtk_cell_area_iter_flush_preferred_height (GtkCellAreaIter *iter) +{ + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + GTK_CELL_AREA_ITER_GET_CLASS (iter)->flush_preferred_height (iter); +} + +void +gtk_cell_area_iter_flush_preferred_width_for_height (GtkCellAreaIter *iter, + gint for_height) +{ + g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter)); + + GTK_CELL_AREA_ITER_GET_CLASS (iter)->flush_preferred_width_for_height (iter, for_height); +} diff --git a/gtk/gtkcellareaiter.h b/gtk/gtkcellareaiter.h new file mode 100644 index 0000000000..92f820fb06 --- /dev/null +++ b/gtk/gtkcellareaiter.h @@ -0,0 +1,117 @@ +/* gtkcellareaiter.h + * + * Copyright (C) 2010 Openismus GmbH + * + * Authors: + * Tristan Van Berkom + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_CELL_AREA_ITER_H__ +#define __GTK_CELL_AREA_ITER_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_CELL_AREA_ITER (gtk_cell_area_iter_get_type ()) +#define GTK_CELL_AREA_ITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_AREA_ITER, GtkCellAreaIter)) +#define GTK_CELL_AREA_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_AREA_ITER, GtkCellAreaIterClass)) +#define GTK_IS_CELL_AREA_ITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_AREA_ITER)) +#define GTK_IS_CELL_AREA_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CELL_AREA_ITER)) +#define GTK_CELL_AREA_ITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CELL_AREA_ITER, GtkCellAreaIterClass)) + +typedef struct _GtkCellAreaIter GtkCellAreaIter; +typedef struct _GtkCellAreaIterPrivate GtkCellAreaIterPrivate; +typedef struct _GtkCellAreaIterClass GtkCellAreaIterClass; + +struct _GtkCellAreaIter +{ + GObject parent_instance; + + GtkCellAreaIterPrivate *priv; +}; + +struct _GtkCellAreaIterClass +{ + GObjectClass parent_class; + + /* Subclasses can use this to flush their alignments */ + void (* flush_preferred_width) (GtkCellAreaIter *iter); + void (* flush_preferred_height_for_width) (GtkCellAreaIter *iter, + gint width); + void (* flush_preferred_height) (GtkCellAreaIter *iter); + void (* flush_preferred_width_for_height) (GtkCellAreaIter *iter, + gint height); + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + +GType gtk_cell_area_iter_get_type (void) G_GNUC_CONST; + +/* Apis for GtkCellArea clients to consult cached values for multiple GtkTreeModel rows */ +void gtk_cell_area_iter_get_preferred_width (GtkCellAreaIter *iter, + gint *minimum_width, + gint *natural_width); +void gtk_cell_area_iter_get_preferred_height_for_width (GtkCellAreaIter *iter, + gint for_width, + gint *minimum_height, + gint *natural_height); +void gtk_cell_area_iter_get_preferred_height (GtkCellAreaIter *iter, + gint *minimum_height, + gint *natural_height); +void gtk_cell_area_iter_get_preferred_width_for_height (GtkCellAreaIter *iter, + gint for_height, + gint *minimum_width, + gint *natural_width); + +/* Apis for GtkCellArea implementations to update cached values for multiple GtkTreeModel rows */ +void gtk_cell_area_iter_push_preferred_width (GtkCellAreaIter *iter, + gint minimum_width, + gint natural_width); +void gtk_cell_area_iter_push_preferred_height_for_width (GtkCellAreaIter *iter, + gint for_width, + gint minimum_height, + gint natural_height); +void gtk_cell_area_iter_push_preferred_height (GtkCellAreaIter *iter, + gint minimum_height, + gint natural_height); +void gtk_cell_area_iter_push_preferred_width_for_height (GtkCellAreaIter *iter, + gint for_height, + gint minimum_width, + gint natural_width); + +/* Apis for GtkCellArea clients to flush the cache */ +void gtk_cell_area_iter_flush (GtkCellAreaIter *iter); +void gtk_cell_area_iter_flush_preferred_width (GtkCellAreaIter *iter); +void gtk_cell_area_iter_flush_preferred_height_for_width (GtkCellAreaIter *iter, + gint for_width); +void gtk_cell_area_iter_flush_preferred_height (GtkCellAreaIter *iter); +void gtk_cell_area_iter_flush_preferred_width_for_height (GtkCellAreaIter *iter, + gint for_height); + +G_END_DECLS + +#endif /* __GTK_CELL_AREA_ITER_H__ */