summaryrefslogtreecommitdiff
path: root/gtk/gtkcellareabox.c
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2010-11-26 21:26:24 +0900
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2010-11-26 21:38:10 +0900
commit487223d480578457f924470c1a1d73eb261eefd7 (patch)
treee6888ecfc4a29875b54e5ba349a47f36ccc183fd /gtk/gtkcellareabox.c
parentfa3c8f182edcddcfb948513fbdadeeec2e059fe0 (diff)
downloadgtk+-487223d480578457f924470c1a1d73eb261eefd7.tar.gz
Finally really support rendering of cells in an unallocated context.
What this means is basically that a vertically oriented GtkCellAreaBox will render cells properly even if the height is not constant for every for of data in the said GtkCellAreaContext (i.e. the height was not allocated by gtk_cell_area_context_allocate). This is done completely on the fly and so is much more heavy duty at render time (considerably slower but not visibly noticable in lightweight views like GtkTreeMenu). Note that cell alignments are not possible in an unallocated orientation, each row of data individually receives only enough space to render the independant row and no space is reserved for alignments if the size is not a constant size across rows in the same context.
Diffstat (limited to 'gtk/gtkcellareabox.c')
-rw-r--r--gtk/gtkcellareabox.c139
1 files changed, 123 insertions, 16 deletions
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index 02ec53f9e3..522c397590 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -167,7 +167,8 @@ static void init_context_group (GtkCellAreaBox *box,
static GSList *get_allocated_cells (GtkCellAreaBox *box,
GtkCellAreaBoxContext *context,
GtkWidget *widget,
- gint orientation_size);
+ gint width,
+ gint height);
struct _GtkCellAreaBoxPrivate
@@ -564,6 +565,121 @@ flush_contexts (GtkCellAreaBox *box)
}
}
+/* Fall back on a completely unaligned dynamic allocation of cells
+ * when not allocated for the said orientation, alignment of cells
+ * is not done when each area gets a different size in the orientation
+ * of the box.
+ */
+static GSList *
+allocate_cells_manually (GtkCellAreaBox *box,
+ GtkWidget *widget,
+ gint width,
+ gint height)
+{
+ GtkCellAreaBoxPrivate *priv = box->priv;
+ GList *cells, *l;
+ GSList *allocated_cells = NULL;
+ GtkRequestedSize *sizes;
+ gint i;
+ gint nvisible = 0, nexpand = 0, group_expand;
+ gint avail_size, extra_size, extra_extra;
+ gint position = 0;
+
+ if (!priv->cells)
+ return NULL;
+
+ cells = list_consecutive_cells (box);
+
+ /* Count the visible and expand cells */
+ for (i = 0; i < priv->groups->len; i++)
+ {
+ CellGroup *group = &g_array_index (priv->groups, CellGroup, i);
+
+ nvisible += count_visible_cells (group, &group_expand);
+ nexpand += group_expand;
+ }
+
+ if (nvisible <= 0)
+ {
+ g_list_free (cells);
+ return NULL;
+ }
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ avail_size = width;
+ else
+ avail_size = height;
+
+ /* Go ahead and collect the requests on the fly */
+ sizes = g_new0 (GtkRequestedSize, nvisible);
+ for (l = cells, i = 0; l; l = l->next)
+ {
+ CellInfo *info = l->data;
+
+ if (!gtk_cell_renderer_get_visible (info->renderer))
+ continue;
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_cell_renderer_get_preferred_width_for_height (info->renderer, widget, height,
+ &sizes[i].minimum_size,
+ &sizes[i].natural_size);
+ else
+ gtk_cell_renderer_get_preferred_height_for_width (info->renderer, widget, width,
+ &sizes[i].minimum_size,
+ &sizes[i].natural_size);
+
+ avail_size -= sizes[i].minimum_size;
+
+ sizes[i].data = info;
+
+ i++;
+ }
+
+ /* Naturally distribute the allocation */
+ avail_size -= (nvisible - 1) * priv->spacing;
+ avail_size = gtk_distribute_natural_allocation (avail_size, nvisible, sizes);
+
+ /* Calculate/distribute expand for cells */
+ if (nexpand > 0)
+ {
+ extra_size = avail_size / nexpand;
+ extra_extra = avail_size % nexpand;
+ }
+ else
+ extra_size = extra_extra = 0;
+
+ /* Create the allocated cells */
+ for (i = 0; i < nvisible; i++)
+ {
+ CellInfo *info = sizes[i].data;
+ AllocatedCell *cell;
+
+ if (info->expand)
+ {
+ sizes[i].minimum_size += extra_size;
+ if (extra_extra)
+ {
+ sizes[i].minimum_size++;
+ extra_extra--;
+ }
+ }
+
+ cell = allocated_cell_new (info->renderer, position, sizes[i].minimum_size);
+
+ allocated_cells = g_slist_prepend (allocated_cells, cell);
+
+ position += sizes[i].minimum_size;
+ position += priv->spacing;
+ }
+
+ g_free (sizes);
+ g_list_free (cells);
+
+ /* Note it might not be important to reverse the list here at all,
+ * we have the correct positions, no need to allocate from left to right */
+ return g_slist_reverse (allocated_cells);
+}
+
/* Returns an allocation for each cell in the orientation of the box,
* used in ->render()/->event() implementations to get a straight-forward
* list of allocated cells to operate on.
@@ -572,7 +688,8 @@ static GSList *
get_allocated_cells (GtkCellAreaBox *box,
GtkCellAreaBoxContext *context,
GtkWidget *widget,
- gint orientation_size)
+ gint width,
+ gint height)
{
GtkCellAreaBoxAllocation *group_allocs;
GtkCellArea *area = GTK_CELL_AREA (box);
@@ -580,14 +697,10 @@ get_allocated_cells (GtkCellAreaBox *box,
GList *cell_list;
GSList *allocated_cells = NULL;
gint i, j, n_allocs;
- gboolean free_allocs = FALSE;
group_allocs = gtk_cell_area_box_context_get_orientation_allocs (context, &n_allocs);
if (!group_allocs)
- {
- group_allocs = gtk_cell_area_box_context_allocate (context, orientation_size, &n_allocs);
- free_allocs = TRUE;
- }
+ return allocate_cells_manually (box, widget, width, height);
for (i = 0; i < n_allocs; i++)
{
@@ -686,9 +799,6 @@ get_allocated_cells (GtkCellAreaBox *box,
}
}
- if (free_allocs)
- g_free (group_allocs);
-
/* Note it might not be important to reverse the list here at all,
* we have the correct positions, no need to allocate from left to right */
return g_slist_reverse (allocated_cells);
@@ -843,8 +953,7 @@ gtk_cell_area_box_get_cell_allocation (GtkCellArea *area,
/* Get a list of cells with allocation sizes decided regardless
* of alignments and pack order etc. */
allocated_cells = get_allocated_cells (box, box_context, widget,
- priv->orientation == GTK_ORIENTATION_HORIZONTAL ?
- cell_area->width : cell_area->height);
+ cell_area->width, cell_area->height);
for (l = allocated_cells; l; l = l->next)
{
@@ -921,8 +1030,7 @@ gtk_cell_area_box_event (GtkCellArea *area,
/* Get a list of cells with allocation sizes decided regardless
* of alignments and pack order etc. */
allocated_cells = get_allocated_cells (box, box_context, widget,
- priv->orientation == GTK_ORIENTATION_HORIZONTAL ?
- cell_area->width : cell_area->height);
+ cell_area->width, cell_area->height);
for (l = allocated_cells; l; l = l->next)
{
@@ -1025,8 +1133,7 @@ gtk_cell_area_box_render (GtkCellArea *area,
/* Get a list of cells with allocation sizes decided regardless
* of alignments and pack order etc. */
allocated_cells = get_allocated_cells (box, box_context, widget,
- priv->orientation == GTK_ORIENTATION_HORIZONTAL ?
- cell_area->width : cell_area->height);
+ cell_area->width, cell_area->height);
for (l = allocated_cells; l; l = l->next)
{