[gtk+] Added logic to GtkScrolledWindow when allocating height-for-width children.



commit e85dad38e2c579598c142515c8b816ea6657e0c8
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Tue Oct 12 17:16:32 2010 +0900

    Added logic to GtkScrolledWindow when allocating height-for-width children.
    
    This patch makes the scrolled window reconsider allocating the child
    the full width or height (depending on the child's request mode) without
    a scrollbar. For instance when the child is height-for-width; the child
    will first be tested if the content's height for full allocated width
    (without a vscrollbar) will allow the contents height for that width
    to fit the allocated height.
    
    Patch is a simplified version of code inspected in st-scroll-view.c.
    Note that this patch assumes children will begin to scroll only after
    reaching their minimum size; adding a property to the future
    GtkScrollableIface to decide whether to scroll-to-minimum or scroll-to-natural
    will effect this code (it should then reconsider whether the child
    will scroll below the natural size instead of the minimum).
    
    Patch addresses bug 629778.

 gtk/gtkscrolledwindow.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 123 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index a6058b1..1a13b4a 100644
--- a/gtk/gtkscrolledwindow.c
+++ b/gtk/gtkscrolledwindow.c
@@ -1453,10 +1453,132 @@ gtk_scrolled_window_size_allocate (GtkWidget     *widget,
   child = gtk_bin_get_child (bin);
   if (child && gtk_widget_get_visible (child))
     {
-      gboolean previous_vvis;
+      gint child_min_width;
+      gint child_min_height;
       gboolean previous_hvis;
+      gboolean previous_vvis;
       guint count = 0;
 
+      /* In the case that both scrollbars are visible in the previous round,
+       * we dont do our guess-work before hand because it's possible some
+       * infinite recursion was detected (leave it up to the child scrollable
+       * widget in this case to drive the scrollbar visibility completely 
+       * with the adjustment values).
+       */
+      if (!priv->vscrollbar_visible || !priv->hscrollbar_visible)
+	{
+
+	  /* Determine scrollbar visibility first via hfw apis */
+	  if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+	    {
+	      gtk_widget_get_preferred_width (child, &child_min_width, NULL);
+	      
+	      if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+		{
+		  /* First try without a vertical scrollbar if the content will fit the height
+		   * given the extra width of the scrollbar */
+		  gtk_widget_get_preferred_height_for_width (child, allocation->width, 
+							     &child_min_height, NULL);
+		  
+		  if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+		    {
+		      /* Does the content height fit the allocation height ? */
+		      priv->vscrollbar_visible = child_min_height > allocation->height;
+		      
+		      /* Does the content width fit the allocation with minus a possible scrollbar ? */
+		      priv->hscrollbar_visible = 
+			child_min_width > allocation->width - 
+			(priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+		      
+		      /* Now that we've guessed the hscrollbar, does the content height fit
+		       * the possible new allocation height ? */
+		      priv->vscrollbar_visible = 
+			child_min_height > allocation->height - 
+			(priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+		      
+		      /* Now that we've guessed the vscrollbar, does the content width fit
+		       * the possible new allocation width ? */
+		      priv->hscrollbar_visible = 
+			child_min_width > allocation->width - 
+			(priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+		    }
+		  else /* priv->hscrollbar_policy != GTK_POLICY_AUTOMATIC */
+		    {
+		      priv->hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
+		      priv->vscrollbar_visible = child_min_height > allocation->height - 
+			(priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+		    }
+		}
+	      else /* priv->vscrollbar_policy != GTK_POLICY_AUTOMATIC */
+		{
+		  priv->vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
+		  
+		  if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+		    priv->hscrollbar_visible = 
+		      child_min_width > allocation->width - 
+		      (priv->vscrollbar_visible ? 0 : sb_width + sb_spacing);
+		  else
+		    priv->hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
+		}
+	    } 
+	  else /* GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT */
+	    {
+	      gtk_widget_get_preferred_height (child, &child_min_height, NULL);
+	      
+	      if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+		{
+		  /* First try without a horizontal scrollbar if the content will fit the width
+		   * given the extra height of the scrollbar */
+		  gtk_widget_get_preferred_width_for_height (child, allocation->height, 
+							     &child_min_width, NULL);
+		  
+		  if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+		    {
+		      /* Does the content width fit the allocation width ? */
+		      priv->hscrollbar_visible = child_min_width > allocation->width;
+		      
+		      /* Does the content height fit the allocation with minus a possible scrollbar ? */
+		      priv->vscrollbar_visible = 
+			child_min_height > allocation->height - 
+			(priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+		      
+		      /* Now that we've guessed the vscrollbar, does the content width fit
+		       * the possible new allocation width ? */
+		      priv->hscrollbar_visible = 
+			child_min_width > allocation->width - 
+			(priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+		      
+		      /* Now that we've guessed the hscrollbar, does the content height fit
+		       * the possible new allocation height ? */
+		      priv->vscrollbar_visible = 
+			child_min_height > allocation->height - 
+			(priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+		    }
+		  else /* priv->vscrollbar_policy != GTK_POLICY_AUTOMATIC */
+		    {
+		      priv->vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
+		      priv->hscrollbar_visible = child_min_width > allocation->width - 
+			(priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+		    }
+		}
+	      else /* priv->hscrollbar_policy != GTK_POLICY_AUTOMATIC */
+		{
+		  priv->hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
+		  
+		  if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+		    priv->vscrollbar_visible = 
+		      child_min_height > allocation->height - 
+		      (priv->hscrollbar_visible ? 0 : sb_height + sb_spacing);
+		  else
+		    priv->vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
+		}
+	    }
+	}
+
+      /* Now after guessing scrollbar visibility; fall back on the allocation loop which 
+       * observes the adjustments to detect scrollbar visibility and also avoids 
+       * infinite recursion
+       */
       do
 	{
 	  gtk_scrolled_window_relative_allocation (widget, &relative_allocation);



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