From c4a990809fdb0755be8945c2a5d7db2b07079e8c Mon Sep 17 00:00:00 2001 From: Adrien Plazas Date: Fri, 22 Feb 2019 17:07:12 +0100 Subject: [PATCH 1/2] column: Rework width measurements Move basic width measurements from get_child_width() into measure(), which will allow to compute the natural width the column should request. This also fixes the minimum size request of the column by ensuring it doesn't allocate less width than its child requires. --- src/hdy-column.c | 88 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 22 deletions(-) diff --git a/src/hdy-column.c b/src/hdy-column.c index 67c69b25..c9bccd07 100644 --- a/src/hdy-column.c +++ b/src/hdy-column.c @@ -91,39 +91,83 @@ hdy_column_set_property (GObject *object, } } -static gint -get_child_width (HdyColumn *self, - gint width) +static void +measure_thresholds (HdyColumn *self, + gint child_minimum, + gint child_natural, + gint *child_maximum, + gint *linear_threshold, + gint *maximum_threshold) +{ + /* Sanitize the linear threshold width to use for computations. */ + *linear_threshold = MAX (MAX (child_minimum, child_natural), MIN (self->linear_growth_width, self->maximum_width)); + /* Sanitize the maximum width to use for computations. */ + *child_maximum = MAX (*linear_threshold, self->maximum_width); + *maximum_threshold = HDY_EASE_OUT_TAN_CUBIC * (*child_maximum - *linear_threshold) + *linear_threshold; +} + +/* Measure various sizes to use for size computations. */ +static void +measure (HdyColumn *self, + gint *minimum, + gint *natural, + gint *child_maximum, + gint *linear_threshold, + gint *maximum_threshold) { - GtkBin *bin = GTK_BIN (self); GtkWidget *child; - gint minimum_width = 0, maximum_width; - gdouble amplitude, threshold, progress; + gint child_minimum = 0, child_natural = 0; + gint _child_maximum; + gint _linear_threshold; // If the column width is ≤ this threshold, the child should have the same width as the column. + gint _maximum_threshold; // If the column width is ≥ this threshold, the child should be allocated its maximum width. - child = gtk_bin_get_child (bin); - if (child == NULL) - return 0; + child = gtk_bin_get_child (GTK_BIN (self)); + g_assert (child != NULL); if (gtk_widget_get_visible (child)) - gtk_widget_get_preferred_width (child, &minimum_width, NULL); + gtk_widget_get_preferred_width (child, &child_minimum, &child_natural); + + if (minimum) + *minimum = child_minimum; - /* Sanitize the minimum width to use for computations. */ - minimum_width = MIN (MAX (minimum_width, self->linear_growth_width), self->maximum_width); + if (natural) { + /* First, measure including the natural width to measure the column's natural width. */ + measure_thresholds (self, child_minimum, child_natural, &_child_maximum, &_linear_threshold, &_maximum_threshold); + *natural = _maximum_threshold; + } - if (width <= minimum_width) - return width; + /* Then, measure without the natural width to measure the sizes to actually use. */ + measure_thresholds (self, child_minimum, 0, &_child_maximum, &_linear_threshold, &_maximum_threshold); - /* Sanitize the maximum width to use for computations. */ - maximum_width = MAX (minimum_width, self->maximum_width); - amplitude = maximum_width - minimum_width; - threshold = (HDY_EASE_OUT_TAN_CUBIC * amplitude + (gdouble) minimum_width); + if (linear_threshold) + *linear_threshold = _linear_threshold; + if (child_maximum) + *child_maximum = _child_maximum; + if (maximum_threshold) + *maximum_threshold = _maximum_threshold; +} + +static gint +get_child_width (HdyColumn *self, + gint for_width) +{ + gint child_maximum, linear_threshold, maximum_threshold; + gdouble progress; + + if (gtk_bin_get_child (GTK_BIN (self)) == NULL) + return 0; + + measure (self, NULL, NULL, &child_maximum, &linear_threshold, &maximum_threshold); + + if (for_width <= linear_threshold) + return for_width; - if (width >= threshold) - return maximum_width; + if (for_width >= maximum_threshold) + return child_maximum; - progress = (width - minimum_width) / (threshold - minimum_width); + progress = (gdouble) (for_width - linear_threshold) / (gdouble) (maximum_threshold - linear_threshold); - return ease_out_cubic (progress) * amplitude + minimum_width; + return ease_out_cubic (progress) * (child_maximum - linear_threshold) + linear_threshold; } /* This private method is prefixed by the call name because it will be a virtual -- GitLab From cc63614eba4080ead60325167c6f6cd6022867dd Mon Sep 17 00:00:00 2001 From: Adrien Plazas Date: Fri, 22 Feb 2019 17:13:54 +0100 Subject: [PATCH 2/2] column: Fix the natural width Set the natural width of the column from the child's one to what is needed for the child to reach the maximum allocatable width. This not only makes more sense but it will allow HdyColumn to serve as a container setting a natural size to its child by giving the same value to the maximum width and the linear growth width. https://source.puri.sm/Librem5/libhandy/issues/87 --- src/hdy-column.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hdy-column.c b/src/hdy-column.c index c9bccd07..e3bc564d 100644 --- a/src/hdy-column.c +++ b/src/hdy-column.c @@ -199,7 +199,7 @@ hdy_column_measure (GtkWidget *widget, return; if (orientation == GTK_ORIENTATION_HORIZONTAL) - gtk_widget_get_preferred_width (child, minimum, natural); + measure (HDY_COLUMN (widget), minimum, natural, NULL, NULL, NULL); else { gint child_width = get_child_width (HDY_COLUMN (widget), for_size); -- GitLab