]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcellview.c
Merge branch 'master' into treeview-refactor
[~andy/gtk] / gtk / gtkcellview.c
index 1e9912f3d49bfe46d8f7c349aba5f7d81817e807..09840d4ecaf02e022d10b1f8c1c9deb4032d7862 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#include <config.h>
-#include "gtkalias.h"
+#include "config.h"
+#include <string.h>
 #include "gtkcellview.h"
 #include "gtkcelllayout.h"
 #include "gtkintl.h"
-#include "gtksignal.h"
 #include "gtkcellrenderertext.h"
 #include "gtkcellrendererpixbuf.h"
+#include "gtkprivate.h"
+#include "gtksizerequest.h"
 #include <gobject/gmarshal.h>
+#include "gtkbuildable.h"
+
 
 typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo;
 struct _GtkCellViewCellInfo
@@ -33,6 +36,7 @@ struct _GtkCellViewCellInfo
   GtkCellRenderer *cell;
 
   gint requested_width;
+  gint natural_width;
   gint real_width;
   guint expand : 1;
   guint pack : 1;
@@ -51,12 +55,11 @@ struct _GtkCellViewPrivate
   GList *cell_list;
   gint spacing;
 
-  GdkColor background;
+  GdkRGBA background;
   gboolean background_set;
 };
 
 
-static void        gtk_cell_view_class_init               (GtkCellViewClass *klass);
 static void        gtk_cell_view_cell_layout_init         (GtkCellLayoutIface *iface);
 static void        gtk_cell_view_get_property             (GObject           *object,
                                                            guint             param_id,
@@ -66,19 +69,15 @@ static void        gtk_cell_view_set_property             (GObject          *obj
                                                            guint             param_id,
                                                            const GValue     *value,
                                                            GParamSpec       *pspec);
-static void        gtk_cell_view_init                     (GtkCellView      *cellview);
 static void        gtk_cell_view_finalize                 (GObject          *object);
-static void        gtk_cell_view_style_set                (GtkWidget        *widget,
-                                                           GtkStyle         *previous_style);
-static void        gtk_cell_view_size_request             (GtkWidget        *widget,
-                                                           GtkRequisition   *requisition);
 static void        gtk_cell_view_size_allocate            (GtkWidget        *widget,
                                                            GtkAllocation    *allocation);
-static gboolean    gtk_cell_view_expose                   (GtkWidget        *widget,
-                                                           GdkEventExpose   *event);
-static void        gtk_cell_view_set_valuesv              (GtkCellView      *cellview,
-                                                           GtkCellRenderer  *renderer,
-                                                           va_list           args);
+static gboolean    gtk_cell_view_draw                     (GtkWidget        *widget,
+                                                           cairo_t          *cr);
+static void        gtk_cell_view_set_value                (GtkCellView     *cell_view,
+                                                           GtkCellRenderer *renderer,
+                                                           gchar           *property,
+                                                           GValue          *value);
 static GtkCellViewCellInfo *gtk_cell_view_get_cell_info   (GtkCellView      *cellview,
                                                            GtkCellRenderer  *renderer);
 static void        gtk_cell_view_set_cell_data            (GtkCellView      *cell_view);
@@ -105,57 +104,56 @@ static void       gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout
 static void       gtk_cell_view_cell_layout_reorder            (GtkCellLayout         *layout,
                                                                 GtkCellRenderer       *cell,
                                                                 gint                   position);
+static GList *    gtk_cell_view_cell_layout_get_cells          (GtkCellLayout         *layout);
+
+/* buildable */
+static void       gtk_cell_view_buildable_init                 (GtkBuildableIface     *iface);
+static gboolean   gtk_cell_view_buildable_custom_tag_start     (GtkBuildable         *buildable,
+                                                               GtkBuilder            *builder,
+                                                               GObject               *child,
+                                                               const gchar           *tagname,
+                                                               GMarkupParser         *parser,
+                                                               gpointer              *data);
+static void       gtk_cell_view_buildable_custom_tag_end       (GtkBuildable         *buildable,
+                                                               GtkBuilder            *builder,
+                                                               GObject               *child,
+                                                               const gchar           *tagname,
+                                                               gpointer              *data);
+
+static void       gtk_cell_view_get_preferred_width            (GtkWidget             *widget,
+                                                               gint                  *minimum_size,
+                                                               gint                  *natural_size);
+static void       gtk_cell_view_get_preferred_height           (GtkWidget             *widget,
+                                                               gint                  *minimum_size,
+                                                               gint                  *natural_size);
+static void       gtk_cell_view_get_preferred_width_for_height (GtkWidget             *widget,
+                                                               gint                   avail_size,
+                                                               gint                  *minimum_size,
+                                                               gint                  *natural_size);
+static void       gtk_cell_view_get_preferred_height_for_width (GtkWidget             *widget,
+                                                               gint                   avail_size,
+                                                               gint                  *minimum_size,
+                                                               gint                  *natural_size);
+
+static GtkBuildableIface *parent_buildable_iface;
 
 
-#define GTK_CELL_VIEW_GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_VIEW, GtkCellViewPrivate))
-
 enum
 {
   PROP_0,
   PROP_BACKGROUND,
   PROP_BACKGROUND_GDK,
-  PROP_BACKGROUND_SET
+  PROP_BACKGROUND_RGBA,
+  PROP_BACKGROUND_SET,
+  PROP_MODEL
 };
 
-static GtkObjectClass *parent_class = NULL;
-
-
-GType
-gtk_cell_view_get_type (void)
-{
-  static GType cell_view_type = 0;
-
-  if (!cell_view_type)
-    {
-      static const GTypeInfo cell_view_info =
-        {
-          sizeof (GtkCellViewClass),
-          NULL, /* base_init */
-          NULL, /* base_finalize */
-          (GClassInitFunc) gtk_cell_view_class_init,
-          NULL, /* class_finalize */
-          NULL, /* class_data */
-          sizeof (GtkCellView),
-          0,
-          (GInstanceInitFunc) gtk_cell_view_init
-        };
-
-      static const GInterfaceInfo cell_layout_info =
-       {
-         (GInterfaceInitFunc) gtk_cell_view_cell_layout_init,
-         NULL,
-         NULL
-       };
-
-      cell_view_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkCellView",
-                                               &cell_view_info, 0);
-
-      g_type_add_interface_static (cell_view_type, GTK_TYPE_CELL_LAYOUT,
-                                   &cell_layout_info);
-    }
+G_DEFINE_TYPE_WITH_CODE (GtkCellView, gtk_cell_view, GTK_TYPE_WIDGET, 
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
+                                               gtk_cell_view_cell_layout_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                               gtk_cell_view_buildable_init))
 
-  return cell_view_type;
-}
 
 static void
 gtk_cell_view_class_init (GtkCellViewClass *klass)
@@ -163,16 +161,16 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
-
   gobject_class->get_property = gtk_cell_view_get_property;
   gobject_class->set_property = gtk_cell_view_set_property;
   gobject_class->finalize = gtk_cell_view_finalize;
 
-  widget_class->expose_event = gtk_cell_view_expose;
-  widget_class->size_allocate = gtk_cell_view_size_allocate;
-  widget_class->size_request = gtk_cell_view_size_request;
-  widget_class->style_set = gtk_cell_view_style_set;
+  widget_class->draw                           = gtk_cell_view_draw;
+  widget_class->size_allocate                  = gtk_cell_view_size_allocate;
+  widget_class->get_preferred_width            = gtk_cell_view_get_preferred_width;
+  widget_class->get_preferred_height           = gtk_cell_view_get_preferred_height;
+  widget_class->get_preferred_width_for_height = gtk_cell_view_get_preferred_width_for_height;
+  widget_class->get_preferred_height_for_width = gtk_cell_view_get_preferred_height_for_width;
 
   /* properties */
   g_object_class_install_property (gobject_class,
@@ -181,24 +179,62 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
                                                         P_("Background color name"),
                                                         P_("Background color as a string"),
                                                         NULL,
-                                                        G_PARAM_WRITABLE));
+                                                        GTK_PARAM_WRITABLE));
   g_object_class_install_property (gobject_class,
                                    PROP_BACKGROUND_GDK,
-                                   g_param_spec_boxed ("background_gdk",
+                                   g_param_spec_boxed ("background-gdk",
                                                       P_("Background color"),
                                                       P_("Background color as a GdkColor"),
                                                       GDK_TYPE_COLOR,
-                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
-
-#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))
-
-  ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
+                                                      GTK_PARAM_READWRITE));
+  /**
+   * GtkCellView:background-rgba
+   *
+   * The background color as a #GdkRGBA
+   *
+   * Since: 3.0
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_BACKGROUND_RGBA,
+                                   g_param_spec_boxed ("background-rgba",
+                                                      P_("Background RGBA color"),
+                                                      P_("Background color as a GdkRGBA"),
+                                                      GDK_TYPE_RGBA,
+                                                      GTK_PARAM_READWRITE));
+
+  /**
+   * GtkCellView:model
+   *
+   * The model for cell view
+   *
+   * since 2.10
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_MODEL,
+                                  g_param_spec_object  ("model",
+                                                        P_("CellView model"),
+                                                        P_("The model for cell view"),
+                                                        GTK_TYPE_TREE_MODEL,
+                                                        GTK_PARAM_READWRITE));
+  
+#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
+
+  ADD_SET_PROP ("background-set", PROP_BACKGROUND_SET,
                 P_("Background set"),
                 P_("Whether this tag affects the background color"));
 
   g_type_class_add_private (gobject_class, sizeof (GtkCellViewPrivate));
 }
 
+static void
+gtk_cell_view_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add_child = _gtk_cell_layout_buildable_add_child;
+  iface->custom_tag_start = gtk_cell_view_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_cell_view_buildable_custom_tag_end;
+}
+
 static void
 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
 {
@@ -209,6 +245,7 @@ gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
   iface->set_cell_data_func = gtk_cell_view_cell_layout_set_cell_data_func;
   iface->clear_attributes = gtk_cell_view_cell_layout_clear_attributes;
   iface->reorder = gtk_cell_view_cell_layout_reorder;
+  iface->get_cells = gtk_cell_view_cell_layout_get_cells;
 }
 
 static void
@@ -225,14 +262,23 @@ gtk_cell_view_get_property (GObject    *object,
         {
           GdkColor color;
 
-          color = view->priv->background;
+          color.red = (guint) (view->priv->background.red * 65535);
+          color.green = (guint) (view->priv->background.green * 65535);
+          color.blue = (guint) (view->priv->background.blue * 65535);
+          color.pixel = 0;
 
           g_value_set_boxed (value, &color);
         }
         break;
+      case PROP_BACKGROUND_RGBA:
+        g_value_set_boxed (value, &view->priv->background);
+        break;
       case PROP_BACKGROUND_SET:
         g_value_set_boolean (value, view->priv->background_set);
         break;
+      case PROP_MODEL:
+       g_value_set_object (value, view->priv->model);
+       break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
         break;
@@ -260,16 +306,22 @@ gtk_cell_view_set_property (GObject      *object,
           else
             g_warning ("Don't know color `%s'", g_value_get_string (value));
 
-          g_object_notify (object, "background_gdk");
+          g_object_notify (object, "background-gdk");
         }
         break;
       case PROP_BACKGROUND_GDK:
         gtk_cell_view_set_background_color (view, g_value_get_boxed (value));
         break;
+      case PROP_BACKGROUND_RGBA:
+        gtk_cell_view_set_background_rgba (view, g_value_get_boxed (value));
+        break;
       case PROP_BACKGROUND_SET:
         view->priv->background_set = g_value_get_boolean (value);
         break;
-      default:
+      case PROP_MODEL:
+       gtk_cell_view_set_model (view, g_value_get_object (value));
+       break;
+    default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
         break;
     }
@@ -278,18 +330,14 @@ gtk_cell_view_set_property (GObject      *object,
 static void
 gtk_cell_view_init (GtkCellView *cellview)
 {
-  GTK_WIDGET_SET_FLAGS (cellview, GTK_NO_WINDOW);
+  GtkCellViewPrivate *priv;
 
-  cellview->priv = GTK_CELL_VIEW_GET_PRIVATE (cellview);
-}
+  cellview->priv = G_TYPE_INSTANCE_GET_PRIVATE (cellview,
+                                                GTK_TYPE_CELL_VIEW,
+                                                GtkCellViewPrivate);
+  priv = cellview->priv;
 
-static void
-gtk_cell_view_style_set (GtkWidget *widget,
-                         GtkStyle  *previous_style)
-{
-  if (previous_style && GTK_WIDGET_REALIZED (widget))
-    gdk_window_set_background (widget->window,
-                               &widget->style->base[GTK_WIDGET_STATE (widget)]);
+  gtk_widget_set_has_window (GTK_WIDGET (cellview), FALSE);
 }
 
 static void
@@ -305,145 +353,128 @@ gtk_cell_view_finalize (GObject *object)
   if (cellview->priv->displayed_row)
      gtk_tree_row_reference_free (cellview->priv->displayed_row);
 
-  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+  G_OBJECT_CLASS (gtk_cell_view_parent_class)->finalize (object);
 }
 
 static void
-gtk_cell_view_size_request (GtkWidget      *widget,
-                            GtkRequisition *requisition)
+gtk_cell_view_size_allocate (GtkWidget     *widget,
+                             GtkAllocation *allocation)
 {
-  GList *i;
-  gboolean first_cell = TRUE;
-  GtkCellView *cellview;
+  GtkCellView      *cellview;
+  GtkRequestedSize *sizes;
+  GList            *list;
+  gint              n_visible_cells, n_expand_cells;
+  gint              avail_width = 0;
+  gint              extra_per_cell, extra_extra, i;
+  gboolean          first_cell = TRUE;
+
+  gtk_widget_set_allocation (widget, allocation);
 
   cellview = GTK_CELL_VIEW (widget);
 
-  requisition->width = 0;
-  requisition->height = 0;
+  avail_width = allocation->width;
 
-  if (cellview->priv->displayed_row)
-    gtk_cell_view_set_cell_data (cellview);
-
-  for (i = cellview->priv->cell_list; i; i = i->next)
+  /* Count visible/expand children */
+  for (n_visible_cells = 0, n_expand_cells = 0, list = cellview->priv->cell_list; 
+       list; list = list->next)
     {
-      gint width, height;
-      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
-      if (!info->cell->visible)
-        continue;
-
-      if (!first_cell)
-        requisition->width += cellview->priv->spacing;
-
-      gtk_cell_renderer_get_size (info->cell, widget, NULL, NULL, NULL,
-                                  &width, &height);
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
 
-      info->requested_width = width;
-      requisition->width += width;
-      requisition->height = MAX (requisition->height, height);
+      n_visible_cells++;
 
-      first_cell = FALSE;
+      if (info->expand)
+        n_expand_cells++;
     }
-}
-
-static void
-gtk_cell_view_size_allocate (GtkWidget     *widget,
-                             GtkAllocation *allocation)
-{
-  GList *i;
-  gint expand_cell_count = 0;
-  gint full_requested_width = 0;
-  gint extra_space;
-  GtkCellView *cellview;
 
-  widget->allocation = *allocation;
-
-  cellview = GTK_CELL_VIEW (widget);
+  sizes = g_new0 (GtkRequestedSize, n_visible_cells);
 
   /* checking how much extra space we have */
-  for (i = cellview->priv->cell_list; i; i = i->next)
+  for (i = 0, list = cellview->priv->cell_list; list; list = list->next)
     {
-      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
 
-      if (!info->cell->visible)
+      if (!gtk_cell_renderer_get_visible (info->cell))
         continue;
 
-      if (info->expand)
-        expand_cell_count++;
+      sizes[i].data = info;
+      sizes[i].minimum_size = info->requested_width;
+      sizes[i].natural_size = info->natural_width;
 
-      full_requested_width += info->requested_width;
-    }
+      if (!first_cell)
+       avail_width -= cellview->priv->spacing;
 
-  extra_space = widget->allocation.width - full_requested_width;
-  if (extra_space < 0)
-    extra_space = 0;
-  else if (extra_space > 0 && expand_cell_count > 0)
-    extra_space /= expand_cell_count;
+      avail_width -= sizes[i].minimum_size;
 
-  /* iterate list for PACK_START cells */
-  for (i = cellview->priv->cell_list; i; i = i->next)
-    {
-      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
+      first_cell = FALSE;
 
-      if (info->pack == GTK_PACK_END)
-        continue;
+      i++;
+    }
 
-      if (!info->cell->visible)
-        continue;
+  avail_width = gtk_distribute_natural_allocation (MAX (0, avail_width), n_visible_cells, sizes);
 
-      info->real_width = info->requested_width + (info->expand?extra_space:0);
+  /* Deal with any expand space... */
+  if (n_expand_cells > 0)
+    {
+      extra_per_cell = avail_width / n_expand_cells;
+      extra_extra    = avail_width % n_expand_cells;
     }
+  else
+    /* Everything just left-aligned if no cells expand */
+    extra_per_cell = extra_extra = 0;
 
-  /* iterate list for PACK_END cells */
-  for (i = cellview->priv->cell_list; i; i = i->next)
+  for (i = 0, list = cellview->priv->cell_list; list; list = list->next)
     {
-      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
 
-      if (info->pack == GTK_PACK_START)
+      if (!gtk_cell_renderer_get_visible (info->cell))
         continue;
 
-      if (!info->cell->visible)
-        continue;
+      info->real_width = sizes[i].minimum_size;
 
-      info->real_width = info->requested_width + (info->expand?extra_space:0);
+      if (info->expand)
+        {
+         info->real_width += extra_per_cell;
+
+         if (extra_extra)
+           {
+             info->real_width++;
+             extra_extra--;
+           }
+       }
+      
+      /* increment index into sizes for visible children */
+      i++;
     }
+
+  g_free (sizes);
 }
 
 static gboolean
-gtk_cell_view_expose (GtkWidget      *widget,
-                      GdkEventExpose *event)
+gtk_cell_view_draw (GtkWidget *widget,
+                    cairo_t   *cr)
 {
-  GList *i;
+  GList *list;
   GtkCellView *cellview;
   GdkRectangle area;
   GtkCellRendererState state;
   gboolean rtl = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL);
+  GtkPackType packing;
+  int width;
 
   cellview = GTK_CELL_VIEW (widget);
 
-  if (! GTK_WIDGET_DRAWABLE (widget))
-    return FALSE;
+  /* render cells */
+  area.x = 0;
+  area.y = 0;
+  area.width = width = gtk_widget_get_allocated_width (widget);
+  area.height = gtk_widget_get_allocated_height (widget);
 
   /* "blank" background */
   if (cellview->priv->background_set)
     {
-      GdkGC *gc;
-
-      gc = gdk_gc_new (GTK_WIDGET (cellview)->window);
-      gdk_gc_set_rgb_fg_color (gc, &cellview->priv->background);
-
-      gdk_draw_rectangle (GTK_WIDGET (cellview)->window,
-                          gc,
-                          TRUE,
-
-                          /*0, 0,*/
-                          widget->allocation.x,
-                          widget->allocation.y,
-
-                          widget->allocation.width,
-                          widget->allocation.height);
-
-      g_object_unref (gc);
+      gdk_cairo_rectangle (cr, &area);
+      gdk_cairo_set_source_rgba (cr, &cellview->priv->background);
+      cairo_fill (cr);
     }
 
   /* set cell data (if available) */
@@ -452,67 +483,51 @@ gtk_cell_view_expose (GtkWidget      *widget,
   else if (cellview->priv->model)
     return FALSE;
 
-  /* render cells */
-  area = widget->allocation;
-
-  /* we draw on our very own window, initialize x and y to zero */
-  area.x = widget->allocation.x + (rtl ? widget->allocation.width : 0); 
-  area.y = widget->allocation.y;
-
-  if (GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT)
+  if (gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT)
     state = GTK_CELL_RENDERER_PRELIT;
+  else if (gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE)
+    state = GTK_CELL_RENDERER_INSENSITIVE;
   else
     state = 0;
       
-  /* PACK_START */
-  for (i = cellview->priv->cell_list; i; i = i->next)
+  for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
     {
-      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
-      if (info->pack == GTK_PACK_END)
-        continue;
-
-      if (!info->cell->visible)
-        continue;
-
-      area.width = info->real_width;
-      if (rtl)                                             
-         area.x -= area.width;
-
-      gtk_cell_renderer_render (info->cell,
-                                event->window,
-                                widget,
-                                /* FIXME! */
-                                &area, &area, &event->area, state);
+      if (packing == GTK_PACK_START)
+       area.x = rtl ? width : 0;
+      else
+       area.x = rtl ? 0 : width;
 
-      if (!rtl)                                           
-         area.x += info->real_width;
-    }
-
-   area.x = rtl ? widget->allocation.x : (widget->allocation.x + widget->allocation.width);  
-
-  /* PACK_END */
-  for (i = cellview->priv->cell_list; i; i = i->next)
-    {
-      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
-      if (info->pack == GTK_PACK_START)
-        continue;
-
-      if (!info->cell->visible)
-        continue;
-
-      area.width = info->real_width;
-      if (!rtl)
-         area.x -= area.width;   
-
-      gtk_cell_renderer_render (info->cell,
-                                widget->window,
-                                widget,
-                                /* FIXME ! */
-                                &area, &area, &event->area, state);
-      if (rtl)
-         area.x += info->real_width;
+      for (list = cellview->priv->cell_list; list; list = list->next)
+       {
+         GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+
+         if (info->pack != packing)
+           continue;
+
+         if (!gtk_cell_renderer_get_visible (info->cell))
+           continue;
+
+         area.width = info->real_width;
+
+         if ((packing == GTK_PACK_START && rtl) ||
+             (packing == GTK_PACK_END && !rtl))
+           area.x -= area.width;
+
+         gtk_cell_renderer_render (info->cell,
+                                    cr,
+                                    widget,
+                                    /* FIXME! */
+                                    &area, &area, state);
+
+         if ((packing == GTK_PACK_START && !rtl) ||
+             (packing == GTK_PACK_END && rtl))
+           {
+             area.x += area.width;
+             area.x += cellview->priv->spacing;
+           }
+         else
+           area.x -= cellview->priv->spacing;
+       }
     }
 
   return FALSE;
@@ -591,19 +606,18 @@ gtk_cell_view_cell_layout_pack_start (GtkCellLayout   *layout,
   GtkCellViewCellInfo *info;
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
 
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
   g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
 
-  g_object_ref (renderer);
-  gtk_object_sink (GTK_OBJECT (renderer));
+  g_object_ref_sink (renderer);
 
-  info = g_new0 (GtkCellViewCellInfo, 1);
+  info = g_slice_new0 (GtkCellViewCellInfo);
   info->cell = renderer;
   info->expand = expand ? TRUE : FALSE;
   info->pack = GTK_PACK_START;
 
   cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
+
+  gtk_widget_queue_resize (GTK_WIDGET (cellview));
 }
 
 static void
@@ -614,19 +628,18 @@ gtk_cell_view_cell_layout_pack_end (GtkCellLayout   *layout,
   GtkCellViewCellInfo *info;
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
 
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
   g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
 
-  g_object_ref (renderer);
-  gtk_object_sink (GTK_OBJECT (renderer));
+  g_object_ref_sink (renderer);
 
-  info = g_new0 (GtkCellViewCellInfo, 1);
+  info = g_slice_new0 (GtkCellViewCellInfo);
   info->cell = renderer;
   info->expand = expand ? TRUE : FALSE;
   info->pack = GTK_PACK_END;
 
   cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
+
+  gtk_widget_queue_resize (GTK_WIDGET (cellview));
 }
 
 static void
@@ -638,7 +651,6 @@ gtk_cell_view_cell_layout_add_attribute (GtkCellLayout   *layout,
   GtkCellViewCellInfo *info;
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
 
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
   info = gtk_cell_view_get_cell_info (cellview, renderer);
   g_return_if_fail (info != NULL);
 
@@ -653,15 +665,13 @@ gtk_cell_view_cell_layout_clear (GtkCellLayout *layout)
 {
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
 
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-
   while (cellview->priv->cell_list)
     {
       GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)cellview->priv->cell_list->data;
 
       gtk_cell_view_cell_layout_clear_attributes (layout, info->cell);
       g_object_unref (info->cell);
-      g_free (info);
+      g_slice_free (GtkCellViewCellInfo, info);
       cellview->priv->cell_list = g_list_delete_link (cellview->priv->cell_list, 
                                                      cellview->priv->cell_list);
     }
@@ -677,8 +687,6 @@ gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
   GtkCellViewCellInfo *info;
 
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-
   info = gtk_cell_view_get_cell_info (cellview, cell);
   g_return_if_fail (info != NULL);
 
@@ -699,13 +707,10 @@ static void
 gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout   *layout,
                                             GtkCellRenderer *renderer)
 {
-  GtkCellViewCellInfo *info;
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
+  GtkCellViewCellInfo *info;
   GSList *list;
 
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
   info = gtk_cell_view_get_cell_info (cellview, renderer);
   if (info != NULL)
     {
@@ -726,12 +731,9 @@ gtk_cell_view_cell_layout_reorder (GtkCellLayout   *layout,
                                    GtkCellRenderer *cell,
                                    gint             position)
 {
-  GList *link;
-  GtkCellViewCellInfo *info;
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
-  g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
+  GtkCellViewCellInfo *info;
+  GList *link;
 
   info = gtk_cell_view_get_cell_info (cellview, cell);
 
@@ -742,7 +744,7 @@ gtk_cell_view_cell_layout_reorder (GtkCellLayout   *layout,
 
   g_return_if_fail (link != NULL);
 
-  cellview->priv->cell_list = g_list_remove_link (cellview->priv->cell_list,
+  cellview->priv->cell_list = g_list_delete_link (cellview->priv->cell_list,
                                                   link);
   cellview->priv->cell_list = g_list_insert (cellview->priv->cell_list,
                                              info, position);
@@ -795,7 +797,7 @@ gtk_cell_view_new_with_text (const gchar *text)
 
   g_value_init (&value, G_TYPE_STRING);
   g_value_set_string (&value, text);
-  gtk_cell_view_set_values (cellview, renderer, "text", &value, NULL);
+  gtk_cell_view_set_value (cellview, renderer, "text", &value);
   g_value_unset (&value);
 
   return GTK_WIDGET (cellview);
@@ -806,7 +808,7 @@ gtk_cell_view_new_with_text (const gchar *text)
  * @markup: the text to display in the cell view
  *
  * Creates a new #GtkCellView widget, adds a #GtkCellRendererText 
- * to it, and makes its show @markup. The text can text can be
+ * to it, and makes it show @markup. The text can be
  * marked up with the <link linkend="PangoMarkupFormat">Pango text 
  * markup language</link>.
  *
@@ -829,7 +831,7 @@ gtk_cell_view_new_with_markup (const gchar *markup)
 
   g_value_init (&value, G_TYPE_STRING);
   g_value_set_string (&value, markup);
-  gtk_cell_view_set_values (cellview, renderer, "markup", &value, NULL);
+  gtk_cell_view_set_value (cellview, renderer, "markup", &value);
   g_value_unset (&value);
 
   return GTK_WIDGET (cellview);
@@ -861,7 +863,7 @@ gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf)
 
   g_value_init (&value, GDK_TYPE_PIXBUF);
   g_value_set_object (&value, pixbuf);
-  gtk_cell_view_set_values (cellview, renderer, "pixbuf", &value, NULL);
+  gtk_cell_view_set_value (cellview, renderer, "pixbuf", &value);
   g_value_unset (&value);
 
   return GTK_WIDGET (cellview);
@@ -879,15 +881,12 @@ gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf)
  *
  * Since: 2.6
  */
-void
+static void
 gtk_cell_view_set_value (GtkCellView     *cell_view,
                          GtkCellRenderer *renderer,
                          gchar           *property,
                          GValue          *value)
 {
-  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
   g_object_set_property (G_OBJECT (renderer), property, value);
 
   /* force resize and redraw */
@@ -895,59 +894,13 @@ gtk_cell_view_set_value (GtkCellView     *cell_view,
   gtk_widget_queue_draw (GTK_WIDGET (cell_view));
 }
 
-static void
-gtk_cell_view_set_valuesv (GtkCellView     *cell_view,
-                           GtkCellRenderer *renderer,
-                           va_list          args)
-{
-  gchar *attribute;
-  GValue *value;
-
-  attribute = va_arg (args, gchar *);
-
-  while (attribute)
-    {
-      value = va_arg (args, GValue *);
-      gtk_cell_view_set_value (cell_view, renderer, attribute, value);
-      attribute = va_arg (args, gchar *);
-    }
-}
-
-/**
- * gtk_cell_view_set_values:
- * @cell_view: a #GtkCellView widget
- * @renderer: one of the renderers of @cell_view
- * @Varargs: a list of pairs of property names and #GValue<!-- -->s,
- *   finished by %NULL
- * 
- * Sets multiple properties of a cell renderer of @cell_view, and
- * makes sure the display of @cell_view is updated.
- *
- * Since: 2.6
- */
-void
-gtk_cell_view_set_values (GtkCellView     *cell_view,
-                          GtkCellRenderer *renderer,
-                          ...)
-{
-  va_list args;
-
-  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-  g_return_if_fail (gtk_cell_view_get_cell_info (cell_view, renderer));
-
-  va_start (args, renderer);
-  gtk_cell_view_set_valuesv (cell_view, renderer, args);
-  va_end (args);
-}
-
 /**
  * gtk_cell_view_set_model:
  * @cell_view: a #GtkCellView
- * @model: a #GtkTreeModel
+ * @model: (allow-none): a #GtkTreeModel
  *
  * Sets the model for @cell_view.  If @cell_view already has a model
- * set, it will remove it before setting the new model.  If @model is 
+ * set, it will remove it before setting the new model.  If @model is
  * %NULL, then it will unset the old model.
  *
  * Since: 2.6
@@ -957,7 +910,7 @@ gtk_cell_view_set_model (GtkCellView  *cell_view,
                          GtkTreeModel *model)
 {
   g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
-  g_return_if_fail (GTK_IS_TREE_MODEL (model));
+  g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
 
   if (cell_view->priv->model)
     {
@@ -975,11 +928,30 @@ gtk_cell_view_set_model (GtkCellView  *cell_view,
     g_object_ref (cell_view->priv->model);
 }
 
+/**
+ * gtk_cell_view_get_model:
+ * @cell_view: a #GtkCellView
+ *
+ * Returns the model for @cell_view. If no model is used %NULL is
+ * returned.
+ *
+ * Returns: (transfer none): a #GtkTreeModel used or %NULL
+ *
+ * Since: 2.16
+ **/
+GtkTreeModel *
+gtk_cell_view_get_model (GtkCellView *cell_view)
+{
+  g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), NULL);
+
+  return cell_view->priv->model;
+}
+
 /**
  * gtk_cell_view_set_displayed_row:
  * @cell_view: a #GtkCellView
- * @path: a #GtkTreePath or %NULL to unset.
- * 
+ * @path: (allow-none): a #GtkTreePath or %NULL to unset.
+ *
  * Sets the row of the model that is currently displayed
  * by the #GtkCellView. If the path is unset, then the
  * contents of the cellview "stick" at their last value;
@@ -1012,6 +984,18 @@ gtk_cell_view_set_displayed_row (GtkCellView *cell_view,
   gtk_widget_queue_draw (GTK_WIDGET (cell_view));
 }
 
+/**
+ * gtk_cell_view_get_displayed_row:
+ * @cell_view: a #GtkCellView
+ *
+ * Returns a #GtkTreePath referring to the currently 
+ * displayed row. If no row is currently displayed, 
+ * %NULL is returned.
+ *
+ * Returns: the currently displayed row or %NULL
+ *
+ * Since: 2.6
+ */
 GtkTreePath *
 gtk_cell_view_get_displayed_row (GtkCellView *cell_view)
 {
@@ -1035,32 +1019,108 @@ gtk_cell_view_get_displayed_row (GtkCellView *cell_view)
  * Return value: %TRUE
  *
  * Since: 2.6
+ * 
+ * Deprecated: 3.0: Use gtk_cell_view_get_desired_width_of_row() and
+ * gtk_cell_view_get_desired_height_for_width_of_row() instead.
  */
 gboolean
 gtk_cell_view_get_size_of_row (GtkCellView    *cell_view,
                                GtkTreePath    *path,
                                GtkRequisition *requisition)
 {
-  GtkTreeRowReference *tmp;
   GtkRequisition req;
 
   g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), FALSE);
   g_return_val_if_fail (path != NULL, FALSE);
-  g_return_val_if_fail (requisition != NULL, FALSE);
+
+  /* Return the minimum height for the minimum width */
+  gtk_cell_view_get_desired_width_of_row (cell_view, path, &req.width, NULL);
+  gtk_cell_view_get_desired_height_for_width_of_row (cell_view, path, req.width, &req.height, NULL);
+
+  if (requisition)
+    *requisition = req;
+
+  return TRUE;
+}
+
+
+/**
+ * gtk_cell_view_get_desired_width_of_row:
+ * @cell_view: a #GtkCellView
+ * @path: a #GtkTreePath 
+ * @minimum_size: location to store the minimum size 
+ * @natural_size: location to store the natural size 
+ *
+ * Sets @minimum_size and @natural_size to the width desired by @cell_view 
+ * to display the model row pointed to by @path.
+ * 
+ * Since: 3.0
+ */
+void
+gtk_cell_view_get_desired_width_of_row (GtkCellView     *cell_view,
+                                       GtkTreePath     *path,
+                                       gint            *minimum_size,
+                                       gint            *natural_size)
+{
+  GtkTreeRowReference *tmp;
+
+  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (minimum_size != NULL || natural_size != NULL);
 
   tmp = cell_view->priv->displayed_row;
   cell_view->priv->displayed_row =
     gtk_tree_row_reference_new (cell_view->priv->model, path);
 
-  gtk_cell_view_size_request (GTK_WIDGET (cell_view), requisition);
+  gtk_cell_view_get_preferred_width (GTK_WIDGET (cell_view), minimum_size, natural_size);
 
   gtk_tree_row_reference_free (cell_view->priv->displayed_row);
   cell_view->priv->displayed_row = tmp;
 
-  /* restore actual size info */
-  gtk_cell_view_size_request (GTK_WIDGET (cell_view), &req);
+  /* Restore active size (this will restore the cellrenderer info->width/requested_width's) */
+  gtk_cell_view_get_preferred_width (GTK_WIDGET (cell_view), NULL, NULL);
+}
 
-  return TRUE;
+
+/**
+ * gtk_cell_view_get_desired_height_for_width_of_row:
+ * @cell_view: a #GtkCellView
+ * @path: a #GtkTreePath 
+ * @avail_size: available width
+ * @minimum_size: location to store the minimum height 
+ * @natural_size: location to store the natural height
+ *
+ * Sets @minimum_size and @natural_size to the height desired by @cell_view 
+ * if it were allocated a width of @avail_size to display the model row 
+ * pointed to by @path.
+ * 
+ * Since: 3.0
+ */
+void
+gtk_cell_view_get_desired_height_for_width_of_row (GtkCellView     *cell_view,
+                                                  GtkTreePath     *path,
+                                                  gint             avail_size,
+                                                  gint            *minimum_size,
+                                                  gint            *natural_size)
+{
+  GtkTreeRowReference *tmp;
+
+  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
+  g_return_if_fail (path != NULL);
+  g_return_if_fail (minimum_size != NULL || natural_size != NULL);
+
+  tmp = cell_view->priv->displayed_row;
+  cell_view->priv->displayed_row =
+    gtk_tree_row_reference_new (cell_view->priv->model, path);
+
+  /* Then get the collective height_for_width based on the cached values */
+  gtk_cell_view_get_preferred_height_for_width (GTK_WIDGET (cell_view), avail_size, minimum_size, natural_size);
+
+  gtk_tree_row_reference_free (cell_view->priv->displayed_row);
+  cell_view->priv->displayed_row = tmp;
+
+  /* Restore active size (this will restore the cellrenderer info->width/requested_width's) */
+  gtk_cell_view_get_preferred_width (GTK_WIDGET (cell_view), NULL, NULL);
 }
 
 /**
@@ -1083,38 +1143,67 @@ gtk_cell_view_set_background_color (GtkCellView    *cell_view,
       if (!cell_view->priv->background_set)
         {
           cell_view->priv->background_set = TRUE;
-          g_object_notify (G_OBJECT (cell_view), "background_set");
+          g_object_notify (G_OBJECT (cell_view), "background-set");
         }
 
-      cell_view->priv->background = *color;
+      cell_view->priv->background.red = color->red / 65535.;
+      cell_view->priv->background.green = color->green / 65535.;
+      cell_view->priv->background.blue = color->blue / 65535.;
+      cell_view->priv->background.alpha = 1;
     }
   else
     {
       if (cell_view->priv->background_set)
         {
           cell_view->priv->background_set = FALSE;
-          g_object_notify (G_OBJECT (cell_view), "background_set");
+          g_object_notify (G_OBJECT (cell_view), "background-set");
         }
     }
 
-  gtk_widget_queue_draw (GTK_WIDGET (cellview));
+  gtk_widget_queue_draw (GTK_WIDGET (cell_view));
 }
 
 /**
- * gtk_cell_view_get_cell_renderers:
+ * gtk_cell_view_set_background_rgba:
  * @cell_view: a #GtkCellView
- * 
- * Returns the cell renderers which have been added to @cell_view.
+ * @rgba: the new background color
  *
- * Return value: a list of cell renderers. The list, but not the
- *   renderers has been newly allocated and should be freed with
- *   g_list_free() when no longer needed.
- * 
- * Since: 2.6
+ * Sets the background color of @cell_view.
+ *
+ * Since: 3.0
  */
-GList *
-gtk_cell_view_get_cell_renderers (GtkCellView *cell_view)
+void
+gtk_cell_view_set_background_rgba (GtkCellView   *cell_view,
+                                   const GdkRGBA *rgba)
 {
+  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
+
+  if (rgba)
+    {
+      if (!cell_view->priv->background_set)
+        {
+          cell_view->priv->background_set = TRUE;
+          g_object_notify (G_OBJECT (cell_view), "background-set");
+        }
+
+      cell_view->priv->background = *rgba;
+    }
+  else
+    {
+      if (cell_view->priv->background_set)
+        {
+          cell_view->priv->background_set = FALSE;
+          g_object_notify (G_OBJECT (cell_view), "background-set");
+        }
+    }
+
+  gtk_widget_queue_draw (GTK_WIDGET (cell_view));
+}
+
+static GList *
+gtk_cell_view_cell_layout_get_cells (GtkCellLayout *layout)
+{
+  GtkCellView *cell_view = GTK_CELL_VIEW (layout);
   GList *retval = NULL, *list;
 
   g_return_val_if_fail (cell_view != NULL, NULL);
@@ -1130,3 +1219,216 @@ gtk_cell_view_get_cell_renderers (GtkCellView *cell_view)
 
   return g_list_reverse (retval);
 }
+
+static gboolean
+gtk_cell_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start &&
+      parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+                                                     tagname, parser, data);
+}
+
+static void
+gtk_cell_view_buildable_custom_tag_end (GtkBuildable *buildable,
+                                       GtkBuilder   *builder,
+                                       GObject      *child,
+                                       const gchar  *tagname,
+                                       gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+                                              data);
+  else if (parent_buildable_iface->custom_tag_end)
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+                                           data);
+}
+
+static void
+gtk_cell_view_get_preferred_width  (GtkWidget *widget,
+                                    gint      *minimum_size,
+                                    gint      *natural_size)
+{
+  GList *list;
+  gint cell_min, cell_nat;
+  gboolean first_cell = TRUE;
+  GtkCellView *cellview = GTK_CELL_VIEW (widget);
+  gint minimum, natural;
+
+  minimum = natural = 0;
+
+  if (cellview->priv->displayed_row)
+    gtk_cell_view_set_cell_data (cellview);
+
+  for (list = cellview->priv->cell_list; list; list = list->next)
+    {
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+
+      if (gtk_cell_renderer_get_visible (info->cell))
+        {
+         
+         if (!first_cell)
+           {
+             minimum += cellview->priv->spacing;
+             natural += cellview->priv->spacing;
+           }
+
+         gtk_cell_renderer_get_preferred_width (info->cell,
+                                                 GTK_WIDGET (cellview), &cell_min, &cell_nat);
+         
+         info->requested_width = cell_min;
+         info->natural_width   = cell_nat;
+         
+         minimum += info->requested_width;
+         natural += info->natural_width;
+
+         first_cell = FALSE;
+        }
+    }
+
+  if (minimum_size)
+    *minimum_size = minimum;
+
+  if (natural_size)
+    *natural_size = natural;
+}
+
+static void       
+gtk_cell_view_get_preferred_height (GtkWidget *widget,
+                                    gint      *minimum_size,
+                                    gint      *natural_size)
+{
+  gint minimum_width;
+
+  /* CellViews only need to respond to height-for-width mode (cellview is pretty much
+   * an implementation detail of GtkComboBox) */
+  gtk_cell_view_get_preferred_width (widget, &minimum_width, NULL);
+  gtk_cell_view_get_preferred_height_for_width (widget, minimum_width, minimum_size, natural_size);
+}
+
+static void       
+gtk_cell_view_get_preferred_width_for_height (GtkWidget *widget,
+                                              gint       for_size,
+                                              gint      *minimum_size,
+                                              gint      *natural_size)
+{
+  /* CellViews only need to respond to height-for-width mode (cellview is pretty much
+   * an implementation detail of GtkComboBox) */
+  gtk_cell_view_get_preferred_width (widget, minimum_size, natural_size);
+}
+
+static void       
+gtk_cell_view_get_preferred_height_for_width (GtkWidget *widget,
+                                              gint       for_size,
+                                              gint      *minimum_size,
+                                              gint      *natural_size)
+{
+  GtkCellView      *cellview = GTK_CELL_VIEW (widget);
+  GList            *list;
+  GtkRequestedSize *sizes;
+  GArray           *array;
+  gint              minimum, natural, avail_size;
+  gboolean          first_cell = TRUE;
+  gint              n_expand_cells = 0;
+  gint              extra_per_cell, extra_extra, i;
+
+  minimum = natural = 0;
+  avail_size = for_size;
+
+  array = g_array_new (0, TRUE, sizeof (GtkRequestedSize));
+
+  if (cellview->priv->displayed_row)
+    gtk_cell_view_set_cell_data (cellview);
+
+  /* First allocate the right width to all cells */
+  for (list = cellview->priv->cell_list; list; list = list->next)
+    {
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+
+      if (gtk_cell_renderer_get_visible (info->cell))
+        {
+         GtkRequestedSize requested;
+
+         gtk_cell_renderer_get_preferred_width (GTK_CELL_RENDERER (info->cell),
+                                                 GTK_WIDGET (cellview), 
+                                                 &requested.minimum_size, 
+                                                 &requested.natural_size);
+
+         requested.data = info;
+         g_array_append_val (array, requested);
+
+         avail_size -= requested.minimum_size;
+
+         if (!first_cell)
+           avail_size -= cellview->priv->spacing;
+
+         first_cell = FALSE;
+
+         if (info->expand)
+           n_expand_cells++;
+        }
+    }
+
+  sizes      = (GtkRequestedSize *)array->data;
+  avail_size = gtk_distribute_natural_allocation (MAX (0, avail_size), array->len, sizes);
+
+  /* Deal with any expand space... */
+  if (n_expand_cells > 0)
+    {
+      extra_per_cell = avail_size / n_expand_cells;
+      extra_extra    = avail_size % n_expand_cells;
+    }
+  else
+    /* Everything just left-aligned if no cells expand */
+    extra_per_cell = extra_extra = 0;
+
+  /* Now get the height for the real width of each cell */
+  for (i = 0, list = cellview->priv->cell_list; list; list = list->next)
+    {
+      GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+      gint cell_minimum, cell_natural;
+
+      if (gtk_cell_renderer_get_visible (info->cell))
+        {
+         gint cell_width = sizes[i].minimum_size;
+
+         g_assert (sizes[i].data == info);
+
+         if (info->expand)
+           {
+             cell_width += extra_per_cell;
+             if (extra_extra)
+               {
+                 cell_width++;
+                 extra_extra--;
+               }
+           }
+
+         /* Get the height for the real width of this cell */
+         gtk_cell_renderer_get_preferred_height_for_width (GTK_CELL_RENDERER (info->cell),
+                                                            GTK_WIDGET (widget),
+                                                            cell_width, &cell_minimum, &cell_natural);
+
+         minimum = MAX (minimum, cell_minimum);
+         natural = MAX (natural, cell_natural);
+
+         /* increment sizes[] index for visible cells */
+         i++;
+        }
+    }
+
+  g_array_free (array, TRUE);
+
+  if (minimum_size)
+    *minimum_size = minimum;
+  if (natural_size)
+    *natural_size = natural;
+}