[gtk+] Use minimum/natural size semantics



commit 6d53c2339f79baa0b295ecc614f41f9daab2e132
Author: John Lindgren <john lindgren aol com>
Date:   Tue Dec 18 02:06:12 2012 -0500

    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 16195ad and is no longer necessary.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=691751

 gtk/gtktreeprivate.h    |    4 +-
 gtk/gtktreeview.c       |  170 ++++++++++++++++++----------------------------
 gtk/gtktreeviewcolumn.c |   62 +++++++++---------
 3 files changed, 101 insertions(+), 135 deletions(-)
---
diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h
index 9817c5c..fcdcf81 100644
--- a/gtk/gtktreeprivate.h
+++ b/gtk/gtktreeprivate.h
@@ -106,7 +106,9 @@ void _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column);
  
 void _gtk_tree_view_column_set_tree_view    (GtkTreeViewColumn *column,
 					     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,
 					     int                x_offset,
 					     int                width);
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 871a8e4..d0b06e9 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -385,10 +385,10 @@ struct _GtkTreeViewPrivate
   gint drag_pos;
   gint x_drag;
 
-  /* Non-interactive Header Resizing, expand flag support */
-  gint last_extra_space;
-  gint last_extra_space_per_column;
-  gint last_number_of_expand_columns;
+  /* Column width allocation */
+  gint minimum_width;
+  gint natural_width;
+  gint n_expand_columns;
 
   /* ATK Hack */
   GtkTreeDestroyCountFunc destroy_count_func;
@@ -492,8 +492,6 @@ 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;
 
@@ -1719,6 +1717,9 @@ 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;
@@ -1751,8 +1752,6 @@ 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;
 
@@ -2395,12 +2394,16 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget,
   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
   GList *list;
   GtkTreeViewColumn *column;
-  gint width = 0;
+  gint column_minimum, column_natural;
 
   /* 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)
@@ -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)
 	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
@@ -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);
 
-  *minimum = *natural = height;
+  if (minimum != NULL)
+    *minimum = height;
+  if (natural != NULL)
+    *natural = height;
 }
 
 static int
@@ -2459,12 +2473,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
   GList *list, *first_column, *last_column;
   GtkTreeViewColumn *column;
   GtkAllocation widget_allocation;
-  gint width = 0;
-  gint extra, extra_per_column, extra_for_last;
-  gint full_requested_width = 0;
-  gint number_of_expand_columns = 0;
+  gint minimum_width, natural_width, n_expand_columns, width;
+  gint column_minimum, column_natural, column_width;
   gboolean rtl;
-  gboolean update_expand;
   
   tree_view = GTK_TREE_VIEW (widget);
 
@@ -2484,111 +2495,65 @@ 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;
 
-      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)
-    extra_per_column = extra/number_of_expand_columns;
-  else
-    extra_per_column = 0;
+  width = MAX (widget_allocation.width, minimum_width);
 
-  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->last_number_of_expand_columns = number_of_expand_columns;
+      tree_view->priv->width = width;
+      if (width_changed)
+        *width_changed = TRUE;
     }
 
-  for (list = (rtl ? last_column : first_column); 
-       list != (rtl ? first_column->prev : last_column->next);
-       list = (rtl ? list->prev : list->next)) 
+  /* 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)) 
     {
-      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);
+      _gtk_tree_view_column_request_width (column, &column_minimum, &column_natural);
+      
+      column_width = column_natural;
 
-      if (gtk_tree_view_column_get_expand (column))
-	{
-	  if (number_of_expand_columns == 1)
+      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)
 	    {
-	      /* We add the remander to the last column as
-	       * */
-	      column_width += extra;
+	      column_width = column_natural + (width - natural_width);
 	    }
-	  else
+	  else if (gtk_tree_view_column_get_expand (column))
 	    {
-	      column_width += extra_per_column;
-	      extra -= extra_per_column;
-	      number_of_expand_columns --;
+	      column_width = column_natural + (width - natural_width) / n_expand_columns;
+	      n_expand_columns--;
 	    }
-	}
-      else if (number_of_expand_columns == 0 &&
-	       list == last_column)
+        }
+      else if (width < natural_width)
 	{
-	  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
-       * 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
-   * 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;
+	
+      _gtk_tree_view_column_allocate (column, width - column_width, column_width);
+      
+      minimum_width -= column_minimum;
+      natural_width -= column_natural;
+      width -= column_width;
     }
 }
 
@@ -6062,7 +6027,6 @@ 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 6a47dbe..3f32c81 100644
--- a/gtk/gtktreeviewcolumn.c
+++ b/gtk/gtktreeviewcolumn.c
@@ -2092,48 +2092,48 @@ gtk_tree_view_column_get_x_offset (GtkTreeViewColumn *tree_column)
   return tree_column->priv->x_offset;
 }
 
-gint
-_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column)
+void
+_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column,
+                                     gint              *minimum,
+                                     gint              *natural)
 {
-  GtkTreeViewColumnPrivate *priv;
-  gint real_requested_width;
-
-  priv = tree_column->priv;
+  GtkTreeViewColumnPrivate *priv = tree_column->priv;
+  gint minimum_width = 1, natural_width = 1;
+  gint button_minimum, button_natural;
 
-  if (priv->fixed_width != -1)
-    {
-      real_requested_width = priv->fixed_width;
-    }
-  else if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
+  if (priv->column_type != GTK_TREE_VIEW_COLUMN_FIXED)
     {
-      gint button_request;
-      gint requested_width;
+      gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &minimum_width, &natural_width);
+      minimum_width += priv->padding;
+      natural_width += priv->padding;
 
-      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);
+      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);
+        }
     }
-  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->fixed_width != -1)
+    natural_width = MAX (priv->fixed_width, minimum_width);
 
   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)
-    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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]