[gtk+/native-layout] Added height-for-width apis to treeviewcolumn
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/native-layout] Added height-for-width apis to treeviewcolumn
- Date: Wed, 23 Jun 2010 22:03:27 +0000 (UTC)
commit 101ad51803fec0aa00bb63f9650e5723a125655d
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Tue Jun 22 13:01:39 2010 -0400
Added height-for-width apis to treeviewcolumn
Added get_natural_width() and get_height_for_width() apis
which need to be treated in a special way from treeview because
of the intricate nature of treeviews and thier requirements:
- get_natural_width() must be called in the request phase for
every row which will cache the ->requested_width and ->natural_width
- get_height_for_width() must be called only after caching the widths
for the entire view
gtk/gtktreeviewcolumn.c | 248 +++++++++++++++++++++++++++++++++++++++++------
gtk/gtktreeviewcolumn.h | 17 +++-
2 files changed, 234 insertions(+), 31 deletions(-)
---
diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c
index 6a91f20..c428835 100644
--- a/gtk/gtktreeviewcolumn.c
+++ b/gtk/gtktreeviewcolumn.c
@@ -27,6 +27,7 @@
#include "gtkalignment.h"
#include "gtklabel.h"
#include "gtkcellsizerequest.h"
+#include "gtksizerequestprivate.h"
#include "gtkhbox.h"
#include "gtkmarshalers.h"
#include "gtkarrow.h"
@@ -71,6 +72,7 @@ struct _GtkTreeViewColumnCellInfo
gpointer func_data;
GDestroyNotify destroy;
gint requested_width;
+ gint natural_width;
gint real_width;
guint expand : 1;
guint pack : 1;
@@ -374,6 +376,8 @@ gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface)
static void
gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
{
+ GtkTreeViewColumnPrivate *priv;
+
tree_column->button = NULL;
tree_column->xalign = 0.0;
tree_column->width = 0;
@@ -399,6 +403,9 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
tree_column->fixed_width = 1;
tree_column->use_resized_width = FALSE;
tree_column->title = g_strdup ("");
+
+ priv = GTK_TREE_VIEW_COLUMN_GET_PRIVATE (tree_column);
+ priv->natural_width = -1;
}
static void
@@ -2622,14 +2629,6 @@ gtk_tree_view_column_cell_get_real_size (GtkTreeViewColumn *tree_column,
if (visible == FALSE)
continue;
- if (first_cell == FALSE)
- {
- min_req.width += tree_column->spacing;
- nat_req.width += tree_column->spacing;
- }
-
- /* XXX TODO: Update to use w4h of cell-renderer apis...
- */
gtk_cell_size_request_get_width (GTK_CELL_SIZE_REQUEST (info->cell),
tree_column->tree_view,
&min_req.width, &nat_req.width);
@@ -2638,12 +2637,19 @@ gtk_tree_view_column_cell_get_real_size (GtkTreeViewColumn *tree_column,
nat_req.width,
&min_req.height, &nat_req.height);
+ if (first_cell == FALSE)
+ {
+ min_req.width += tree_column->spacing;
+ nat_req.width += tree_column->spacing;
+ }
+
min_req.width += focus_line_width * 2;
min_req.height += focus_line_width * 2;
nat_req.width += focus_line_width * 2;
nat_req.height += focus_line_width * 2;
info->requested_width = MAX (info->requested_width, min_req.width);
+ info->natural_width = MAX (info->natural_width, nat_req.width);
first_cell = FALSE;
@@ -2872,39 +2878,37 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column,
/* FOCUS */
else if (action == CELL_ACTION_FOCUS)
{
- gint x_offset, y_offset, width, height;
+ gint x_offset, y_offset;
GtkRequisition min_size;
gtk_cell_size_request_get_size (GTK_CELL_SIZE_REQUEST (info->cell),
tree_column->tree_view,
&min_size, NULL);
- width = min_size.width;
- height = min_size.height;
_gtk_cell_renderer_calc_offset (info->cell, &rtl_cell_area,
gtk_widget_get_direction (tree_column->tree_view),
- width, height, &x_offset, &y_offset);
+ min_size.width, min_size.height, &x_offset, &y_offset);
if (special_cells > 1)
{
if (info->has_focus)
{
min_x = rtl_cell_area.x + x_offset;
- max_x = min_x + width;
+ max_x = min_x + min_size.width;
min_y = rtl_cell_area.y + y_offset;
- max_y = min_y + height;
+ max_y = min_y + min_size.height;
}
}
else
{
if (min_x > (rtl_cell_area.x + x_offset))
min_x = rtl_cell_area.x + x_offset;
- if (max_x < rtl_cell_area.x + x_offset + width)
- max_x = rtl_cell_area.x + x_offset + width;
+ if (max_x < rtl_cell_area.x + x_offset + min_size.width)
+ max_x = rtl_cell_area.x + x_offset + min_size.width;
if (min_y > (rtl_cell_area.y + y_offset))
min_y = rtl_cell_area.y + y_offset;
- if (max_y < rtl_cell_area.y + y_offset + height)
- max_y = rtl_cell_area.y + y_offset + height;
+ if (max_y < rtl_cell_area.y + y_offset + min_size.height)
+ max_y = rtl_cell_area.y + y_offset + min_size.height;
}
}
/* EVENT */
@@ -3042,39 +3046,37 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column,
/* FOCUS */
else if (action == CELL_ACTION_FOCUS)
{
- gint width, height, x_offset, y_offset;
+ gint x_offset, y_offset;
GtkRequisition min_size;
gtk_cell_size_request_get_size (GTK_CELL_SIZE_REQUEST (info->cell),
tree_column->tree_view,
&min_size, NULL);
- width = min_size.width;
- height = min_size.height;
_gtk_cell_renderer_calc_offset (info->cell, &rtl_cell_area,
gtk_widget_get_direction (tree_column->tree_view),
- width, height, &x_offset, &y_offset);
+ min_size.width, min_size.height, &x_offset, &y_offset);
if (special_cells > 1)
{
if (info->has_focus)
{
min_x = rtl_cell_area.x + x_offset;
- max_x = min_x + width;
+ max_x = min_x + min_size.width;
min_y = rtl_cell_area.y + y_offset;
- max_y = min_y + height;
+ max_y = min_y + min_size.height;
}
}
else
{
if (min_x > (rtl_cell_area.x + x_offset))
min_x = rtl_cell_area.x + x_offset;
- if (max_x < rtl_cell_area.x + x_offset + width)
- max_x = rtl_cell_area.x + x_offset + width;
+ if (max_x < rtl_cell_area.x + x_offset + min_size.width)
+ max_x = rtl_cell_area.x + x_offset + min_size.width;
if (min_y > (rtl_cell_area.y + y_offset))
min_y = rtl_cell_area.y + y_offset;
- if (max_y < rtl_cell_area.y + y_offset + height)
- max_y = rtl_cell_area.y + y_offset + height;
+ if (max_y < rtl_cell_area.y + y_offset + min_size.height)
+ max_y = rtl_cell_area.y + y_offset + min_size.height;
}
}
/* EVENT */
@@ -3645,16 +3647,21 @@ _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
gboolean install_handler)
{
GList *list;
+ GtkTreeViewColumnPrivate *priv;
+
+ priv = GTK_TREE_VIEW_COLUMN_GET_PRIVATE (tree_column);
for (list = tree_column->cell_list; list; list = list->next)
{
GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
info->requested_width = 0;
+ info->natural_width = 0;
}
tree_column->dirty = TRUE;
tree_column->requested_width = -1;
tree_column->width = 0;
+ priv->natural_width = -1;
if (tree_column->tree_view &&
gtk_widget_get_realized (tree_column->tree_view))
@@ -3847,5 +3854,190 @@ gtk_tree_view_column_get_desired_size (GtkTreeViewColumn *column,
minimal_size, desired_size);
}
+/**
+ * gtk_tree_view_column_get_natural_width:
+ * @tree_column: A #GtkTreeViewColumn
+ * @minimum_width: location for storing the minimum width, or %NULL
+ * @natural_width: location for storing the natural width, or %NULL
+ *
+ * Retreives @tree_column's minimum and natural width.
+ *
+ * Since: 3.0
+ */
+void
+gtk_tree_view_column_get_natural_width (GtkTreeViewColumn *column,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ GList *list;
+ gboolean first_cell = TRUE;
+ gint focus_line_width;
+ gint min = 0, nat = 0;
+
+ g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
+
+ gtk_widget_style_get (column->tree_view, "focus-line-width", &focus_line_width, NULL);
+
+ for (list = column->cell_list; list; list = list->next)
+ {
+ GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
+ gint cell_min, cell_nat;
+ gboolean visible;
+
+ g_object_get (info->cell, "visible", &visible, NULL);
+
+ if (visible == FALSE)
+ continue;
+
+ if (first_cell == FALSE)
+ {
+ min += column->spacing;
+ nat += column->spacing;
+ }
+
+ gtk_cell_size_request_get_width (GTK_CELL_SIZE_REQUEST (info->cell),
+ column->tree_view, &cell_min, &cell_nat);
+
+ cell_min += focus_line_width * 2;
+ cell_nat += focus_line_width * 2;
+
+ min += cell_min;
+ nat += cell_nat;
+
+ /* Store 'requested_width' and 'natural_width' to cache all the requests
+ * for every row in the column; natural space distribution is only calculated
+ * once for the whole column for now. */
+ info->requested_width = MAX (info->requested_width, cell_min);
+ info->natural_width = MAX (info->natural_width, cell_nat);
+
+ first_cell = FALSE;
+ }
+
+ if (minimum_width)
+ *minimum_width = min;
+
+ if (natural_width)
+ *natural_width = nat;
+}
+
+/**
+ * gtk_tree_view_column_get_height_for_width:
+ * @tree_column: A #GtkTreeViewColumn
+ * @width: the width available for allocation
+ * @minimum_height: location for storing the minimum height, or %NULL
+ * @natural_height: location for storing the natural height, or %NULL
+ *
+ * Retreives @tree_column's minimum and natural height if it were rendered to
+ * @widget with the specified @height.
+ *
+ * Since: 3.0
+ */
+void
+gtk_tree_view_column_get_height_for_width (GtkTreeViewColumn *column,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GList *list;
+ GArray *array;
+ gint size = width;
+ gint focus_line_width;
+ gint expand_cell_count = 0, i;
+ gboolean first_cell = TRUE;
+ gint min_height = 0, nat_height = 0;
+ GtkRequestedSize *sizes;
+
+ g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
+
+ gtk_widget_style_get (column->tree_view, "focus-line-width", &focus_line_width, NULL);
+
+ array = g_array_new (0, TRUE, sizeof (GtkRequestedSize));
+
+
+ /* First get the overall expand space and collect the cell requests */
+ for (list = column->cell_list; list; list = list->next)
+ {
+ GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
+ gboolean visible;
+ GtkRequestedSize requested;
+
+ g_object_get (info->cell, "visible", &visible, NULL);
+
+ if (visible == FALSE)
+ continue;
+
+ if (info->expand == TRUE)
+ expand_cell_count++;
+
+ if (first_cell == FALSE)
+ size -= column->spacing;
+
+ size -= focus_line_width * 2;
+
+ /* Here the collective minimum/natural width for all rows
+ * has necessarily been cached by gtk_tree_view_column_get_natural_width().
+ *
+ * As the allocated width is based on the collective widths of all rows,
+ * the allocated width for a cell will be the same in each row.
+ *
+ * However the height-for-width must also be calculated for each
+ * row based on the aligned width in order to determine the row height.
+ *
+ * OPTIMIZE ME: It would be better to calculate the allocations of the cells once
+ * and caching an extra info->allocated_width in order to avoid this
+ * calculation for every row.
+ *
+ * Note we would use the real minimums/naturals as reported
+ * by the cells for each row here if we were to display
+ * the cells unaligned (which is more expensive to calculate
+ * but would allow cells to flow more naturally inside columns).
+ */
+ requested.data = info;
+ requested.minimum_size = info->requested_width;
+ requested.natural_size = info->natural_width;
+ g_array_append_val (array, requested);
+
+ first_cell = FALSE;
+ }
+
+ /* Distribute as much of remaining 'size' as possible before sharing expand space */
+ sizes = (GtkRequestedSize *)array->data;
+ size = _gtk_distribute_allocation (size, array->len, sizes);
+
+ /* The rest gets split up evenly among expanding cells */
+ size /= expand_cell_count;
+
+ /* Collect the minimum and natural height for the allocations of cells */
+ for (i = 0, list = column->cell_list; list; list = list->next)
+ {
+ GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
+ gint cell_min, cell_nat;
+ gboolean visible;
+
+ g_object_get (info->cell, "visible", &visible, NULL);
+
+ if (visible == FALSE)
+ continue;
+
+ gtk_cell_size_request_get_height_for_width (GTK_CELL_SIZE_REQUEST (info->cell),
+ column->tree_view,
+ sizes[i].minimum_size + (info->expand ? size : 0),
+ &cell_min, &cell_nat);
+
+ min_height = MAX (min_height, cell_min);
+ nat_height = MAX (nat_height, cell_nat);
+
+ i++;
+ }
+ g_array_free (array, TRUE);
+
+ if (minimum_height)
+ *minimum_height = min_height;
+
+ if (natural_height)
+ *natural_height = nat_height;
+}
+
+
#define __GTK_TREE_VIEW_COLUMN_C__
#include "gtkaliasdef.c"
diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h
index 249d22d..8487a9d 100644
--- a/gtk/gtktreeviewcolumn.h
+++ b/gtk/gtktreeviewcolumn.h
@@ -226,9 +226,20 @@ void gtk_tree_view_column_cell_get_size (GtkTreeViewCol
gint *y_offset,
gint *width,
gint *height);
-void gtk_tree_view_column_get_desired_size (GtkTreeViewColumn *column,
- GtkRequisition *minimal_size,
- GtkRequisition *desired_size);
+
+/* XXX: this ones going away ... */
+void gtk_tree_view_column_get_desired_size (GtkTreeViewColumn *column,
+ GtkRequisition *minimal_size,
+ GtkRequisition *desired_size);
+
+void gtk_tree_view_column_get_natural_width (GtkTreeViewColumn *column,
+ gint *minimum_width,
+ gint *natural_width);
+void gtk_tree_view_column_get_height_for_width(GtkTreeViewColumn *column,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height);
+
gboolean gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_focus_cell (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]