diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index d813352572..a2d6d6c80a 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -99,9 +99,7 @@ void _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column); void _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column, GtkTreeView *tree_view); -void _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column, - gint *minimum, - gint *natural); +gint _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column); void _gtk_tree_view_column_allocate (GtkTreeViewColumn *tree_column, int x_offset, int width); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 9a7b337c32..0001c18101 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -371,10 +371,10 @@ struct _GtkTreeViewPrivate gint drag_pos; gint x_drag; - /* Column width allocation */ - gint minimum_width; - gint natural_width; - gint n_expand_columns; + /* Non-interactive Header Resizing, expand flag support */ + gint last_extra_space; + gint last_extra_space_per_column; + gint last_number_of_expand_columns; /* ATK Hack */ GtkTreeDestroyCountFunc destroy_count_func; @@ -481,6 +481,8 @@ struct _GtkTreeViewPrivate 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 */ guint search_entry_avoid_unhandled_binding : 1; @@ -1790,9 +1792,6 @@ gtk_tree_view_init (GtkTreeView *tree_view) tree_view->priv->header_height = 1; tree_view->priv->x_drag = 0; 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->pressed_button = -1; tree_view->priv->press_start_x = -1; @@ -1825,6 +1824,8 @@ gtk_tree_view_init (GtkTreeView *tree_view) 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_y = -1; @@ -2565,16 +2566,12 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget, GtkTreeView *tree_view = GTK_TREE_VIEW (widget); GList *list; GtkTreeViewColumn *column; - gint column_minimum, column_natural; + gint width = 0; /* 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. */ 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 */ for (list = tree_view->priv->columns; list; list = list->next) @@ -2583,18 +2580,10 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget, if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) continue; - _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++; + width += _gtk_tree_view_column_request_width (column); } - if (minimum != NULL) - *minimum = tree_view->priv->minimum_width; - if (natural != NULL) - *natural = tree_view->priv->natural_width; + *minimum = *natural = width; } static void @@ -2609,10 +2598,7 @@ gtk_tree_view_get_preferred_height (GtkWidget *widget, height = gtk_tree_view_get_height (tree_view) + gtk_tree_view_get_effective_header_height (tree_view); - if (minimum != NULL) - *minimum = height; - if (natural != NULL) - *natural = height; + *minimum = *natural = height; } static int @@ -2644,9 +2630,12 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, GList *list, *first_column, *last_column; GtkTreeViewColumn *column; GtkAllocation widget_allocation; - gint minimum_width, natural_width, n_expand_columns, width; - gint column_minimum, column_natural, column_width; + gint width = 0; + gint extra, extra_per_column, extra_for_last; + gint full_requested_width = 0; + gint number_of_expand_columns = 0; gboolean rtl; + gboolean update_expand; tree_view = GTK_TREE_VIEW (widget); @@ -2666,13 +2655,101 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, 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); + 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; - minimum_width = tree_view->priv->minimum_width; - natural_width = tree_view->priv->natural_width; - n_expand_columns = tree_view->priv->n_expand_columns; + tree_view->priv->last_extra_space = extra; + } - width = MAX (widget_allocation.width, minimum_width); + if (number_of_expand_columns > 0) + extra_per_column = extra/number_of_expand_columns; + else + extra_per_column = 0; + + if (update_expand) + { + tree_view->priv->last_extra_space_per_column = extra_per_column; + tree_view->priv->last_number_of_expand_columns = number_of_expand_columns; + } + + for (list = (rtl ? last_column : first_column); + list != (rtl ? first_column->prev : last_column->next); + list = (rtl ? list->prev : list->next)) + { + gint column_width; + + column = list->data; + + if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) + continue; + + column_width = _gtk_tree_view_column_request_width (column); + + if (gtk_tree_view_column_get_expand (column)) + { + if (number_of_expand_columns == 1) + { + /* We add the remander to the last column as + * */ + column_width += extra; + } + else + { + column_width += extra_per_column; + extra -= extra_per_column; + number_of_expand_columns --; + } + } + else if (number_of_expand_columns == 0 && + list == last_column) + { + column_width += extra; + } + + /* In addition to expand, the last column can get even more + * extra space so all available space is filled up. + */ + if (extra_for_last > 0 && list == last_column) + column_width += extra_for_last; + + _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 @@ -2684,48 +2761,6 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, if (width_changed) *width_changed = TRUE; } - - /* iterate through columns in reverse order */ - for (list = (rtl ? first_column : last_column); - list != (rtl ? last_column->next : first_column->prev); - list = (rtl ? list->next : list->prev)) - { - column = list->data; - - if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) - continue; - - _gtk_tree_view_column_request_width (column, &column_minimum, &column_natural); - - column_width = column_natural; - - if (width > natural_width) - { - /* 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) - { - column_width = column_natural + (width - natural_width); - } - else if (gtk_tree_view_column_get_expand (column)) - { - column_width = column_natural + (width - natural_width) / n_expand_columns; - n_expand_columns--; - } - } - else if (width < natural_width) - { - /* 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); - } - - _gtk_tree_view_column_allocate (column, width - column_width, column_width); - - minimum_width -= column_minimum; - natural_width -= column_natural; - width -= column_width; - } } /* GtkWidget::size_allocate helper */ @@ -6186,6 +6221,7 @@ validate_row (GtkTreeView *tree_view, _gtk_rbtree_node_set_height (tree, node, height); } _gtk_rbtree_node_mark_valid (tree, node); + tree_view->priv->post_validation_flag = TRUE; return retval; } diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 5001217fc0..487b44b849 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -2094,48 +2094,48 @@ gtk_tree_view_column_get_x_offset (GtkTreeViewColumn *tree_column) return tree_column->priv->x_offset; } -void -_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column, - gint *minimum, - gint *natural) +gint +_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column) { - GtkTreeViewColumnPrivate *priv = tree_column->priv; - gint minimum_width = 1, natural_width = 1; - gint button_minimum, button_natural; + GtkTreeViewColumnPrivate *priv; + gint real_requested_width; - if (priv->column_type != GTK_TREE_VIEW_COLUMN_FIXED) - { - gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &minimum_width, &natural_width); - minimum_width += priv->padding; - natural_width += priv->padding; - - if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view))) - { - gtk_widget_get_preferred_width (priv->button, &button_minimum, &button_natural); - minimum_width = MAX (minimum_width, button_minimum); - natural_width = MAX (natural_width, button_natural); - } - } + priv = tree_column->priv; if (priv->fixed_width != -1) - natural_width = MAX (priv->fixed_width, minimum_width); + { + real_requested_width = priv->fixed_width; + } + else if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view))) + { + gint button_request; + gint requested_width; + + gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL); + requested_width += priv->padding; + + gtk_widget_get_preferred_width (priv->button, &button_request, NULL); + real_requested_width = MAX (requested_width, button_request); + } + else + { + gint requested_width; + + gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL); + requested_width += priv->padding; + + real_requested_width = requested_width; + if (real_requested_width < 0) + real_requested_width = 0; + } if (priv->min_width != -1) - { - minimum_width = MAX (minimum_width, priv->min_width); - natural_width = MAX (natural_width, priv->min_width); - } + real_requested_width = MAX (real_requested_width, priv->min_width); if (priv->max_width != -1) - { - minimum_width = MIN (minimum_width, priv->max_width); - natural_width = MIN (natural_width, priv->max_width); - } + real_requested_width = MIN (real_requested_width, priv->max_width); - if (minimum != NULL) - *minimum = minimum_width; - if (natural != NULL) - *natural = natural_width; + return real_requested_width; } void