[gtk/revealer-support-min-size-master: 93/93] revealer: Support minimum size of child



commit 57ef793e6db5c4ad848d14815b1e74532cbb775e
Author: Carlos Soriano <csoriano redhat com>
Date:   Tue Sep 18 10:55:02 2018 +0200

    revealer: Support minimum size of child
    
    Up until now when allocating the child it only used the natural size
    while the measuring also used the minimum size, resulting in a clipped
    child when animating if the child had different minimum size and
    natural size. This was an obvious case when using labels that had
    ellipsization.
    
    This commit gives full allocation to the child by inverting the size
    the revealer reduces from its animation progress.
    
    Code done by Benjamin Otte.
    
    Closes: https://gitlab.gnome.org/GNOME/gtk/issues/635

 gtk/gtkrevealer.c | 169 ++++++++++++++++++++++--------------------------------
 1 file changed, 70 insertions(+), 99 deletions(-)
---
diff --git a/gtk/gtkrevealer.c b/gtk/gtkrevealer.c
index 13c37b9a80..b0dfc0c691 100644
--- a/gtk/gtkrevealer.c
+++ b/gtk/gtkrevealer.c
@@ -294,72 +294,46 @@ effective_transition (GtkRevealer *revealer)
 }
 
 static void
-gtk_revealer_get_child_allocation (GtkRevealer         *revealer,
-                                   const GtkAllocation *allocation,
-                                   GtkAllocation       *child_allocation)
+gtk_revealer_real_add (GtkContainer *container,
+                       GtkWidget    *child)
 {
+  GtkRevealer *revealer = GTK_REVEALER (container);
   GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
-  GtkWidget *child;
-  GtkRevealerTransitionType transition;
-
-  g_return_if_fail (revealer != NULL);
-  g_return_if_fail (allocation != NULL);
-
-  child_allocation->x = 0;
-  child_allocation->y = 0;
-  child_allocation->width = 0;
-  child_allocation->height = 0;
-
-  child = gtk_bin_get_child (GTK_BIN (revealer));
-  if (child != NULL && gtk_widget_get_visible (child))
-    {
-      transition = effective_transition (revealer);
 
-      if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT ||
-          transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
-        gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL,
-                            MAX (0, allocation->height),
-                            NULL, &child_allocation->width, NULL, NULL);
-      else
-        gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL,
-                            MAX (0, allocation->width),
-                            NULL, &child_allocation->height, NULL, NULL);
-
-      child_allocation->width = MAX (child_allocation->width, allocation->width);
-      child_allocation->height = MAX (child_allocation->height, allocation->height);
+  g_return_if_fail (child != NULL);
 
-      switch (transition)
-        {
-        case GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT:
-            child_allocation->x = - child_allocation->width * (1 - priv->current_pos);
-          break;
-        case GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN:
-            child_allocation->y = - child_allocation->height * (1 - priv->current_pos);
-          break;
-
-        case GTK_REVEALER_TRANSITION_TYPE_NONE:
-        case GTK_REVEALER_TRANSITION_TYPE_CROSSFADE:
-        case GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT:
-        case GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP:
-        default:
-          break;
-        }
-    }
+  gtk_widget_set_child_visible (child, priv->current_pos != 0.0);
 
+  GTK_CONTAINER_CLASS (gtk_revealer_parent_class)->add (container, child);
 }
 
-static void
-gtk_revealer_real_add (GtkContainer *container,
-                       GtkWidget    *child)
+static double
+get_child_size_scale (GtkRevealer    *revealer,
+                      GtkOrientation  orientation)
 {
-  GtkRevealer *revealer = GTK_REVEALER (container);
   GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
 
-  g_return_if_fail (child != NULL);
+  switch (effective_transition (revealer))
+    {
+    case GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT:
+    case GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT:
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        return priv->current_pos;
+      else
+        return 1.0;
 
-  gtk_widget_set_child_visible (child, priv->current_pos != 0.0);
+    case GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN:
+    case GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP:
+      if (orientation == GTK_ORIENTATION_VERTICAL)
+        return priv->current_pos;
+      else
+        return 1.0;
 
-  GTK_CONTAINER_CLASS (gtk_revealer_parent_class)->add (container, child);
+    case GTK_REVEALER_TRANSITION_TYPE_NONE:
+    case GTK_REVEALER_TRANSITION_TYPE_CROSSFADE:
+    default:
+      return 1.0;
+    }
 }
 
 static void
@@ -374,8 +348,32 @@ gtk_revealer_real_size_allocate (GtkWidget           *widget,
   if (child != NULL && gtk_widget_get_visible (child))
     {
       GtkAllocation child_allocation;
+      double hscale, vscale;
 
-      gtk_revealer_get_child_allocation (revealer, allocation, &child_allocation);
+      child_allocation = *allocation;
+
+      hscale = get_child_size_scale (revealer, GTK_ORIENTATION_HORIZONTAL);
+      vscale = get_child_size_scale (revealer, GTK_ORIENTATION_VERTICAL);
+
+      if (hscale <= 0 || vscale <= 0)
+        {
+          /* don't allocate anything, the child is invisible and the numbers
+           * don't make sense. */
+          return;
+        }
+      else if (hscale < 1.0)
+        {
+          g_assert (vscale == 1.0);
+          child_allocation.width = MIN (G_MAXINT, ceil (child_allocation.width / hscale));
+          if (effective_transition (revealer) == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
+            child_allocation.x = allocation->width - child_allocation.width;
+        }
+      else if (vscale < 1.0)
+        {
+          child_allocation.height = MIN (G_MAXINT, ceil (child_allocation.height / vscale));
+          if (effective_transition (revealer) == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
+            child_allocation.y = allocation->height - child_allocation.height;
+        }
       gtk_widget_size_allocate (child, &child_allocation, -1);
     }
 }
@@ -552,46 +550,6 @@ gtk_revealer_get_child_revealed (GtkRevealer *revealer)
     return !reveal_child;
 }
 
-/* These all report only the natural size, ignoring the minimal size,
- * because its not really possible to allocate the right size during
- * animation if the child size can change (without the child
- * re-arranging itself during the animation).
- */
-
-static void
-set_height (GtkRevealer *revealer,
-            gint        *minimum_height,
-            gint        *natural_height)
-{
-  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
-  GtkRevealerTransitionType transition;
-
-  transition = effective_transition (revealer);
-  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP ||
-      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN)
-    {
-      *minimum_height = round (*minimum_height * priv->current_pos);
-      *natural_height = round (*natural_height * priv->current_pos);
-    }
-}
-
-static void
-set_width (GtkRevealer *revealer,
-           gint        *minimum_width,
-           gint        *natural_width)
-{
-  GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
-  GtkRevealerTransitionType transition;
-
-  transition = effective_transition (revealer);
-  if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT ||
-      transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT)
-    {
-      *minimum_width = round (*minimum_width * priv->current_pos);
-      *natural_width = round (*natural_width * priv->current_pos);
-    }
-}
-
 static void
 gtk_revealer_measure (GtkWidget      *widget,
                       GtkOrientation  orientation,
@@ -601,15 +559,28 @@ gtk_revealer_measure (GtkWidget      *widget,
                       int            *minimum_baseline,
                       int            *natural_baseline)
 {
+  GtkRevealer *self = GTK_REVEALER (widget);
+  double scale;
+
+  scale = get_child_size_scale (self, OPPOSITE_ORIENTATION (orientation));
+
+  if (for_size >= 0)
+    {
+      if (scale == 0)
+        return;
+      else
+        for_size = MIN (G_MAXINT, ceil (for_size / scale));
+    }
+
   GTK_WIDGET_CLASS (gtk_revealer_parent_class)->measure (widget,
                                                          orientation,
                                                          for_size,
                                                          minimum, natural,
                                                          NULL, NULL);
-  if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    set_width (GTK_REVEALER (widget), minimum, natural);
-  else
-    set_height (GTK_REVEALER (widget), minimum, natural);
+
+  scale = get_child_size_scale (self, orientation);
+  *minimum = ceil (*minimum * scale);
+  *natural = ceil (*natural * scale);
 }
 
 static void


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