[gtk+] Bandaid fix for icon view subclassing



commit 726b0d8736a9d5ac8d7f2395f234662b204290fc
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Jan 31 17:34:37 2011 -0500

    Bandaid fix for icon view subclassing
    
    I've decided that it is isn't feasible to make cell areas runtime-settable
    in the time we have left before 3.0, therefore, I'm going with the
    approach to allow init() functions to instantiate the default cell area
    and issue a warning if a construct property is ignored.
    
    This is not ideal, but it keeps existing icon view and combo box
    subclasses working.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=639139

 gtk/gtkcelllayout.c      |   49 +++
 gtk/gtkcellview.c        |   53 +++-
 gtk/gtkcellview.h        |    6 +-
 gtk/gtkcombobox.c        |   46 ++-
 gtk/gtkentrycompletion.c |   24 +-
 gtk/gtkiconview.c        |   79 +++--
 gtk/gtktreeviewcolumn.c  |   86 ++++--
 gtk/tests/Makefile.am    |    4 +
 gtk/tests/cellarea.c     |  855 ++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 1111 insertions(+), 91 deletions(-)
---
diff --git a/gtk/gtkcelllayout.c b/gtk/gtkcelllayout.c
index 7291a4b..d0ff6ca 100644
--- a/gtk/gtkcelllayout.c
+++ b/gtk/gtkcelllayout.c
@@ -83,6 +83,55 @@
  * </example>
  * </para>
  * </refsect2>
+ *
+ * <refsect2>
+ * <title>Subclassing GtkCellLayout implementations</title>
+ * <para>
+ * When subclassing a widget that implements #GtkCellLayout like
+ * #GtkIconView or #GtkComboBox, there are some considerations related
+ * to the fact that these widgets internally use a #GtkCellArea.
+ * The cell area is exposed as a construct-only property by these
+ * widgets. This means that it is possible to e.g. do
+ * <informalexample><programlisting>
+ * combo = g_object_new (GTK_TYPE_COMBO_BOX, "cell-area", my_cell_area, NULL);
+ * </programlisting></informalexample>
+ * to use a custom cell area with a combo box. But construct properties
+ * are only initialized <emphasis>after</emphasis> instance init()
+ * functions have run, which means that using functions which rely on
+ * the existence of the cell area in your subclass' init() function will
+ * cause the default cell area to be instantiated. In this case, a provided
+ * construct property value will be ignored (with a warning, to alert
+ * you to the problem).
+ * <informalexample><programlisting>
+ * static void
+ * my_combo_box_init (MyComboBox *b)
+ * {
+ *   GtkCellRenderer *cell;
+ *
+ *   cell = gtk_cell_renderer_pixbuf_new ();
+ *   /&ast; The following call causes the default cell area for combo boxes,
+ *    &ast; a GtkCellAreaBox, to be instantiated
+ *    &ast;/
+ *   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (b), cell, FALSE);
+ *   ...
+ * }
+ *
+ * GtkWidget *
+ * my_combo_box_new (GtkCellArea *area)
+ * {
+ *   /&ast; This call is going to cause a warning
+ *    &ast; about area being ignored
+ *    &ast;/
+ *   return g_object_new (MY_TYPE_COMBO_BOX, "cell-area", area, NULL);
+ * }
+ * </programlisting></informalexample>
+ * If supporting alternative cell areas with your derived widget is
+ * not important, then this does not have to concern you. If you want
+ * to support alternative cell areas, you can do so by moving the
+ * problematic calls out of init() and into a constructor()
+ * for your class.
+ * </para>
+ * </refsect2>
  */
 
 #include "config.h"
diff --git a/gtk/gtkcellview.c b/gtk/gtkcellview.c
index cd11aeb..0af386b 100644
--- a/gtk/gtkcellview.c
+++ b/gtk/gtkcellview.c
@@ -347,15 +347,14 @@ 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 = 
+  priv->size_changed_id =
     g_signal_connect (priv->context, "notify",
 		      G_CALLBACK (context_size_changed_cb), view);
 
@@ -421,15 +420,16 @@ 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_ORIENTATION:
-      view->priv->orientation = g_value_get_enum (value);
-      if (view->priv->context)
-	gtk_cell_area_context_reset (view->priv->context);
+      priv->orientation = g_value_get_enum (value);
+      if (priv->context)
+        gtk_cell_area_context_reset (priv->context);
 
       _gtk_orientable_set_style_classes (GTK_ORIENTABLE (object));
       break;
@@ -462,16 +462,34 @@ gtk_cell_view_set_property (GObject      *object,
     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:
@@ -809,8 +827,15 @@ static GtkCellArea *
 gtk_cell_view_cell_layout_get_area (GtkCellLayout   *layout)
 {
   GtkCellView *cellview = GTK_CELL_VIEW (layout);
+  GtkCellViewPrivate *priv = cellview->priv;
+
+  if (G_UNLIKELY (!priv->area))
+    {
+      priv->area = gtk_cell_area_box_new ();
+      g_object_ref_sink (priv->area);
+    }
 
-  return cellview->priv->area;
+  return priv->area;
 }
 
 /* GtkBuildable implementation */
@@ -1391,8 +1416,8 @@ gtk_cell_view_get_fit_model (GtkCellView     *cell_view)
  * Since: 3.0
  */
 void
-gtk_cell_view_set_fit_model (GtkCellView     *cell_view,
-			     gboolean         fit_model)
+gtk_cell_view_set_fit_model (GtkCellView *cell_view,
+                             gboolean     fit_model)
 {
   GtkCellViewPrivate *priv;
 
diff --git a/gtk/gtkcellview.h b/gtk/gtkcellview.h
index 0e7fd9a..4a3bd17 100644
--- a/gtk/gtkcellview.h
+++ b/gtk/gtkcellview.h
@@ -65,7 +65,7 @@ struct _GtkCellViewClass
 GType             gtk_cell_view_get_type                (void) G_GNUC_CONST;
 GtkWidget        *gtk_cell_view_new                     (void);
 GtkWidget        *gtk_cell_view_new_with_context        (GtkCellArea        *area,
-							 GtkCellAreaContext *context);
+                                                         GtkCellAreaContext *context);
 GtkWidget        *gtk_cell_view_new_with_text           (const gchar     *text);
 GtkWidget        *gtk_cell_view_new_with_markup         (const gchar     *markup);
 GtkWidget        *gtk_cell_view_new_with_pixbuf         (GdkPixbuf       *pixbuf);
@@ -81,10 +81,10 @@ void              gtk_cell_view_set_background_rgba     (GtkCellView     *cell_v
                                                          const GdkRGBA   *rgba);
 gboolean          gtk_cell_view_get_draw_sensitive      (GtkCellView     *cell_view);
 void              gtk_cell_view_set_draw_sensitive      (GtkCellView     *cell_view,
-							 gboolean         draw_sensitive);
+                                                         gboolean         draw_sensitive);
 gboolean          gtk_cell_view_get_fit_model           (GtkCellView     *cell_view);
 void              gtk_cell_view_set_fit_model           (GtkCellView     *cell_view,
-							 gboolean         fit_model);
+                                                         gboolean         fit_model);
 
 #ifndef GTK_DISABLE_DEPRECATED
 gboolean          gtk_cell_view_get_size_of_row         (GtkCellView     *cell_view,
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
index febf8a9..9db2ff8 100644
--- a/gtk/gtkcombobox.c
+++ b/gtk/gtkcombobox.c
@@ -406,7 +406,7 @@ static void     gtk_combo_box_menu_popup           (GtkComboBox      *combo_box,
                                                     guint32           activate_time);
 
 /* cell layout */
-GtkCellArea    *gtk_combo_box_cell_layout_get_area (GtkCellLayout    *cell_layout);
+static GtkCellArea *gtk_combo_box_cell_layout_get_area       (GtkCellLayout    *cell_layout);
 
 static gboolean gtk_combo_box_mnemonic_activate              (GtkWidget    *widget,
                                                               gboolean      group_cycling);
@@ -1049,6 +1049,7 @@ gtk_combo_box_set_property (GObject      *object,
                             GParamSpec   *pspec)
 {
   GtkComboBox *combo_box = GTK_COMBO_BOX (object);
+  GtkComboBoxPrivate *priv = combo_box->priv;
   GtkCellArea *area;
 
   switch (prop_id)
@@ -1078,16 +1079,15 @@ gtk_combo_box_set_property (GObject      *object,
       break;
 
     case PROP_HAS_FRAME:
-      combo_box->priv->has_frame = g_value_get_boolean (value);
+      priv->has_frame = g_value_get_boolean (value);
 
-      if (combo_box->priv->has_entry)
+      if (priv->has_entry)
         {
           GtkWidget *child;
 
           child = gtk_bin_get_child (GTK_BIN (combo_box));
 
-          gtk_entry_set_has_frame (GTK_ENTRY (child),
-                                   combo_box->priv->has_frame);
+          gtk_entry_set_has_frame (GTK_ENTRY (child), priv->has_frame);
         }
 
       break;
@@ -1119,11 +1119,11 @@ gtk_combo_box_set_property (GObject      *object,
       break;
 
     case PROP_EDITING_CANCELED:
-      combo_box->priv->editing_canceled = g_value_get_boolean (value);
+      priv->editing_canceled = g_value_get_boolean (value);
       break;
 
     case PROP_HAS_ENTRY:
-      combo_box->priv->has_entry = g_value_get_boolean (value);
+      priv->has_entry = g_value_get_boolean (value);
       break;
 
     case PROP_ENTRY_TEXT_COLUMN:
@@ -1141,9 +1141,17 @@ gtk_combo_box_set_property (GObject      *object,
     case PROP_CELL_AREA:
       /* Construct-only, can only be assigned once */
       area = g_value_get_object (value);
-
       if (area)
-        combo_box->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;
 
     default:
@@ -3757,10 +3765,19 @@ gtk_combo_box_list_row_changed (GtkTreeModel *model,
 /*
  * GtkCellLayout implementation
  */
-GtkCellArea *
-gtk_combo_box_cell_layout_get_area (GtkCellLayout    *cell_layout)
+static GtkCellArea *
+gtk_combo_box_cell_layout_get_area (GtkCellLayout *cell_layout)
 {
-  return GTK_COMBO_BOX (cell_layout)->priv->area;
+  GtkComboBox *combo = GTK_COMBO_BOX (cell_layout);
+  GtkComboBoxPrivate *priv = combo->priv;
+
+  if (G_UNLIKELY (!priv->area))
+    {
+      priv->area = gtk_cell_area_box_new ();
+      g_object_ref_sink (priv->area);
+    }
+
+  return priv->area;
 }
 
 /*
@@ -4552,9 +4569,8 @@ gtk_combo_box_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);
     }
 
   priv->cell_view = gtk_cell_view_new_with_context (priv->area, NULL);
diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c
index 77ec2b8..763b670 100644
--- a/gtk/gtkentrycompletion.c
+++ b/gtk/gtkentrycompletion.c
@@ -481,9 +481,9 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
 }
 
 static GObject *
-gtk_entry_completion_constructor (GType                    type,
-                                  guint                    n_construct_properties,
-                                  GObjectConstructParam   *construct_properties)
+gtk_entry_completion_constructor (GType                  type,
+                                  guint                  n_construct_properties,
+                                  GObjectConstructParam *construct_properties)
 {
   GtkEntryCompletion        *completion;
   GtkEntryCompletionPrivate *priv;
@@ -657,9 +657,17 @@ gtk_entry_completion_set_property (GObject      *object,
       case PROP_CELL_AREA:
         /* Construct-only, can only be assigned once */
         area = g_value_get_object (value);
-
         if (area)
-          priv->cell_area = g_object_ref_sink (area);
+          {
+            if (priv->cell_area != NULL)
+              {
+                g_warning ("cell-area has already been set, ignoring construct property");
+                g_object_ref_sink (area);
+                g_object_unref (area);
+              }
+            else
+              priv->cell_area = g_object_ref_sink (area);
+          }
         break;
 
       default:
@@ -786,6 +794,12 @@ gtk_entry_completion_get_area (GtkCellLayout *cell_layout)
 
   priv = GTK_ENTRY_COMPLETION (cell_layout)->priv;
 
+  if (G_UNLIKELY (!priv->cell_area))
+    {
+      priv->cell_area = gtk_cell_area_box_new ();
+      g_object_ref_sink (priv->cell_area);
+    }
+
   return priv->cell_area;
 }
 
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c
index 781c668..7e107da 100644
--- a/gtk/gtkiconview.c
+++ b/gtk/gtkiconview.c
@@ -370,6 +370,9 @@ static GtkIconViewItem *    gtk_icon_view_get_item_at_coords             (GtkIco
 static void                 gtk_icon_view_set_cell_data                  (GtkIconView            *icon_view,
 									  GtkIconViewItem        *item);
 
+static void                 gtk_icon_view_ensure_cell_area               (GtkIconView            *icon_view,
+                                                                          GtkCellArea            *cell_area);
+
 static GtkCellArea         *gtk_icon_view_cell_layout_get_area           (GtkCellLayout          *layout);
 
 static void                 gtk_icon_view_item_selected_changed          (GtkIconView            *icon_view,
@@ -1100,35 +1103,14 @@ gtk_icon_view_constructor (GType               type,
 			   GObjectConstructParam *construct_properties)
 {
   GtkIconView        *icon_view;
-  GtkIconViewPrivate *priv;
   GObject            *object;
 
   object = G_OBJECT_CLASS (gtk_icon_view_parent_class)->constructor
     (type, n_construct_properties, construct_properties);
 
   icon_view = (GtkIconView *) object;
-  priv      = icon_view->priv;
-
-  if (!priv->cell_area)
-    {
-      priv->cell_area = gtk_cell_area_box_new ();
-      g_object_ref_sink (priv->cell_area);
-    }
-
-  if (GTK_IS_ORIENTABLE (priv->cell_area))
-    gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->cell_area), priv->item_orientation);
-
-  priv->cell_area_context = gtk_cell_area_create_context (priv->cell_area);
 
-  priv->add_editable_id = 
-    g_signal_connect (priv->cell_area, "add-editable", 
-		      G_CALLBACK (gtk_icon_view_add_editable), icon_view);
-  priv->remove_editable_id = 
-    g_signal_connect (priv->cell_area, "remove-editable", 
-		      G_CALLBACK (gtk_icon_view_remove_editable), icon_view);
-  priv->context_changed_id = 
-    g_signal_connect (priv->cell_area_context, "notify", 
-		      G_CALLBACK (gtk_icon_view_context_changed), icon_view);
+  gtk_icon_view_ensure_cell_area (icon_view, NULL);
 
   return object;
 }
@@ -1237,9 +1219,17 @@ gtk_icon_view_set_property (GObject      *object,
     case PROP_CELL_AREA:
       /* Construct-only, can only be assigned once */
       area = g_value_get_object (value);
-
       if (area)
-	icon_view->priv->cell_area = g_object_ref_sink (area);
+        {
+          if (icon_view->priv->cell_area != NULL)
+            {
+              g_warning ("cell-area has already been set, ignoring construct property");
+              g_object_ref_sink (area);
+              g_object_unref (area);
+            }
+          else
+            gtk_icon_view_ensure_cell_area (icon_view, area);
+        }
       break;
 
     case PROP_HADJUSTMENT:
@@ -4097,21 +4087,58 @@ gtk_icon_view_scroll_to_item (GtkIconView     *icon_view,
 }
 
 /* GtkCellLayout implementation */
+
+static void
+gtk_icon_view_ensure_cell_area (GtkIconView *icon_view,
+                                GtkCellArea *cell_area)
+{
+  GtkIconViewPrivate *priv = icon_view->priv;
+
+  if (priv->cell_area)
+    return;
+
+  if (cell_area)
+    priv->cell_area = cell_area;
+  else
+    priv->cell_area = gtk_cell_area_box_new ();
+
+  g_object_ref_sink (priv->cell_area);
+
+  if (GTK_IS_ORIENTABLE (priv->cell_area))
+    gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->cell_area), priv->item_orientation);
+
+  priv->cell_area_context = gtk_cell_area_create_context (priv->cell_area);
+
+  priv->add_editable_id =
+    g_signal_connect (priv->cell_area, "add-editable",
+                      G_CALLBACK (gtk_icon_view_add_editable), icon_view);
+  priv->remove_editable_id =
+    g_signal_connect (priv->cell_area, "remove-editable",
+                      G_CALLBACK (gtk_icon_view_remove_editable), icon_view);
+  priv->context_changed_id =
+    g_signal_connect (priv->cell_area_context, "notify",
+                      G_CALLBACK (gtk_icon_view_context_changed), icon_view);
+}
+
 static GtkCellArea *
 gtk_icon_view_cell_layout_get_area (GtkCellLayout *cell_layout)
 {
   GtkIconView *icon_view = GTK_ICON_VIEW (cell_layout);
+  GtkIconViewPrivate *priv = icon_view->priv;
+
+  if (G_UNLIKELY (!priv->cell_area))
+    gtk_icon_view_ensure_cell_area (icon_view, NULL);
 
   return icon_view->priv->cell_area;
 }
 
 static void
-gtk_icon_view_set_cell_data (GtkIconView     *icon_view, 
+gtk_icon_view_set_cell_data (GtkIconView     *icon_view,
 			     GtkIconViewItem *item)
 {
   gboolean iters_persist;
   GtkTreeIter iter;
-  
+
   iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
   
   if (!iters_persist)
diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c
index 0c88847..de1a0a2 100644
--- a/gtk/gtktreeviewcolumn.c
+++ b/gtk/gtktreeviewcolumn.c
@@ -76,6 +76,9 @@ static GObject *gtk_tree_view_column_constructor               (GType
 								GObjectConstructParam   *construct_properties);
 
 /* GtkCellLayout implementation */
+static void       gtk_tree_view_column_ensure_cell_area        (GtkTreeViewColumn      *column,
+                                                                GtkCellArea            *cell_area);
+
 static GtkCellArea *gtk_tree_view_column_cell_layout_get_area  (GtkCellLayout           *cell_layout);
 
 /* Button handling code */
@@ -476,40 +479,19 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
 }
 
 static GObject *
-gtk_tree_view_column_constructor (GType                    type,
-				  guint                    n_construct_properties,
-				  GObjectConstructParam   *construct_properties)
+gtk_tree_view_column_constructor (GType                  type,
+                                  guint                  n_construct_properties,
+                                  GObjectConstructParam *construct_properties)
 {
   GtkTreeViewColumn        *tree_column;
-  GtkTreeViewColumnPrivate *priv;
   GObject                  *object;
 
   object = G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->constructor
     (type, n_construct_properties, construct_properties);
 
   tree_column = (GtkTreeViewColumn *) object;
-  priv        = tree_column->priv;
-
-  if (!priv->cell_area)
-    {
-      priv->cell_area = gtk_cell_area_box_new ();
-      g_object_ref_sink (priv->cell_area);
-    }
-
-  priv->add_editable_signal =
-    g_signal_connect (priv->cell_area, "add-editable",
-		      G_CALLBACK (gtk_tree_view_column_add_editable_callback),
-		      tree_column);
-  priv->remove_editable_signal =
-    g_signal_connect (priv->cell_area, "remove-editable",
-		      G_CALLBACK (gtk_tree_view_column_remove_editable_callback),
-		      tree_column);
-
-  priv->cell_area_context = gtk_cell_area_create_context (priv->cell_area);
 
-  priv->context_changed_signal =
-    g_signal_connect (priv->cell_area_context, "notify",
-		      G_CALLBACK (gtk_tree_view_column_context_changed), tree_column);
+  gtk_tree_view_column_ensure_cell_area (tree_column, NULL);
 
   return object;
 }
@@ -537,7 +519,7 @@ gtk_tree_view_column_dispose (GObject *object)
 				   priv->add_editable_signal);
       g_signal_handler_disconnect (priv->cell_area,
 				   priv->remove_editable_signal);
-      
+
       g_object_unref (priv->cell_area);
       priv->cell_area = NULL;
       priv->add_editable_signal = 0;
@@ -662,9 +644,18 @@ gtk_tree_view_column_set_property (GObject         *object,
       area = g_value_get_object (value);
 
       if (area)
-	tree_column->priv->cell_area = g_object_ref_sink (area);
+        {
+          if (tree_column->priv->cell_area != NULL)
+            {
+              g_warning ("cell-area has already been set, ignoring construct property");
+              g_object_ref_sink (area);
+              g_object_unref (area);
+            }
+          else
+            gtk_tree_view_column_ensure_cell_area (tree_column, area);
+        }
       break;
-      
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -780,12 +771,51 @@ gtk_tree_view_column_get_property (GObject         *object,
 
 /* Implementation of GtkCellLayout interface
  */
+
+static void
+gtk_tree_view_column_ensure_cell_area (GtkTreeViewColumn *column,
+                                       GtkCellArea       *cell_area)
+{
+  GtkTreeViewColumnPrivate *priv = column->priv;
+
+  if (priv->cell_area)
+    return;
+
+  if (cell_area)
+    priv->cell_area = cell_area;
+  else
+    priv->cell_area = gtk_cell_area_box_new ();
+
+  g_object_ref_sink (priv->cell_area);
+
+ priv->cell_area_context = gtk_cell_area_create_context (priv->cell_area);
+
+  priv->add_editable_signal =
+    g_signal_connect (priv->cell_area, "add-editable",
+                      G_CALLBACK (gtk_tree_view_column_add_editable_callback),
+                      column);
+  priv->remove_editable_signal =
+    g_signal_connect (priv->cell_area, "remove-editable",
+                      G_CALLBACK (gtk_tree_view_column_remove_editable_callback),
+                      column);
+
+  priv->cell_area_context = gtk_cell_area_create_context (priv->cell_area);
+
+  priv->context_changed_signal =
+    g_signal_connect (priv->cell_area_context, "notify",
+                      G_CALLBACK (gtk_tree_view_column_context_changed),
+                      column);
+}
+
 static GtkCellArea *
 gtk_tree_view_column_cell_layout_get_area (GtkCellLayout   *cell_layout)
 {
   GtkTreeViewColumn        *column = GTK_TREE_VIEW_COLUMN (cell_layout);
   GtkTreeViewColumnPrivate *priv   = column->priv;
 
+  if (G_UNLIKELY (!priv->cell_area))
+    gtk_tree_view_column_ensure_cell_area (column, NULL);
+
   return priv->cell_area;
 }
 
diff --git a/gtk/tests/Makefile.am b/gtk/tests/Makefile.am
index f27796f..bca3961 100644
--- a/gtk/tests/Makefile.am
+++ b/gtk/tests/Makefile.am
@@ -105,6 +105,10 @@ TEST_PROGS			+= papersize
 papersize_SOURCES		 = papersize.c
 papersize_LDADD			 = $(progs_ldadd)
 
+TEST_PROGS			+= cellarea
+cellarea_SOURCES		 = cellarea.c
+cellarea_LDADD			 = $(progs_ldadd)
+
 EXTRA_DIST +=				\
 	file-chooser-test-dir/empty     \
 	file-chooser-test-dir/text.txt
diff --git a/gtk/tests/cellarea.c b/gtk/tests/cellarea.c
new file mode 100644
index 0000000..cd60c68
--- /dev/null
+++ b/gtk/tests/cellarea.c
@@ -0,0 +1,855 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Author: Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/* tests related to handling of the cell-area property in
+ * GtkCellLayout implementations
+ */
+
+/* test that we have a cell area after new() */
+static void
+test_iconview_new (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  view = gtk_icon_view_new ();
+
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == gtk_icon_view_get_item_orientation (GTK_ICON_VIEW (view)));
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that new_with_area() keeps the provided area */
+static void
+test_iconview_new_with_area (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  view = gtk_icon_view_new_with_area (area);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)) == area);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that g_object_new keeps the provided area */
+static void
+test_iconview_object_new (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
+  view = g_object_new (GTK_TYPE_ICON_VIEW, "cell-area", area, NULL);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)) == area);
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == gtk_icon_view_get_item_orientation (GTK_ICON_VIEW (view)));
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+typedef GtkIconView MyIconView;
+typedef GtkIconViewClass MyIconViewClass;
+
+G_DEFINE_TYPE (MyIconView, my_icon_view, GTK_TYPE_ICON_VIEW)
+
+static void
+my_icon_view_class_init (MyIconViewClass *klass)
+{
+}
+
+static gint subclass_init;
+
+static void
+my_icon_view_init (MyIconView *view)
+{
+  GtkCellArea *area;
+
+  if (subclass_init == 0)
+    {
+      /* do nothing to area */
+    }
+  else if (subclass_init == 1)
+    {
+      area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+      g_assert (GTK_IS_CELL_AREA_BOX (area));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+      gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
+    }
+}
+
+/* test that an iconview subclass has an area */
+static void
+test_iconview_subclass0 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  view = g_object_new (my_icon_view_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that an iconview subclass keeps the provided area */
+static void
+test_iconview_subclass1 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  area = gtk_cell_area_box_new ();
+  view = g_object_new (my_icon_view_get_type (), "cell-area", area, NULL);
+  g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test we can access the area in subclass init */
+static void
+test_iconview_subclass2 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 1;
+
+  view = g_object_new (my_icon_view_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test we get a warning if an area is provided, but ignored */
+static void
+test_iconview_subclass3 (void)
+{
+  subclass_init = 1;
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+    {
+      GtkWidget *view;
+      GtkCellArea *area;
+
+      area = gtk_cell_area_box_new ();
+      view = g_object_new (my_icon_view_get_type (), "cell-area", area, NULL);
+      g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+      g_object_ref_sink (view);
+      g_object_unref (view);
+
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*ignoring construct property*");
+}
+
+/* test that we have a cell area after new() */
+static void
+test_combobox_new (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  view = gtk_combo_box_new ();
+
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that new_with_area() keeps the provided area */
+static void
+test_combobox_new_with_area (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  view = gtk_combo_box_new_with_area (area);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)) == area);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that g_object_new keeps the provided area */
+static void
+test_combobox_object_new (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
+  view = g_object_new (GTK_TYPE_COMBO_BOX, "cell-area", area, NULL);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)) == area);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+typedef GtkComboBox MyComboBox;
+typedef GtkComboBoxClass MyComboBoxClass;
+
+G_DEFINE_TYPE (MyComboBox, my_combo_box, GTK_TYPE_COMBO_BOX)
+
+static void
+my_combo_box_class_init (MyComboBoxClass *klass)
+{
+}
+
+static void
+my_combo_box_init (MyComboBox *view)
+{
+  GtkCellArea *area;
+
+  if (subclass_init == 0)
+    {
+      /* do nothing to area */
+    }
+  else if (subclass_init == 1)
+    {
+      area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+      g_assert (GTK_IS_CELL_AREA_BOX (area));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+      gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_VERTICAL);
+    }
+}
+
+/* test that a combobox subclass has an area */
+static void
+test_combobox_subclass0 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  view = g_object_new (my_combo_box_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that a combobox subclass keeps the provided area */
+static void
+test_combobox_subclass1 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  area = gtk_cell_area_box_new ();
+  view = g_object_new (my_combo_box_get_type (), "cell-area", area, NULL);
+  g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test we can access the area in subclass init */
+static void
+test_combobox_subclass2 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 1;
+
+  view = g_object_new (my_combo_box_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test we get a warning if an area is provided, but ignored */
+static void
+test_combobox_subclass3 (void)
+{
+  subclass_init = 1;
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+    {
+      GtkWidget *view;
+      GtkCellArea *area;
+
+      area = gtk_cell_area_box_new ();
+      view = g_object_new (my_combo_box_get_type (), "cell-area", area, NULL);
+      g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+      g_object_ref_sink (view);
+      g_object_unref (view);
+
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*ignoring construct property*");
+}
+
+/* test that we have a cell area after new() */
+static void
+test_cellview_new (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  view = gtk_cell_view_new ();
+
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that new_with_context() keeps the provided area */
+static void
+test_cellview_new_with_context (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+  GtkCellAreaContext *context;
+
+  area = gtk_cell_area_box_new ();
+  context = gtk_cell_area_create_context (area);
+  view = gtk_cell_view_new_with_context (area, context);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)) == area);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that g_object_new keeps the provided area */
+static void
+test_cellview_object_new (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
+  view = g_object_new (GTK_TYPE_CELL_VIEW, "cell-area", area, NULL);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)) == area);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+typedef GtkCellView MyCellView;
+typedef GtkCellViewClass MyCellViewClass;
+
+G_DEFINE_TYPE (MyCellView, my_cell_view, GTK_TYPE_CELL_VIEW)
+
+static void
+my_cell_view_class_init (MyCellViewClass *klass)
+{
+}
+
+static void
+my_cell_view_init (MyCellView *view)
+{
+  GtkCellArea *area;
+
+  if (subclass_init == 0)
+    {
+      /* do nothing to area */
+    }
+  else if (subclass_init == 1)
+    {
+      area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+      g_assert (GTK_IS_CELL_AREA_BOX (area));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+      gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_VERTICAL);
+    }
+}
+
+/* test that a cellview subclass has an area */
+static void
+test_cellview_subclass0 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  view = g_object_new (my_cell_view_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test that a cellview subclass keeps the provided area */
+static void
+test_cellview_subclass1 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  area = gtk_cell_area_box_new ();
+  view = g_object_new (my_cell_view_get_type (), "cell-area", area, NULL);
+  g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test we can access the area in subclass init */
+static void
+test_cellview_subclass2 (void)
+{
+  GtkWidget *view;
+  GtkCellArea *area;
+
+  subclass_init = 1;
+
+  view = g_object_new (my_cell_view_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+  g_object_ref_sink (view);
+  g_object_unref (view);
+}
+
+/* test we get a warning if an area is provided, but ignored */
+static void
+test_cellview_subclass3 (void)
+{
+  subclass_init = 1;
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+    {
+      GtkWidget *view;
+      GtkCellArea *area;
+
+      area = gtk_cell_area_box_new ();
+      view = g_object_new (my_cell_view_get_type (), "cell-area", area, NULL);
+      g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (view)));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+      g_object_ref_sink (view);
+      g_object_unref (view);
+
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*ignoring construct property*");
+}
+
+/* test that we have a cell area after new() */
+static void
+test_column_new (void)
+{
+  GtkTreeViewColumn *col;
+  GtkCellArea *area;
+
+  col = gtk_tree_view_column_new ();
+
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+
+  g_object_ref_sink (col);
+  g_object_unref (col);
+}
+
+/* test that new_with_area() keeps the provided area */
+static void
+test_column_new_with_area (void)
+{
+  GtkTreeViewColumn *col;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  col = gtk_tree_view_column_new_with_area (area);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col)) == area);
+
+  g_object_ref_sink (col);
+  g_object_unref (col);
+}
+
+/* test that g_object_new keeps the provided area */
+static void
+test_column_object_new (void)
+{
+  GtkTreeViewColumn *col;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
+  col = g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, "cell-area", area, NULL);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col)) == area);
+
+  g_object_ref_sink (col);
+  g_object_unref (col);
+}
+
+typedef GtkTreeViewColumn MyTreeViewColumn;
+typedef GtkTreeViewColumnClass MyTreeViewColumnClass;
+
+G_DEFINE_TYPE (MyTreeViewColumn, my_tree_view_column, GTK_TYPE_TREE_VIEW_COLUMN)
+
+static void
+my_tree_view_column_class_init (MyTreeViewColumnClass *klass)
+{
+}
+
+static void
+my_tree_view_column_init (MyTreeViewColumn *col)
+{
+  GtkCellArea *area;
+
+  if (subclass_init == 0)
+    {
+      /* do nothing to area */
+    }
+  else if (subclass_init == 1)
+    {
+      area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col));
+      g_assert (GTK_IS_CELL_AREA_BOX (area));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+      gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_VERTICAL);
+    }
+}
+
+/* test that a column subclass has an area */
+static void
+test_column_subclass0 (void)
+{
+  GtkTreeViewColumn *col;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  col = g_object_new (my_tree_view_column_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (col);
+  g_object_unref (col);
+}
+
+/* test that a column subclass keeps the provided area */
+static void
+test_column_subclass1 (void)
+{
+  GtkTreeViewColumn *col;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  area = gtk_cell_area_box_new ();
+  col = g_object_new (my_tree_view_column_get_type (), "cell-area", area, NULL);
+  g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col)));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (col);
+  g_object_unref (col);
+}
+
+/* test we can access the area in subclass init */
+static void
+test_column_subclass2 (void)
+{
+  GtkTreeViewColumn *col;
+  GtkCellArea *area;
+
+  subclass_init = 1;
+
+  col = g_object_new (my_tree_view_column_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+  g_object_ref_sink (col);
+  g_object_unref (col);
+}
+
+/* test we get a warning if an area is provided, but ignored */
+static void
+test_column_subclass3 (void)
+{
+  subclass_init = 1;
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+    {
+      GtkTreeViewColumn *col;
+      GtkCellArea *area;
+
+      area = gtk_cell_area_box_new ();
+      col = g_object_new (my_tree_view_column_get_type (), "cell-area", area, NULL);
+      g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (col)));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+      g_object_ref_sink (col);
+      g_object_unref (col);
+
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*ignoring construct property*");
+}
+
+/* test that we have a cell area after new() */
+static void
+test_completion_new (void)
+{
+  GtkEntryCompletion *c;
+  GtkCellArea *area;
+
+  c = gtk_entry_completion_new ();
+
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+
+  g_object_ref_sink (c);
+  g_object_unref (c);
+}
+
+/* test that new_with_area() keeps the provided area */
+static void
+test_completion_new_with_area (void)
+{
+  GtkEntryCompletion *c;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  c = gtk_entry_completion_new_with_area (area);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c)) == area);
+
+  g_object_ref_sink (c);
+  g_object_unref (c);
+}
+
+/* test that g_object_new keeps the provided area */
+static void
+test_completion_object_new (void)
+{
+  GtkEntryCompletion *c;
+  GtkCellArea *area;
+
+  area = gtk_cell_area_box_new ();
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_HORIZONTAL);
+  c = g_object_new (GTK_TYPE_ENTRY_COMPLETION, "cell-area", area, NULL);
+  g_assert (gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c)) == area);
+
+  g_object_ref_sink (c);
+  g_object_unref (c);
+}
+
+typedef GtkEntryCompletion MyEntryCompletion;
+typedef GtkEntryCompletionClass MyEntryCompletionClass;
+
+G_DEFINE_TYPE (MyEntryCompletion, my_entry_completion, GTK_TYPE_ENTRY_COMPLETION)
+
+static void
+my_entry_completion_class_init (MyEntryCompletionClass *klass)
+{
+}
+
+static void
+my_entry_completion_init (MyEntryCompletion *c)
+{
+  GtkCellArea *area;
+
+  if (subclass_init == 0)
+    {
+      /* do nothing to area */
+    }
+  else if (subclass_init == 1)
+    {
+      area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c));
+      g_assert (GTK_IS_CELL_AREA_BOX (area));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+      gtk_orientable_set_orientation (GTK_ORIENTABLE (area), GTK_ORIENTATION_VERTICAL);
+    }
+}
+
+/* test that a completion subclass has an area */
+static void
+test_completion_subclass0 (void)
+{
+  GtkEntryCompletion *c;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  c = g_object_new (my_entry_completion_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (c);
+  g_object_unref (c);
+}
+
+/* test that a completion subclass keeps the provided area */
+static void
+test_completion_subclass1 (void)
+{
+  GtkEntryCompletion *c;
+  GtkCellArea *area;
+
+  subclass_init = 0;
+
+  area = gtk_cell_area_box_new ();
+  c = g_object_new (my_entry_completion_get_type (), "cell-area", area, NULL);
+  g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c)));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_HORIZONTAL);
+
+  g_object_ref_sink (c);
+  g_object_unref (c);
+}
+
+/* test we can access the area in subclass init */
+static void
+test_completion_subclass2 (void)
+{
+  GtkEntryCompletion *c;
+  GtkCellArea *area;
+
+  subclass_init = 1;
+
+  c = g_object_new (my_entry_completion_get_type (), NULL);
+  area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c));
+  g_assert (GTK_IS_CELL_AREA_BOX (area));
+  g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+  g_object_ref_sink (c);
+  g_object_unref (c);
+}
+
+/* test we get a warning if an area is provided, but ignored */
+static void
+test_completion_subclass3 (void)
+{
+  subclass_init = 1;
+
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+    {
+      GtkEntryCompletion *c;
+      GtkCellArea *area;
+
+      area = gtk_cell_area_box_new ();
+      c = g_object_new (my_entry_completion_get_type (), "cell-area", area, NULL);
+      g_assert (area == gtk_cell_layout_get_area (GTK_CELL_LAYOUT (c)));
+      g_assert (gtk_orientable_get_orientation (GTK_ORIENTABLE (area)) == GTK_ORIENTATION_VERTICAL);
+
+      g_object_ref_sink (c);
+      g_object_unref (c);
+
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*ignoring construct property*");
+}
+
+int
+main (int argc, char *argv[])
+{
+  gtk_test_init (&argc, &argv);
+  g_test_bug_base ("http://bugzilla.gnome.org/";);
+  gtk_test_register_all_types();
+
+  g_test_add_func ("/tests/iconview-new", test_iconview_new);
+  g_test_add_func ("/tests/iconview-new-with-area", test_iconview_new_with_area);
+  g_test_add_func ("/tests/iconview-object-new", test_iconview_object_new);
+  g_test_add_func ("/tests/iconview-subclass0", test_iconview_subclass0);
+  g_test_add_func ("/tests/iconview-subclass1", test_iconview_subclass1);
+  g_test_add_func ("/tests/iconview-subclass2", test_iconview_subclass2);
+  g_test_add_func ("/tests/iconview-subclass3", test_iconview_subclass3);
+
+  g_test_add_func ("/tests/combobox-new", test_combobox_new);
+  g_test_add_func ("/tests/combobox-new-with-area", test_combobox_new_with_area);
+  g_test_add_func ("/tests/combobox-object-new", test_combobox_object_new);
+  g_test_add_func ("/tests/combobox-subclass0", test_combobox_subclass0);
+  g_test_add_func ("/tests/combobox-subclass1", test_combobox_subclass1);
+  g_test_add_func ("/tests/combobox-subclass2", test_combobox_subclass2);
+  g_test_add_func ("/tests/combobox-subclass3", test_combobox_subclass3);
+
+  g_test_add_func ("/tests/cellview-new", test_cellview_new);
+  g_test_add_func ("/tests/cellview-new-with-context", test_cellview_new_with_context);
+  g_test_add_func ("/tests/cellview-object-new", test_cellview_object_new);
+  g_test_add_func ("/tests/cellview-subclass0", test_cellview_subclass0);
+  g_test_add_func ("/tests/cellview-subclass1", test_cellview_subclass1);
+  g_test_add_func ("/tests/cellview-subclass2", test_cellview_subclass2);
+  g_test_add_func ("/tests/cellview-subclass3", test_cellview_subclass3);
+
+  g_test_add_func ("/tests/column-new", test_column_new);
+  g_test_add_func ("/tests/column-new-with-area", test_column_new_with_area);
+  g_test_add_func ("/tests/column-object-new", test_column_object_new);
+  g_test_add_func ("/tests/column-subclass0", test_column_subclass0);
+  g_test_add_func ("/tests/column-subclass1", test_column_subclass1);
+  g_test_add_func ("/tests/column-subclass2", test_column_subclass2);
+  g_test_add_func ("/tests/column-subclass3", test_column_subclass3);
+
+  g_test_add_func ("/tests/completion-new", test_completion_new);
+  g_test_add_func ("/tests/completion-new-with-area", test_completion_new_with_area);
+  g_test_add_func ("/tests/completion-object-new", test_completion_object_new);
+  g_test_add_func ("/tests/completion-subclass0", test_completion_subclass0);
+  g_test_add_func ("/tests/completion-subclass1", test_completion_subclass1);
+  g_test_add_func ("/tests/completion-subclass2", test_completion_subclass2);
+  g_test_add_func ("/tests/completion-subclass3", test_completion_subclass3);
+
+  return g_test_run();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]