Commit 6d53c233 authored by John Lindgren's avatar John Lindgren Committed by Benjamin Otte

Use minimum/natural size semantics

Rewrites gtk_tree_view_column_request_width() and
gtk_tree_view_size_allocate_columns() to respect the minimum and natural
sizes that are already being returned by
gtk_cell_area_context_get_preferred_width().

The convoluted logic explained (not!) by this comment has been removed:
“Only update the expand value if the width of the widget has changed, or
the number of expand columns has changed, or if there are no expand
columns, or if we didn't have an size-allocation yet after the last
validated node.”  This logic seems to have been a workaround for the
“jumping” behavior fixed in 16195adc and is no longer necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=691751
parent 9b6661a0
...@@ -106,7 +106,9 @@ void _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column); ...@@ -106,7 +106,9 @@ void _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column);
void _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column, void _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
GtkTreeView *tree_view); GtkTreeView *tree_view);
gint _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column); void _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column,
gint *minimum,
gint *natural);
void _gtk_tree_view_column_allocate (GtkTreeViewColumn *tree_column, void _gtk_tree_view_column_allocate (GtkTreeViewColumn *tree_column,
int x_offset, int x_offset,
int width); int width);
......
...@@ -385,10 +385,10 @@ struct _GtkTreeViewPrivate ...@@ -385,10 +385,10 @@ struct _GtkTreeViewPrivate
gint drag_pos; gint drag_pos;
gint x_drag; gint x_drag;
/* Non-interactive Header Resizing, expand flag support */ /* Column width allocation */
gint last_extra_space; gint minimum_width;
gint last_extra_space_per_column; gint natural_width;
gint last_number_of_expand_columns; gint n_expand_columns;
/* ATK Hack */ /* ATK Hack */
GtkTreeDestroyCountFunc destroy_count_func; GtkTreeDestroyCountFunc destroy_count_func;
...@@ -492,8 +492,6 @@ struct _GtkTreeViewPrivate ...@@ -492,8 +492,6 @@ struct _GtkTreeViewPrivate
guint in_grab : 1; guint in_grab : 1;
guint post_validation_flag : 1;
/* Whether our key press handler is to avoid sending an unhandled binding to the search entry */ /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
guint search_entry_avoid_unhandled_binding : 1; guint search_entry_avoid_unhandled_binding : 1;
...@@ -1719,6 +1717,9 @@ gtk_tree_view_init (GtkTreeView *tree_view) ...@@ -1719,6 +1717,9 @@ gtk_tree_view_init (GtkTreeView *tree_view)
tree_view->priv->header_height = 1; tree_view->priv->header_height = 1;
tree_view->priv->x_drag = 0; tree_view->priv->x_drag = 0;
tree_view->priv->drag_pos = -1; tree_view->priv->drag_pos = -1;
tree_view->priv->minimum_width = 0;
tree_view->priv->natural_width = 0;
tree_view->priv->n_expand_columns = 0;
tree_view->priv->header_has_focus = FALSE; tree_view->priv->header_has_focus = FALSE;
tree_view->priv->pressed_button = -1; tree_view->priv->pressed_button = -1;
tree_view->priv->press_start_x = -1; tree_view->priv->press_start_x = -1;
...@@ -1751,8 +1752,6 @@ gtk_tree_view_init (GtkTreeView *tree_view) ...@@ -1751,8 +1752,6 @@ gtk_tree_view_init (GtkTreeView *tree_view)
tree_view->priv->tooltip_column = -1; tree_view->priv->tooltip_column = -1;
tree_view->priv->post_validation_flag = FALSE;
tree_view->priv->last_button_x = -1; tree_view->priv->last_button_x = -1;
tree_view->priv->last_button_y = -1; tree_view->priv->last_button_y = -1;
...@@ -2395,12 +2394,16 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget, ...@@ -2395,12 +2394,16 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget,
GtkTreeView *tree_view = GTK_TREE_VIEW (widget); GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *list; GList *list;
GtkTreeViewColumn *column; GtkTreeViewColumn *column;
gint width = 0; gint column_minimum, column_natural;
/* we validate some rows initially just to make sure we have some size. /* we validate some rows initially just to make sure we have some size.
* In practice, with a lot of static lists, this should get a good width. * In practice, with a lot of static lists, this should get a good width.
*/ */
do_validate_rows (tree_view, FALSE); do_validate_rows (tree_view, FALSE);
tree_view->priv->minimum_width = 0;
tree_view->priv->natural_width = 0;
tree_view->priv->n_expand_columns = 0;
/* keep this in sync with size_allocate below */ /* keep this in sync with size_allocate below */
for (list = tree_view->priv->columns; list; list = list->next) for (list = tree_view->priv->columns; list; list = list->next)
...@@ -2409,10 +2412,18 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget, ...@@ -2409,10 +2412,18 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget,
if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
continue; continue;
width += _gtk_tree_view_column_request_width (column); _gtk_tree_view_column_request_width (column, &column_minimum, &column_natural);
tree_view->priv->minimum_width += column_minimum;
tree_view->priv->natural_width += column_natural;
if (gtk_tree_view_column_get_expand (column))
tree_view->priv->n_expand_columns++;
} }
*minimum = *natural = width; if (minimum != NULL)
*minimum = tree_view->priv->minimum_width;
if (natural != NULL)
*natural = tree_view->priv->natural_width;
} }
static void static void
...@@ -2427,7 +2438,10 @@ gtk_tree_view_get_preferred_height (GtkWidget *widget, ...@@ -2427,7 +2438,10 @@ gtk_tree_view_get_preferred_height (GtkWidget *widget,
height = tree_view->priv->height + gtk_tree_view_get_effective_header_height (tree_view); height = tree_view->priv->height + gtk_tree_view_get_effective_header_height (tree_view);
*minimum = *natural = height; if (minimum != NULL)
*minimum = height;
if (natural != NULL)
*natural = height;
} }
static int static int
...@@ -2459,12 +2473,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, ...@@ -2459,12 +2473,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
GList *list, *first_column, *last_column; GList *list, *first_column, *last_column;
GtkTreeViewColumn *column; GtkTreeViewColumn *column;
GtkAllocation widget_allocation; GtkAllocation widget_allocation;
gint width = 0; gint minimum_width, natural_width, n_expand_columns, width;
gint extra, extra_per_column, extra_for_last; gint column_minimum, column_natural, column_width;
gint full_requested_width = 0;
gint number_of_expand_columns = 0;
gboolean rtl; gboolean rtl;
gboolean update_expand;
tree_view = GTK_TREE_VIEW (widget); tree_view = GTK_TREE_VIEW (widget);
...@@ -2484,111 +2495,65 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, ...@@ -2484,111 +2495,65 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
/* find out how many extra space and expandable columns we have */
for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
{
column = (GtkTreeViewColumn *)list->data;
if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
continue;
full_requested_width += _gtk_tree_view_column_request_width (column);
if (gtk_tree_view_column_get_expand (column))
number_of_expand_columns++;
}
/* Only update the expand value if the width of the widget has changed,
* or the number of expand columns has changed, or if there are no expand
* columns, or if we didn't have an size-allocation yet after the
* last validated node.
*/
update_expand = (width_changed && *width_changed == TRUE)
|| number_of_expand_columns != tree_view->priv->last_number_of_expand_columns
|| number_of_expand_columns == 0
|| tree_view->priv->post_validation_flag == TRUE;
tree_view->priv->post_validation_flag = FALSE;
gtk_widget_get_allocation (widget, &widget_allocation); gtk_widget_get_allocation (widget, &widget_allocation);
if (!update_expand)
{
extra = tree_view->priv->last_extra_space;
extra_for_last = MAX (widget_allocation.width - full_requested_width - extra, 0);
}
else
{
extra = MAX (widget_allocation.width - full_requested_width, 0);
extra_for_last = 0;
tree_view->priv->last_extra_space = extra; minimum_width = tree_view->priv->minimum_width;
} natural_width = tree_view->priv->natural_width;
n_expand_columns = tree_view->priv->n_expand_columns;
if (number_of_expand_columns > 0) width = MAX (widget_allocation.width, minimum_width);
extra_per_column = extra/number_of_expand_columns;
else
extra_per_column = 0;
if (update_expand) /* We change the width here. The user might have been resizing columns,
* which changes the total width of the tree view. This is of
* importance for getting the horizontal scroll bar right.
*/
if (tree_view->priv->width != width)
{ {
tree_view->priv->last_extra_space_per_column = extra_per_column; tree_view->priv->width = width;
tree_view->priv->last_number_of_expand_columns = number_of_expand_columns; if (width_changed)
*width_changed = TRUE;
} }
for (list = (rtl ? last_column : first_column); /* iterate through columns in reverse order */
list != (rtl ? first_column->prev : last_column->next); for (list = (rtl ? first_column : last_column);
list = (rtl ? list->prev : list->next)) list != (rtl ? last_column->next : first_column->prev);
list = (rtl ? list->next : list->prev))
{ {
gint column_width;
column = list->data; column = list->data;
if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
continue; continue;
column_width = _gtk_tree_view_column_request_width (column); _gtk_tree_view_column_request_width (column, &column_minimum, &column_natural);
column_width = column_natural;
if (gtk_tree_view_column_get_expand (column)) if (width > natural_width)
{ {
if (number_of_expand_columns == 1) /* We need to expand some columns. If there are none marked to
* expand, give all the extra space to the last column. */
if (n_expand_columns == 0)
{ {
/* We add the remander to the last column as column_width = column_natural + (width - natural_width);
* */
column_width += extra;
} }
else else if (gtk_tree_view_column_get_expand (column))
{ {
column_width += extra_per_column; column_width = column_natural + (width - natural_width) / n_expand_columns;
extra -= extra_per_column; n_expand_columns--;
number_of_expand_columns --;
} }
} }
else if (number_of_expand_columns == 0 && else if (width < natural_width)
list == last_column)
{ {
column_width += extra; /* We need to shrink some columns. Starting with later columns,
* shrink each one down to its minimum width as necessary. */
column_width = MAX (column_natural + (width - natural_width), column_minimum);
} }
/* In addition to expand, the last column can get even more _gtk_tree_view_column_allocate (column, width - column_width, column_width);
* extra space so all available space is filled up.
*/ minimum_width -= column_minimum;
if (extra_for_last > 0 && list == last_column) natural_width -= column_natural;
column_width += extra_for_last; width -= column_width;
_gtk_tree_view_column_allocate (column, width, column_width);
width += column_width;
}
/* We change the width here. The user might have been resizing columns,
* which changes the total width of the tree view. This is of
* importance for getting the horizontal scroll bar right.
*/
if (tree_view->priv->width != width)
{
tree_view->priv->width = width;
if (width_changed)
*width_changed = TRUE;
} }
} }
...@@ -6062,7 +6027,6 @@ validate_row (GtkTreeView *tree_view, ...@@ -6062,7 +6027,6 @@ validate_row (GtkTreeView *tree_view,
_gtk_rbtree_node_set_height (tree, node, height); _gtk_rbtree_node_set_height (tree, node, height);
} }
_gtk_rbtree_node_mark_valid (tree, node); _gtk_rbtree_node_mark_valid (tree, node);
tree_view->priv->post_validation_flag = TRUE;
return retval; return retval;
} }
......
...@@ -2092,48 +2092,48 @@ gtk_tree_view_column_get_x_offset (GtkTreeViewColumn *tree_column) ...@@ -2092,48 +2092,48 @@ gtk_tree_view_column_get_x_offset (GtkTreeViewColumn *tree_column)
return tree_column->priv->x_offset; return tree_column->priv->x_offset;
} }
gint void
_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column) _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column,
gint *minimum,
gint *natural)
{ {
GtkTreeViewColumnPrivate *priv; GtkTreeViewColumnPrivate *priv = tree_column->priv;
gint real_requested_width; gint minimum_width = 1, natural_width = 1;
gint button_minimum, button_natural;
priv = tree_column->priv;
if (priv->fixed_width != -1) if (priv->column_type != GTK_TREE_VIEW_COLUMN_FIXED)
{
real_requested_width = priv->fixed_width;
}
else if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
{ {
gint button_request; gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &minimum_width, &natural_width);
gint requested_width; minimum_width += priv->padding;
natural_width += priv->padding;
gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL); if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
requested_width += priv->padding; {
gtk_widget_get_preferred_width (priv->button, &button_minimum, &button_natural);
gtk_widget_get_preferred_width (priv->button, &button_request, NULL); minimum_width = MAX (minimum_width, button_minimum);
real_requested_width = MAX (requested_width, button_request); natural_width = MAX (natural_width, button_natural);
}
} }
else
{
gint requested_width;
gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL); if (priv->fixed_width != -1)
requested_width += priv->padding; natural_width = MAX (priv->fixed_width, minimum_width);
real_requested_width = requested_width;
if (real_requested_width < 0)
real_requested_width = 0;
}
if (priv->min_width != -1) if (priv->min_width != -1)
real_requested_width = MAX (real_requested_width, priv->min_width); {
minimum_width = MAX (minimum_width, priv->min_width);
natural_width = MAX (natural_width, priv->min_width);
}
if (priv->max_width != -1) if (priv->max_width != -1)
real_requested_width = MIN (real_requested_width, priv->max_width); {
minimum_width = MIN (minimum_width, priv->max_width);
natural_width = MIN (natural_width, priv->max_width);
}
return real_requested_width; if (minimum != NULL)
*minimum = minimum_width;
if (natural != NULL)
*natural = natural_width;
} }
void void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment