+static gboolean
+gtk_cell_view_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data)
+{
+ if (parent_buildable_iface->custom_tag_start &&
+ parent_buildable_iface->custom_tag_start (buildable, builder, child,
+ tagname, parser, data))
+ return TRUE;
+
+ return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+ tagname, parser, data);
+}
+
+static void
+gtk_cell_view_buildable_custom_tag_end (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer *data)
+{
+ if (strcmp (tagname, "attributes") == 0)
+ _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+ data);
+ else if (parent_buildable_iface->custom_tag_end)
+ parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+ data);
+}
+
+static void
+gtk_cell_view_get_preferred_width (GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GList *list;
+ gint cell_min, cell_nat;
+ gboolean first_cell = TRUE;
+ GtkCellView *cellview = GTK_CELL_VIEW (widget);
+ gint minimum, natural;
+
+ minimum = natural = 0;
+
+ if (cellview->priv->displayed_row)
+ gtk_cell_view_set_cell_data (cellview);
+
+ for (list = cellview->priv->cell_list; list; list = list->next)
+ {
+ GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+
+ if (gtk_cell_renderer_get_visible (info->cell))
+ {
+
+ if (!first_cell)
+ {
+ minimum += cellview->priv->spacing;
+ natural += cellview->priv->spacing;
+ }
+
+ gtk_cell_renderer_get_preferred_width (info->cell,
+ GTK_WIDGET (cellview), &cell_min, &cell_nat);
+
+ info->requested_width = cell_min;
+ info->natural_width = cell_nat;
+
+ minimum += info->requested_width;
+ natural += info->natural_width;
+
+ first_cell = FALSE;
+ }
+ }
+
+ if (minimum_size)
+ *minimum_size = minimum;
+
+ if (natural_size)
+ *natural_size = natural;
+}
+
+static void
+gtk_cell_view_get_preferred_height (GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ gint minimum_width;
+
+ /* CellViews only need to respond to height-for-width mode (cellview is pretty much
+ * an implementation detail of GtkComboBox) */
+ gtk_cell_view_get_preferred_width (widget, &minimum_width, NULL);
+ gtk_cell_view_get_preferred_height_for_width (widget, minimum_width, minimum_size, natural_size);
+}
+
+static void
+gtk_cell_view_get_preferred_width_for_height (GtkWidget *widget,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ /* CellViews only need to respond to height-for-width mode (cellview is pretty much
+ * an implementation detail of GtkComboBox) */
+ gtk_cell_view_get_preferred_width (widget, minimum_size, natural_size);
+}
+
+static void
+gtk_cell_view_get_preferred_height_for_width (GtkWidget *widget,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkCellView *cellview = GTK_CELL_VIEW (widget);
+ GList *list;
+ GtkRequestedSize *sizes;
+ GArray *array;
+ gint minimum, natural, avail_size;
+ gboolean first_cell = TRUE;
+ gint n_expand_cells = 0;
+ gint extra_per_cell, extra_extra, i;
+
+ minimum = natural = 0;
+ avail_size = for_size;
+
+ array = g_array_new (0, TRUE, sizeof (GtkRequestedSize));
+
+ if (cellview->priv->displayed_row)
+ gtk_cell_view_set_cell_data (cellview);
+
+ /* First allocate the right width to all cells */
+ for (list = cellview->priv->cell_list; list; list = list->next)
+ {
+ GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+
+ if (gtk_cell_renderer_get_visible (info->cell))
+ {
+ GtkRequestedSize requested;
+
+ gtk_cell_renderer_get_preferred_width (GTK_CELL_RENDERER (info->cell),
+ GTK_WIDGET (cellview),
+ &requested.minimum_size,
+ &requested.natural_size);
+
+ requested.data = info;
+ g_array_append_val (array, requested);
+
+ avail_size -= requested.minimum_size;
+
+ if (!first_cell)
+ avail_size -= cellview->priv->spacing;
+
+ first_cell = FALSE;
+
+ if (info->expand)
+ n_expand_cells++;
+ }
+ }
+
+ sizes = (GtkRequestedSize *)array->data;
+ avail_size = gtk_distribute_natural_allocation (MAX (0, avail_size), array->len, sizes);
+
+ /* Deal with any expand space... */
+ if (n_expand_cells > 0)
+ {
+ extra_per_cell = avail_size / n_expand_cells;
+ extra_extra = avail_size % n_expand_cells;
+ }
+ else
+ /* Everything just left-aligned if no cells expand */
+ extra_per_cell = extra_extra = 0;
+
+ /* Now get the height for the real width of each cell */
+ for (i = 0, list = cellview->priv->cell_list; list; list = list->next)
+ {
+ GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
+ gint cell_minimum, cell_natural;
+
+ if (gtk_cell_renderer_get_visible (info->cell))
+ {
+ gint cell_width = sizes[i].minimum_size;
+
+ g_assert (sizes[i].data == info);
+
+ if (info->expand)
+ {
+ cell_width += extra_per_cell;
+ if (extra_extra)
+ {
+ cell_width++;
+ extra_extra--;
+ }
+ }
+
+ /* Get the height for the real width of this cell */
+ gtk_cell_renderer_get_preferred_height_for_width (GTK_CELL_RENDERER (info->cell),
+ GTK_WIDGET (widget),
+ cell_width, &cell_minimum, &cell_natural);
+
+ minimum = MAX (minimum, cell_minimum);
+ natural = MAX (natural, cell_natural);
+
+ /* increment sizes[] index for visible cells */
+ i++;
+ }
+ }
+
+ g_array_free (array, TRUE);
+
+ if (minimum_size)
+ *minimum_size = minimum;
+ if (natural_size)
+ *natural_size = natural;
+}