[libadwaita/wip/exalm/fixes: 3/3] clamp-layout: Fix measure()
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/fixes: 3/3] clamp-layout: Fix measure()
- Date: Tue, 7 Dec 2021 21:12:09 +0000 (UTC)
commit 79af9a03df6a0d5a58c5fa6a506683a6fe7ae093
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Tue Dec 7 21:47:59 2021 +0500
clamp-layout: Fix measure()
So turns out after all the fixes this was still wrong:
- When get_child_size() gets for_size == -1, it returns the natural size
of the child. That's all good and well, but in reality we need the natural
size of the clamp itself - which would be larger because of the padding at
that size. So we need to calculate it - reverse the lerp and ease out cubic
we do on the clamp size to get the child size.
Refactor everything, extract inverse clamp function since we use it in two
places now.
Fixes https://gitlab.gnome.org/GNOME/libadwaita/-/issues/347
src/adw-clamp-layout.c | 102 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 66 insertions(+), 36 deletions(-)
---
diff --git a/src/adw-clamp-layout.c b/src/adw-clamp-layout.c
index 90621166..0907349f 100644
--- a/src/adw-clamp-layout.c
+++ b/src/adw-clamp-layout.c
@@ -9,6 +9,7 @@
#include <math.h>
+#include "adw-animation-util.h"
#include "adw-easing.h"
#include "adw-macros-private.h"
@@ -120,37 +121,62 @@ adw_clamp_layout_set_property (GObject *object,
}
}
+static inline double
+inverse_lerp (double a,
+ double b,
+ double t)
+{
+ return (t - a) / (b - a);
+}
+
static int
-get_child_size (AdwClampLayout *self,
- GtkWidget *child,
- int for_size,
- int *child_minimum,
- int *child_maximum,
- int *lower_threshold,
- int *upper_threshold)
+clamp_size_from_child (AdwClampLayout *self,
+ int min,
+ int nat)
{
- int min = 0, nat = 0, max = 0, lower = 0, upper = 0;
- double amplitude, progress;
+ int max = 0, lower = 0, upper = 0;
+ double progress;
+
+ lower = MAX (MIN (self->tightening_threshold, self->maximum_size), min);
+ max = MAX (lower, self->maximum_size);
+ upper = lower + ADW_EASE_OUT_TAN_CUBIC * (max - lower);
- if (gtk_widget_get_visible (child))
- gtk_widget_measure (child, self->orientation, -1, &min, &nat, NULL, NULL);
+ if (nat <= lower)
+ progress = 0;
+ else if (nat >= max)
+ progress = 1;
+ else {
+ double ease = inverse_lerp (lower, max, nat);
- if (for_size < 0)
- return nat;
+ progress = 1 + cbrt (ease - 1); // inverse ease out cubic
+ }
+
+ return ceil (adw_lerp (lower, upper, progress));
+}
+
+static int
+child_size_from_clamp (AdwClampLayout *self,
+ GtkWidget *child,
+ int for_size,
+ int *child_maximum,
+ int *lower_threshold)
+{
+ int min = 0, nat = 0, max = 0, lower = 0, upper = 0;
+ double progress;
+
+ gtk_widget_measure (child, self->orientation, -1, &min, &nat, NULL, NULL);
lower = MAX (MIN (self->tightening_threshold, self->maximum_size), min);
max = MAX (lower, self->maximum_size);
- amplitude = max - lower;
- upper = ADW_EASE_OUT_TAN_CUBIC * amplitude + lower;
+ upper = lower + ADW_EASE_OUT_TAN_CUBIC * (max - lower);
- if (child_minimum)
- *child_minimum = min;
if (child_maximum)
*child_maximum = max;
if (lower_threshold)
*lower_threshold = lower;
- if (upper_threshold)
- *upper_threshold = upper;
+
+ if (for_size < 0)
+ return MIN (nat, max);
if (for_size <= lower)
return for_size;
@@ -158,9 +184,9 @@ get_child_size (AdwClampLayout *self,
if (for_size >= upper)
return max;
- progress = (double) (for_size - lower) / (double) (upper - lower);
+ progress = inverse_lerp (lower, upper, for_size);
- return adw_easing_ease (ADW_EASE_OUT_CUBIC, progress) * amplitude + lower;
+ return adw_lerp (lower, max, adw_easing_ease (ADW_EASE_OUT_CUBIC, progress));
}
static GtkSizeRequestMode
@@ -190,7 +216,6 @@ adw_clamp_layout_measure (GtkLayoutManager *manager,
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child)) {
- int child_size = -1;
int child_min = 0;
int child_nat = 0;
int child_min_baseline = -1;
@@ -199,13 +224,19 @@ adw_clamp_layout_measure (GtkLayoutManager *manager,
if (!gtk_widget_should_layout (child))
continue;
- if (self->orientation != orientation)
- child_size = get_child_size (self, child, for_size,
- NULL, NULL, NULL, NULL);
+ if (self->orientation == orientation) {
+ gtk_widget_measure (child, orientation, -1,
+ &child_min, &child_nat,
+ &child_min_baseline, &child_nat_baseline);
- gtk_widget_measure (child, orientation, child_size,
- &child_min, &child_nat,
- &child_min_baseline, &child_nat_baseline);
+ child_nat = clamp_size_from_child (self, child_min, child_nat);
+ } else {
+ int child_size = child_size_from_clamp (self, child, for_size, NULL, NULL);
+
+ gtk_widget_measure (child, orientation, child_size,
+ &child_min, &child_nat,
+ &child_min_baseline, &child_nat_baseline);
+ }
*minimum = MAX (*minimum, child_min);
*natural = MAX (*natural, child_nat);
@@ -243,18 +274,17 @@ adw_clamp_layout_allocate (GtkLayoutManager *manager,
}
if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
- child_allocation.width = get_child_size (self, child, width,
- NULL, &child_maximum,
- &lower_threshold, NULL);
+ child_allocation.width = child_size_from_clamp (self, child, width,
+ &child_maximum,
+ &lower_threshold);
child_allocation.height = height;
child_clamped_size = child_allocation.width;
- }
- else {
+ } else {
child_allocation.width = width;
- child_allocation.height = get_child_size (self, child, height,
- NULL, &child_maximum,
- &lower_threshold, NULL);
+ child_allocation.height = child_size_from_clamp (self, child, height,
+ &child_maximum,
+ &lower_threshold);
child_clamped_size = child_allocation.height;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]