]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcellview.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkcellview.c
index bc5a6ffe463e2cce81e6c060b0fe895d37a59bef..d5d33ede3221e98c238da93eb3607c0dba842931 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -26,7 +24,7 @@
 #include "gtkcellrenderertext.h"
 #include "gtkcellrendererpixbuf.h"
 #include "gtkprivate.h"
-#include "gtksizerequest.h"
+#include "gtkorientableprivate.h"
 #include <gobject/gmarshal.h>
 #include "gtkbuildable.h"
 
  * @Short_description: A widget displaying a single row of a GtkTreeModel
  * @Title: GtkCellView
  *
- * A #GtkCellView displays a single row of a #GtkTreeModel, using
- * cell renderers just like #GtkTreeView. #GtkCellView doesn't support
- * some of the more complex features of #GtkTreeView, like cell editing
- * and drag and drop.
+ * A #GtkCellView displays a single row of a #GtkTreeModel using a #GtkCellArea
+ * and #GtkCellAreaContext. A #GtkCellAreaContext can be provided to the 
+ * #GtkCellView at construction time in order to keep the cellview in context
+ * of a group of cell views, this ensures that the renderers displayed will
+ * be properly aligned with eachother (like the aligned cells in the menus
+ * of #GtkComboBox).
+ *
+ * #GtkCellView is #GtkOrientable in order to decide in which orientation
+ * the underlying #GtkCellAreaContext should be allocated. Taking the #GtkComboBox
+ * menu as an example, cellviews should be oriented horizontally if the menus are
+ * listed top-to-bottom and thus all share the same width but may have separate
+ * individual heights (left-to-right menus should be allocated vertically since
+ * they all share the same height but may have variable widths).
  */
 
-struct _GtkCellViewPrivate
-{
-  GtkTreeModel        *model;
-  GtkTreeRowReference *displayed_row;
-
-  GtkCellArea         *area;
-  GtkCellAreaContext  *context;
-
-  GdkRGBA              background;
-  gboolean             background_set;
-};
-
-
-static void        gtk_cell_view_cell_layout_init         (GtkCellLayoutIface *iface);
 static GObject    *gtk_cell_view_constructor              (GType                  type,
                                                           guint                  n_construct_properties,
                                                           GObjectConstructParam *construct_properties);
@@ -79,31 +72,11 @@ static void        gtk_cell_view_set_value                (GtkCellView     *cell
                                                            GValue          *value);
 static void        gtk_cell_view_set_cell_data            (GtkCellView      *cell_view);
 
-
-static void        gtk_cell_view_cell_layout_pack_start        (GtkCellLayout         *layout,
-                                                                GtkCellRenderer       *renderer,
-                                                                gboolean               expand);
-static void        gtk_cell_view_cell_layout_pack_end          (GtkCellLayout         *layout,
-                                                                GtkCellRenderer       *renderer,
-                                                                gboolean               expand);
-static void        gtk_cell_view_cell_layout_add_attribute     (GtkCellLayout         *layout,
-                                                                GtkCellRenderer       *renderer,
-                                                                const gchar           *attribute,
-                                                                gint                   column);
-static void       gtk_cell_view_cell_layout_clear              (GtkCellLayout         *layout);
-static void       gtk_cell_view_cell_layout_clear_attributes   (GtkCellLayout         *layout,
-                                                                GtkCellRenderer       *renderer);
-static void       gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
-                                                                GtkCellRenderer       *cell,
-                                                                GtkCellLayoutDataFunc  func,
-                                                                gpointer               func_data,
-                                                                GDestroyNotify         destroy);
-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);
+/* celllayout */
+static void        gtk_cell_view_cell_layout_init         (GtkCellLayoutIface *iface);
 static GtkCellArea *gtk_cell_view_cell_layout_get_area         (GtkCellLayout         *layout);
 
+
 /* buildable */
 static void       gtk_cell_view_buildable_init                 (GtkBuildableIface     *iface);
 static gboolean   gtk_cell_view_buildable_custom_tag_start     (GtkBuildable         *buildable,
@@ -118,6 +91,7 @@ static void       gtk_cell_view_buildable_custom_tag_end       (GtkBuildable
                                                                const gchar           *tagname,
                                                                gpointer              *data);
 
+static GtkSizeRequestMode gtk_cell_view_get_request_mode       (GtkWidget             *widget);
 static void       gtk_cell_view_get_preferred_width            (GtkWidget             *widget,
                                                                gint                  *minimum_size,
                                                                gint                  *natural_size);
@@ -133,26 +107,58 @@ static void       gtk_cell_view_get_preferred_height_for_width (GtkWidget
                                                                gint                  *minimum_size,
                                                                gint                  *natural_size);
 
+static void       context_size_changed_cb                      (GtkCellAreaContext   *context,
+                                                               GParamSpec           *pspec,
+                                                               GtkWidget            *view);
+static void       row_changed_cb                               (GtkTreeModel         *model,
+                                                               GtkTreePath          *path,
+                                                               GtkTreeIter          *iter,
+                                                               GtkCellView          *view);
+
+
+struct _GtkCellViewPrivate
+{
+  GtkTreeModel        *model;
+  GtkTreeRowReference *displayed_row;
+
+  GtkCellArea         *area;
+  GtkCellAreaContext  *context;
+
+  GdkRGBA              background;
+
+  gulong               size_changed_id;
+  gulong               row_changed_id;
+
+  GtkOrientation       orientation;
+
+  guint                background_set : 1;
+  guint                draw_sensitive : 1;
+  guint                fit_model      : 1;
+};
+
 static GtkBuildableIface *parent_buildable_iface;
 
 enum
 {
   PROP_0,
+  PROP_ORIENTATION,
   PROP_BACKGROUND,
   PROP_BACKGROUND_GDK,
   PROP_BACKGROUND_RGBA,
   PROP_BACKGROUND_SET,
   PROP_MODEL,
   PROP_CELL_AREA,
-  PROP_CELL_AREA_CONTEXT
+  PROP_CELL_AREA_CONTEXT,
+  PROP_DRAW_SENSITIVE,
+  PROP_FIT_MODEL
 };
 
 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))
-
+                                               gtk_cell_view_buildable_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
 
 static void
 gtk_cell_view_class_init (GtkCellViewClass *klass)
@@ -168,12 +174,15 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
 
   widget_class->draw                           = gtk_cell_view_draw;
   widget_class->size_allocate                  = gtk_cell_view_size_allocate;
+  widget_class->get_request_mode               = gtk_cell_view_get_request_mode;
   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_override_property (gobject_class, PROP_ORIENTATION, "orientation");
+
   g_object_class_install_property (gobject_class,
                                    PROP_BACKGROUND,
                                    g_param_spec_string ("background",
@@ -181,15 +190,23 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
                                                         P_("Background color as a string"),
                                                         NULL,
                                                         GTK_PARAM_WRITABLE));
+
+  /**
+   * GtkCellView:background-gdk:
+   *
+   * The background color as a #GdkColor
+   *
+   * Deprecated: 3.4: Use #GtkCellView:background-rgba instead.
+   */
   g_object_class_install_property (gobject_class,
                                    PROP_BACKGROUND_GDK,
                                    g_param_spec_boxed ("background-gdk",
                                                       P_("Background color"),
                                                       P_("Background color as a GdkColor"),
                                                       GDK_TYPE_COLOR,
-                                                      GTK_PARAM_READWRITE));
+                                                      GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
   /**
-   * GtkCellView:background-rgba
+   * GtkCellView:background-rgba:
    *
    * The background color as a #GdkRGBA
    *
@@ -204,7 +221,7 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
                                                       GTK_PARAM_READWRITE));
 
   /**
-   * GtkCellView:model
+   * GtkCellView:model:
    *
    * The model for cell view
    *
@@ -220,10 +237,13 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
 
 
   /**
-   * GtkCellView:cell-area
+   * GtkCellView:cell-area:
    *
    * The #GtkCellArea rendering cells
    *
+   * If no area is specified when creating the cell view with gtk_cell_view_new_with_context() 
+   * a horizontally oriented #GtkCellAreaBox will be used.
+   *
    * since 3.0
    */
    g_object_class_install_property (gobject_class,
@@ -235,10 +255,19 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   /**
-   * GtkCellView:cell-area-context
+   * GtkCellView:cell-area-context:
    *
    * The #GtkCellAreaContext used to compute the geometry of the cell view.
    *
+   * A group of cell views can be assigned the same context in order to
+   * ensure the sizes and cell alignments match across all the views with
+   * the same context.
+   *
+   * #GtkComboBox menus uses this to assign the same context to all cell views
+   * in the menu items for a single menu (each submenu creates its own
+   * context since the size of each submenu does not depend on parent
+   * or sibling menus).
+   *
    * since 3.0
    */
    g_object_class_install_property (gobject_class,
@@ -250,6 +279,43 @@ gtk_cell_view_class_init (GtkCellViewClass *klass)
                                                         GTK_TYPE_CELL_AREA_CONTEXT,
                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
+  /**
+   * GtkCellView:draw-sensitive:
+   *
+   * Whether all cells should be draw as sensitive for this view regardless
+   * of the actual cell properties (used to make menus with submenus appear
+   * sensitive when the items in submenus might be insensitive).
+   *
+   * since 3.0
+   */
+   g_object_class_install_property (gobject_class,
+                                    PROP_DRAW_SENSITIVE,
+                                    g_param_spec_boolean ("draw-sensitive",
+                                                         P_("Draw Sensitive"),
+                                                         P_("Whether to force cells to be drawn in a "
+                                                            "sensitive state"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkCellView:fit-model:
+   *
+   * Whether the view should request enough space to always fit
+   * the size of every row in the model (used by the combo box to
+   * ensure the combo box size doesnt change when different items
+   * are selected).
+   *
+   * since 3.0
+   */
+   g_object_class_install_property (gobject_class,
+                                    PROP_FIT_MODEL,
+                                    g_param_spec_boolean ("fit-model",
+                                                         P_("Fit Model"),
+                                                         P_("Whether to request enough space for "
+                                                            "every row in the model"),
+                                                         FALSE,
+                                                         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))
 
@@ -272,14 +338,6 @@ gtk_cell_view_buildable_init (GtkBuildableIface *iface)
 static void
 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
 {
-  iface->pack_start = gtk_cell_view_cell_layout_pack_start;
-  iface->pack_end = gtk_cell_view_cell_layout_pack_end;
-  iface->clear = gtk_cell_view_cell_layout_clear;
-  iface->add_attribute = gtk_cell_view_cell_layout_add_attribute;
-  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;
   iface->get_area = gtk_cell_view_cell_layout_get_area;
 }
 
@@ -300,14 +358,17 @@ gtk_cell_view_constructor (GType                  type,
 
   if (!priv->area)
     {
-      GtkCellArea *area = gtk_cell_area_box_new ();
-
-      priv->area = g_object_ref_sink (area);
+      priv->area = gtk_cell_area_box_new ();
+      g_object_ref_sink (priv->area);
     }
 
   if (!priv->context)
     priv->context = gtk_cell_area_create_context (priv->area);
 
+  priv->size_changed_id =
+    g_signal_connect (priv->context, "notify",
+                     G_CALLBACK (context_size_changed_cb), view);
+
   return object;
 }
 
@@ -321,36 +382,45 @@ gtk_cell_view_get_property (GObject    *object,
 
   switch (param_id)
     {
-      case PROP_BACKGROUND_GDK:
-        {
-          GdkColor color;
-
-          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;
-      case PROP_CELL_AREA:
-       g_value_set_object (value, view->priv->area);
-       break;
-      case PROP_CELL_AREA_CONTEXT:
-       g_value_set_object (value, view->priv->context);
-       break;
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-        break;
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, view->priv->orientation);
+      break;
+    case PROP_BACKGROUND_GDK:
+      {
+       GdkColor color;
+       
+       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;
+    case PROP_CELL_AREA:
+      g_value_set_object (value, view->priv->area);
+      break;
+    case PROP_CELL_AREA_CONTEXT:
+      g_value_set_object (value, view->priv->context);
+      break;
+    case PROP_DRAW_SENSITIVE:
+      g_value_set_boolean (value, view->priv->draw_sensitive);
+      break;
+    case PROP_FIT_MODEL:
+      g_value_set_boolean (value, view->priv->fit_model);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
     }
 }
 
@@ -361,50 +431,97 @@ gtk_cell_view_set_property (GObject      *object,
                             GParamSpec   *pspec)
 {
   GtkCellView *view = GTK_CELL_VIEW (object);
+  GtkCellViewPrivate *priv = view->priv;
   GtkCellArea *area;
   GtkCellAreaContext *context;
 
   switch (param_id)
     {
-      case PROP_BACKGROUND:
-        {
-          GdkColor color;
+    case PROP_ORIENTATION:
+      priv->orientation = g_value_get_enum (value);
+      if (priv->context)
+        gtk_cell_area_context_reset (priv->context);
 
-          if (!g_value_get_string (value))
-            gtk_cell_view_set_background_color (view, NULL);
-          else if (gdk_color_parse (g_value_get_string (value), &color))
-            gtk_cell_view_set_background_color (view, &color);
-          else
-            g_warning ("Don't know color `%s'", g_value_get_string (value));
+      _gtk_orientable_set_style_classes (GTK_ORIENTABLE (object));
+      break;
+    case PROP_BACKGROUND:
+      {
+        GdkRGBA color;
+
+       if (!g_value_get_string (value))
+          gtk_cell_view_set_background_rgba (view, NULL);
+       else if (gdk_rgba_parse (&color, g_value_get_string (value)))
+          gtk_cell_view_set_background_rgba (view, &color);
+       else
+         g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+        g_object_notify (object, "background-rgba");
+        g_object_notify (object, "background-gdk");
+      }
+      break;
+    case PROP_BACKGROUND_GDK:
+      {
+        GdkColor *color;
+        GdkRGBA rgba;
 
-          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;
-      case PROP_MODEL:
-       gtk_cell_view_set_model (view, g_value_get_object (value));
-       break;
+        color = g_value_get_boxed (value);
+
+        rgba.red = color->red / 65535.0;
+        rgba.green = color->green / 65535.0;
+        rgba.blue = color->blue / 65535.0;
+        rgba.alpha = 1.0;
+
+        gtk_cell_view_set_background_rgba (view, &rgba);
+      }
+      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;
+    case PROP_MODEL:
+      gtk_cell_view_set_model (view, g_value_get_object (value));
+      break;
     case PROP_CELL_AREA:
       /* Construct-only, can only be assigned once */
       area = g_value_get_object (value);
 
       if (area)
-       view->priv->area = g_object_ref_sink (area);
+        {
+          if (priv->area != NULL)
+            {
+              g_warning ("cell-area has already been set, ignoring construct property");
+              g_object_ref_sink (area);
+              g_object_unref (area);
+            }
+          else
+            priv->area = g_object_ref_sink (area);
+        }
       break;
     case PROP_CELL_AREA_CONTEXT:
       /* Construct-only, can only be assigned once */
       context = g_value_get_object (value);
 
       if (context)
-       view->priv->context = g_object_ref (context);
+        {
+          if (priv->context != NULL)
+            {
+              g_warning ("cell-area-context has already been set, ignoring construct property");
+              g_object_ref_sink (context);
+              g_object_unref (context);
+            }
+          else
+            priv->context = g_object_ref (context);
+        }
+      break;
+
+    case PROP_DRAW_SENSITIVE:
+      gtk_cell_view_set_draw_sensitive (view, g_value_get_boolean (value));
+      break;
+
+    case PROP_FIT_MODEL:
+      gtk_cell_view_set_fit_model (view, g_value_get_boolean (value));
       break;
 
     default:
@@ -424,6 +541,8 @@ gtk_cell_view_init (GtkCellView *cellview)
   priv = cellview->priv;
 
   gtk_widget_set_has_window (GTK_WIDGET (cellview), FALSE);
+
+  priv->orientation = GTK_ORIENTATION_HORIZONTAL;
 }
 
 static void
@@ -442,13 +561,7 @@ gtk_cell_view_dispose (GObject *object)
 {
   GtkCellView *cellview = GTK_CELL_VIEW (object);
 
-  gtk_cell_view_cell_layout_clear (GTK_CELL_LAYOUT (cellview));
-
-  if (cellview->priv->model)
-    {
-      g_object_unref (cellview->priv->model);
-      cellview->priv->model = NULL;
-    }
+  gtk_cell_view_set_model (cellview, NULL);
 
   if (cellview->priv->area)
     {
@@ -458,8 +571,11 @@ gtk_cell_view_dispose (GObject *object)
 
   if (cellview->priv->context)
     {
+      g_signal_handler_disconnect (cellview->priv->context, cellview->priv->size_changed_id);
+
       g_object_unref (cellview->priv->context);
       cellview->priv->context = NULL;
+      cellview->priv->size_changed_id = 0;
     }
 
   G_OBJECT_CLASS (gtk_cell_view_parent_class)->dispose (object);
@@ -478,11 +594,186 @@ gtk_cell_view_size_allocate (GtkWidget     *widget,
   gtk_cell_area_context_get_allocation (priv->context, &alloc_width, &alloc_height);
 
   /* The first cell view in context is responsible for allocating the context at allocate time 
-   * (or the cellview has its own context and is not grouped with any other cell views) */
-  if (alloc_width <= 0 && alloc_height <= 0)
+   * (or the cellview has its own context and is not grouped with any other cell views) 
+   *
+   * If the cellview is in "fit model" mode, we assume it's not in context and needs to
+   * allocate every time.
+   */
+  if (priv->fit_model)
+    gtk_cell_area_context_allocate (priv->context, allocation->width, allocation->height);
+  else if (alloc_width != allocation->width && priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+    gtk_cell_area_context_allocate (priv->context, allocation->width, -1);
+  else if (alloc_height != allocation->height && priv->orientation == GTK_ORIENTATION_VERTICAL)
+    gtk_cell_area_context_allocate (priv->context, -1, allocation->height);
+}
+
+static void
+gtk_cell_view_request_model (GtkCellView        *cellview,
+                            GtkTreeIter        *parent,
+                            GtkOrientation      orientation,
+                            gint                for_size,
+                            gint               *minimum_size,
+                            gint               *natural_size)
+{
+  GtkCellViewPrivate *priv = cellview->priv;
+  GtkTreeIter         iter;
+  gboolean            valid;
+
+  if (!priv->model)
+    return;
+
+  valid = gtk_tree_model_iter_children (priv->model, &iter, parent);
+  while (valid)
+    {
+      gint min, nat;
+
+      gtk_cell_area_apply_attributes (priv->area, priv->model, &iter, FALSE, FALSE);
+
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+       {
+         if (for_size < 0)
+           gtk_cell_area_get_preferred_width (priv->area, priv->context, 
+                                              GTK_WIDGET (cellview), &min, &nat);
+         else
+           gtk_cell_area_get_preferred_width_for_height (priv->area, priv->context, 
+                                                         GTK_WIDGET (cellview), for_size, &min, &nat);
+       }
+      else
+       {
+         if (for_size < 0)
+           gtk_cell_area_get_preferred_height (priv->area, priv->context, 
+                                               GTK_WIDGET (cellview), &min, &nat);
+         else
+           gtk_cell_area_get_preferred_height_for_width (priv->area, priv->context, 
+                                                         GTK_WIDGET (cellview), for_size, &min, &nat);
+       }
+
+      *minimum_size = MAX (min, *minimum_size);
+      *natural_size = MAX (nat, *natural_size);
+
+      /* Recurse into children when they exist */
+      gtk_cell_view_request_model (cellview, &iter, orientation, for_size, minimum_size, natural_size);
+
+      valid = gtk_tree_model_iter_next (priv->model, &iter);
+    }
+}
+
+static GtkSizeRequestMode 
+gtk_cell_view_get_request_mode (GtkWidget *widget)
+{
+  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
+  GtkCellViewPrivate *priv = cellview->priv;
+
+  return gtk_cell_area_get_request_mode (priv->area);
+}
+
+static void
+gtk_cell_view_get_preferred_width  (GtkWidget *widget,
+                                    gint      *minimum_size,
+                                    gint      *natural_size)
+{
+  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
+  GtkCellViewPrivate *priv = cellview->priv;
+
+  g_signal_handler_block (priv->context, priv->size_changed_id);
+
+  if (priv->fit_model)
+    {
+      gint min = 0, nat = 0;
+      gtk_cell_view_request_model (cellview, NULL, GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat);
+    }
+  else
     {
-      gtk_cell_area_context_allocate_width (priv->context, allocation->width);
-      gtk_cell_area_context_allocate_height (priv->context, allocation->height);
+      if (cellview->priv->displayed_row)
+       gtk_cell_view_set_cell_data (cellview);
+
+      gtk_cell_area_get_preferred_width (priv->area, priv->context, widget, NULL, NULL);
+    }
+
+  gtk_cell_area_context_get_preferred_width (priv->context, minimum_size, natural_size);
+
+  g_signal_handler_unblock (priv->context, priv->size_changed_id);
+}
+
+static void       
+gtk_cell_view_get_preferred_height (GtkWidget *widget,
+                                    gint      *minimum_size,
+                                    gint      *natural_size)
+{
+  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
+  GtkCellViewPrivate *priv = cellview->priv;
+
+  g_signal_handler_block (priv->context, priv->size_changed_id);
+
+  if (priv->fit_model)
+    {
+      gint min = 0, nat = 0;
+      gtk_cell_view_request_model (cellview, NULL, GTK_ORIENTATION_VERTICAL, -1, &min, &nat);
+    }
+  else
+    {
+      if (cellview->priv->displayed_row)
+       gtk_cell_view_set_cell_data (cellview);
+      
+      gtk_cell_area_get_preferred_height (priv->area, priv->context, widget, NULL, NULL);
+    }
+
+  gtk_cell_area_context_get_preferred_height (priv->context, minimum_size, natural_size);
+
+  g_signal_handler_unblock (priv->context, priv->size_changed_id);
+}
+
+static void       
+gtk_cell_view_get_preferred_width_for_height (GtkWidget *widget,
+                                              gint       for_size,
+                                              gint      *minimum_size,
+                                              gint      *natural_size)
+{
+  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
+  GtkCellViewPrivate *priv = cellview->priv;
+
+  if (priv->fit_model)
+    {
+      gint min = 0, nat = 0;
+      gtk_cell_view_request_model (cellview, NULL, GTK_ORIENTATION_HORIZONTAL, for_size, &min, &nat);
+
+      *minimum_size = min;
+      *natural_size = nat;
+    }
+  else
+    {
+      if (cellview->priv->displayed_row)
+       gtk_cell_view_set_cell_data (cellview);
+
+      gtk_cell_area_get_preferred_width_for_height (priv->area, priv->context, widget, 
+                                                   for_size, 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);
+  GtkCellViewPrivate *priv = cellview->priv;
+
+  if (priv->fit_model)
+    {
+      gint min = 0, nat = 0;
+      gtk_cell_view_request_model (cellview, NULL, GTK_ORIENTATION_VERTICAL, for_size, &min, &nat);
+
+      *minimum_size = min;
+      *natural_size = nat;
+    }
+  else
+    {
+      if (cellview->priv->displayed_row)
+       gtk_cell_view_set_cell_data (cellview);
+
+      gtk_cell_area_get_preferred_height_for_width (priv->area, priv->context, widget, 
+                                                   for_size, minimum_size, natural_size);
     }
 }
 
@@ -518,8 +809,6 @@ gtk_cell_view_draw (GtkWidget *widget,
 
   if (gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_PRELIGHT)
     state = GTK_CELL_RENDERER_PRELIT;
-  else if (gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_INSENSITIVE)
-    state = GTK_CELL_RENDERER_INSENSITIVE;
   else
     state = 0;
       
@@ -548,101 +837,105 @@ gtk_cell_view_set_cell_data (GtkCellView *cell_view)
   gtk_cell_area_apply_attributes (cell_view->priv->area, 
                                  cell_view->priv->model, 
                                  &iter, FALSE, FALSE);
-}
 
-/* GtkCellLayout implementation */
-static void
-gtk_cell_view_cell_layout_pack_start (GtkCellLayout   *layout,
-                                      GtkCellRenderer *renderer,
-                                      gboolean         expand)
-{
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
+  if (cell_view->priv->draw_sensitive)
+    {
+      GList *l, *cells = 
+       gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_view->priv->area));
 
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview->priv->area), renderer, expand);
+      for (l = cells; l; l = l->next)
+       {
+         GObject *renderer = l->data;
 
-  gtk_widget_queue_resize (GTK_WIDGET (cellview));
+         g_object_set (renderer, "sensitive", TRUE, NULL);
+       }
+      g_list_free (cells);
+    }
 }
 
-static void
-gtk_cell_view_cell_layout_pack_end (GtkCellLayout   *layout,
-                                    GtkCellRenderer *renderer,
-                                    gboolean         expand)
+/* GtkCellLayout implementation */
+static GtkCellArea *
+gtk_cell_view_cell_layout_get_area (GtkCellLayout   *layout)
 {
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
+  GtkCellViewPrivate *priv = cellview->priv;
 
-  gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (cellview->priv->area), renderer, expand);
-
-  gtk_widget_queue_resize (GTK_WIDGET (cellview));
-}
-
-static void
-gtk_cell_view_cell_layout_add_attribute (GtkCellLayout   *layout,
-                                         GtkCellRenderer *renderer,
-                                         const gchar     *attribute,
-                                         gint             column)
-{
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
+  if (G_UNLIKELY (!priv->area))
+    {
+      priv->area = gtk_cell_area_box_new ();
+      g_object_ref_sink (priv->area);
+    }
 
-  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (cellview->priv->area), renderer, 
-                                attribute, column);
+  return priv->area;
 }
 
-static void
-gtk_cell_view_cell_layout_clear (GtkCellLayout *layout)
+/* GtkBuildable implementation */
+static gboolean
+gtk_cell_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data)
 {
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
+  if (parent_buildable_iface->custom_tag_start &&
+      parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                               tagname, parser, data))
+    return TRUE;
 
-  if (cellview->priv->area)
-    gtk_cell_layout_clear (GTK_CELL_LAYOUT (cellview->priv->area));
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+                                                     tagname, parser, data);
 }
 
 static void
-gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
-                                              GtkCellRenderer       *cell,
-                                              GtkCellLayoutDataFunc  func,
-                                              gpointer               func_data,
-                                              GDestroyNotify         destroy)
+gtk_cell_view_buildable_custom_tag_end (GtkBuildable *buildable,
+                                       GtkBuilder   *builder,
+                                       GObject      *child,
+                                       const gchar  *tagname,
+                                       gpointer     *data)
 {
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
-  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (cellview->priv->area),
-                                     cell, func, func_data, destroy);
+  if (_gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+                                                data))
+    return;
+  else if (parent_buildable_iface->custom_tag_end)
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+                                           data);
 }
 
 static void
-gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout   *layout,
-                                            GtkCellRenderer *renderer)
+context_size_changed_cb (GtkCellAreaContext  *context,
+                        GParamSpec          *pspec,
+                        GtkWidget           *view)
 {
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
-  gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (cellview->priv->area), renderer);
+  if (!strcmp (pspec->name, "minimum-width") ||
+      !strcmp (pspec->name, "natural-width") ||
+      !strcmp (pspec->name, "minimum-height") ||
+      !strcmp (pspec->name, "natural-height"))
+    gtk_widget_queue_resize (view);
 }
 
 static void
-gtk_cell_view_cell_layout_reorder (GtkCellLayout   *layout,
-                                   GtkCellRenderer *cell,
-                                   gint             position)
+row_changed_cb (GtkTreeModel         *model,
+               GtkTreePath          *path,
+               GtkTreeIter          *iter,
+               GtkCellView          *view)
 {
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
-  gtk_cell_layout_reorder (GTK_CELL_LAYOUT (cellview->priv->area), cell, position);
-}
+  GtkTreePath *row_path;
 
+  if (view->priv->displayed_row)
+    {
+      row_path = 
+       gtk_tree_row_reference_get_path (view->priv->displayed_row);
 
-static GList *
-gtk_cell_view_cell_layout_get_cells (GtkCellLayout *layout)
-{
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
+      if (row_path)
+       {
+         /* Resize everything in our context if our row changed */
+         if (gtk_tree_path_compare (row_path, path) == 0)
+           gtk_cell_area_context_reset (view->priv->context);
 
-  return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cellview->priv->area));
-}
-
-static GtkCellArea *
-gtk_cell_view_cell_layout_get_area (GtkCellLayout   *layout)
-{
-  GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
-  return cellview->priv->area;
+         gtk_tree_path_free (row_path);
+       }
+    }
 }
 
 /**
@@ -700,7 +993,7 @@ gtk_cell_view_new_with_context (GtkCellArea        *area,
  * @text: the text to display in the cell view
  *
  * Creates a new #GtkCellView widget, adds a #GtkCellRendererText 
- * to it, and makes its show @text.
+ * to it, and makes it show @text.
  *
  * Return value: A newly created #GtkCellView widget.
  *
@@ -711,13 +1004,13 @@ gtk_cell_view_new_with_text (const gchar *text)
 {
   GtkCellView *cellview;
   GtkCellRenderer *renderer;
-  GValue value = {0, };
+  GValue value = G_VALUE_INIT;
 
   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
 
   renderer = gtk_cell_renderer_text_new ();
-  gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
-                                        renderer, TRUE);
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
+                             renderer, TRUE);
 
   g_value_init (&value, G_TYPE_STRING);
   g_value_set_string (&value, text);
@@ -745,13 +1038,13 @@ gtk_cell_view_new_with_markup (const gchar *markup)
 {
   GtkCellView *cellview;
   GtkCellRenderer *renderer;
-  GValue value = {0, };
+  GValue value = G_VALUE_INIT;
 
   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
 
   renderer = gtk_cell_renderer_text_new ();
-  gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
-                                        renderer, TRUE);
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
+                             renderer, TRUE);
 
   g_value_init (&value, G_TYPE_STRING);
   g_value_set_string (&value, markup);
@@ -765,8 +1058,8 @@ gtk_cell_view_new_with_markup (const gchar *markup)
  * gtk_cell_view_new_with_pixbuf:
  * @pixbuf: the image to display in the cell view
  *
- * Creates a new #GtkCellView widget, adds a #GtkCellRendererPixbuf 
- * to it, and makes its show @pixbuf. 
+ * Creates a new #GtkCellView widget, adds a #GtkCellRendererPixbuf
+ * to it, and makes it show @pixbuf.
  *
  * Return value: A newly created #GtkCellView widget.
  *
@@ -777,13 +1070,13 @@ gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf)
 {
   GtkCellView *cellview;
   GtkCellRenderer *renderer;
-  GValue value = {0, };
+  GValue value = G_VALUE_INIT;
 
   cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
 
   renderer = gtk_cell_renderer_pixbuf_new ();
-  gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
-                                        renderer, TRUE);
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
+                             renderer, TRUE);
 
   g_value_init (&value, GDK_TYPE_PIXBUF);
   g_value_set_object (&value, pixbuf);
@@ -838,18 +1131,27 @@ gtk_cell_view_set_model (GtkCellView  *cell_view,
 
   if (cell_view->priv->model)
     {
+      g_signal_handler_disconnect (cell_view->priv->model, 
+                                  cell_view->priv->row_changed_id);
+      cell_view->priv->row_changed_id = 0;
+
       if (cell_view->priv->displayed_row)
         gtk_tree_row_reference_free (cell_view->priv->displayed_row);
       cell_view->priv->displayed_row = NULL;
 
       g_object_unref (cell_view->priv->model);
-      cell_view->priv->model = NULL;
     }
 
   cell_view->priv->model = model;
 
   if (cell_view->priv->model)
-    g_object_ref (cell_view->priv->model);
+    {
+      g_object_ref (cell_view->priv->model);
+
+      cell_view->priv->row_changed_id = 
+       g_signal_connect (cell_view->priv->model, "row-changed",
+                         G_CALLBACK (row_changed_cb), cell_view);
+    }
 }
 
 /**
@@ -935,7 +1237,7 @@ gtk_cell_view_get_displayed_row (GtkCellView *cell_view)
  * gtk_cell_view_get_size_of_row:
  * @cell_view: a #GtkCellView
  * @path: a #GtkTreePath 
- * @requisition: return location for the size 
+ * @requisition: (out): return location for the size 
  *
  * Sets @requisition to the size needed by @cell_view to display 
  * the model row pointed to by @path.
@@ -944,107 +1246,36 @@ gtk_cell_view_get_displayed_row (GtkCellView *cell_view)
  *
  * 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.
+ * Deprecated: 3.0: Combo box formerly used this to calculate the
+ * sizes for cellviews, now you can achieve this by either using
+ * the #GtkCellView:fit-model property or by setting the currently
+ * displayed row of the #GtkCellView and using gtk_widget_get_preferred_size().
  */
 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);
 
-  /* 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_get_preferred_width (GTK_WIDGET (cell_view), minimum_size, natural_size);
+  gtk_widget_get_preferred_width (GTK_WIDGET (cell_view), &req.width, NULL);
+  gtk_widget_get_preferred_height_for_width (GTK_WIDGET (cell_view), req.width, &req.height, NULL);
 
   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);
-}
-
-
-/**
- * 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;
+  if (requisition)
+    *requisition = 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;
 }
 
 /**
@@ -1055,6 +1286,8 @@ gtk_cell_view_get_desired_height_for_width_of_row (GtkCellView     *cell_view,
  * Sets the background color of @view.
  *
  * Since: 2.6
+ *
+ * Deprecated: 3.4: Use gtk_cell_view_set_background_rgba() instead.
  */
 void
 gtk_cell_view_set_background_color (GtkCellView    *cell_view,
@@ -1124,98 +1357,113 @@ gtk_cell_view_set_background_rgba (GtkCellView   *cell_view,
   gtk_widget_queue_draw (GTK_WIDGET (cell_view));
 }
 
-static gboolean
-gtk_cell_view_buildable_custom_tag_start (GtkBuildable  *buildable,
-                                         GtkBuilder    *builder,
-                                         GObject       *child,
-                                         const gchar   *tagname,
-                                         GMarkupParser *parser,
-                                         gpointer      *data)
+/**
+ * gtk_cell_view_get_draw_sensitive:
+ * @cell_view: a #GtkCellView
+ *
+ * Gets whether @cell_view is configured to draw all of its
+ * cells in a sensitive state.
+ *
+ * Return value: whether @cell_view draws all of its
+ * cells in a sensitive state
+ *
+ * Since: 3.0
+ */
+gboolean
+gtk_cell_view_get_draw_sensitive (GtkCellView     *cell_view)
 {
-  if (parent_buildable_iface->custom_tag_start &&
-      parent_buildable_iface->custom_tag_start (buildable, builder, child,
-                                               tagname, parser, data))
-    return TRUE;
+  GtkCellViewPrivate *priv;
 
-  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
-                                                     tagname, parser, data);
-}
+  g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), FALSE);
 
-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);
+  priv = cell_view->priv;
+
+  return priv->draw_sensitive;
 }
 
-static void
-gtk_cell_view_get_preferred_width  (GtkWidget *widget,
-                                    gint      *minimum_size,
-                                    gint      *natural_size)
+/**
+ * gtk_cell_view_set_draw_sensitive:
+ * @cell_view: a #GtkCellView
+ * @draw_sensitive: whether to draw all cells in a sensitive state.
+ *
+ * Sets whether @cell_view should draw all of its
+ * cells in a sensitive state, this is used by #GtkComboBox menus
+ * to ensure that rows with insensitive cells that contain
+ * children appear sensitive in the parent menu item.
+ *
+ * Since: 3.0
+ */
+void
+gtk_cell_view_set_draw_sensitive (GtkCellView     *cell_view,
+                                 gboolean         draw_sensitive)
 {
-  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
-  GtkCellViewPrivate *priv = cellview->priv;
+  GtkCellViewPrivate *priv;
 
-  if (cellview->priv->displayed_row)
-    gtk_cell_view_set_cell_data (cellview);
+  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
 
-  gtk_cell_area_get_preferred_width (priv->area, priv->context, widget, NULL, NULL);
-  gtk_cell_area_context_sum_preferred_width (priv->context);
-  gtk_cell_area_context_get_preferred_width (priv->context, minimum_size, natural_size);
+  priv = cell_view->priv;
+
+  if (priv->draw_sensitive != draw_sensitive)
+    {
+      priv->draw_sensitive = draw_sensitive;
+
+      g_object_notify (G_OBJECT (cell_view), "draw-sensitive");
+    }
 }
 
-static void       
-gtk_cell_view_get_preferred_height (GtkWidget *widget,
-                                    gint      *minimum_size,
-                                    gint      *natural_size)
+/**
+ * gtk_cell_view_get_fit_model:
+ * @cell_view: a #GtkCellView
+ *
+ * Gets whether @cell_view is configured to request space
+ * to fit the entire #GtkTreeModel.
+ *
+ * Return value: whether @cell_view requests space to fit
+ * the entire #GtkTreeModel.
+ *
+ * Since: 3.0
+ */
+gboolean
+gtk_cell_view_get_fit_model (GtkCellView     *cell_view)
 {
-  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
-  GtkCellViewPrivate *priv = cellview->priv;
+  GtkCellViewPrivate *priv;
 
-  if (cellview->priv->displayed_row)
-    gtk_cell_view_set_cell_data (cellview);
+  g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), FALSE);
 
-  gtk_cell_area_get_preferred_height (priv->area, priv->context, widget, NULL, NULL);
-  gtk_cell_area_context_sum_preferred_height (priv->context);
-  gtk_cell_area_context_get_preferred_height (priv->context, minimum_size, natural_size);
+  priv = cell_view->priv;
+
+  return priv->fit_model;
 }
 
-static void       
-gtk_cell_view_get_preferred_width_for_height (GtkWidget *widget,
-                                              gint       for_size,
-                                              gint      *minimum_size,
-                                              gint      *natural_size)
+/**
+ * gtk_cell_view_set_fit_model:
+ * @cell_view: a #GtkCellView
+ * @fit_model: whether @cell_view should request space for the whole model.
+ *
+ * Sets whether @cell_view should request space to fit the entire #GtkTreeModel.
+ *
+ * This is used by #GtkComboBox to ensure that the cell view displayed on
+ * the combo box's button always gets enough space and does not resize
+ * when selection changes.
+ *
+ * Since: 3.0
+ */
+void
+gtk_cell_view_set_fit_model (GtkCellView *cell_view,
+                             gboolean     fit_model)
 {
-  GtkCellView        *cellview = GTK_CELL_VIEW (widget);
-  GtkCellViewPrivate *priv = cellview->priv;
+  GtkCellViewPrivate *priv;
 
-  if (cellview->priv->displayed_row)
-    gtk_cell_view_set_cell_data (cellview);
+  g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
 
-  gtk_cell_area_get_preferred_width_for_height (priv->area, priv->context, widget, 
-                                               for_size, minimum_size, natural_size);
-}
+  priv = cell_view->priv;
 
-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);
-  GtkCellViewPrivate *priv = cellview->priv;
+  if (priv->fit_model != fit_model)
+    {
+      priv->fit_model = fit_model;
 
-  if (cellview->priv->displayed_row)
-    gtk_cell_view_set_cell_data (cellview);
+      gtk_cell_area_context_reset (cell_view->priv->context);
 
-  gtk_cell_area_get_preferred_height_for_width (priv->area, priv->context, widget, 
-                                               for_size, minimum_size, natural_size);
+      g_object_notify (G_OBJECT (cell_view), "fit-model");
+    }
 }