diff options
author | Benjamin Otte <otte.benjamin@googlemail.com> | 2021-11-09 03:15:00 +0000 |
---|---|---|
committer | Benjamin Otte <otte.benjamin@googlemail.com> | 2021-11-09 03:15:00 +0000 |
commit | 08d48201e998a06c07c5148b37bc374bbdcb9353 (patch) | |
tree | 9b4c9cac24d703c96d384c5ac6f9be33283ab828 | |
parent | 27d286eb7a6fda4da0ecb4e5de3c3307ae02d49b (diff) | |
parent | 76c46739447023368db4c3e6d008b52ff4b249e0 (diff) | |
download | gtk+-08d48201e998a06c07c5148b37bc374bbdcb9353.tar.gz |
Merge branch 'wip/otte/for-master' into 'master'
lots of sizing fixes
See merge request GNOME/gtk!4131
-rw-r--r-- | demos/widget-factory/widget-factory.ui | 2 | ||||
-rw-r--r-- | gtk/gtkboxlayout.c | 268 | ||||
-rw-r--r-- | gtk/gtklabel.c | 11 | ||||
-rw-r--r-- | gtk/gtksizerequest.c | 3 | ||||
-rw-r--r-- | testsuite/reftests/label-huge-max-width-chars.ref.ui | 11 | ||||
-rw-r--r-- | testsuite/reftests/label-huge-max-width-chars.ui | 12 | ||||
-rw-r--r-- | testsuite/reftests/label-small-max-width-chars.ref.ui | 11 | ||||
-rw-r--r-- | testsuite/reftests/label-small-max-width-chars.ui | 12 | ||||
-rw-r--r-- | testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui | 12 | ||||
-rw-r--r-- | testsuite/reftests/label-wrapped-huge-max-width-chars.ui | 13 | ||||
-rw-r--r-- | testsuite/reftests/meson.build | 8 | ||||
-rw-r--r-- | testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui | 27 | ||||
-rw-r--r-- | testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui | 30 |
13 files changed, 322 insertions, 98 deletions
diff --git a/demos/widget-factory/widget-factory.ui b/demos/widget-factory/widget-factory.ui index 7c190d08cb..e31629d986 100644 --- a/demos/widget-factory/widget-factory.ui +++ b/demos/widget-factory/widget-factory.ui @@ -2923,7 +2923,7 @@ microphone-sensitivity-medium-symbolic</property> <property name="resizable">0</property> <property name="modal">1</property> <property name="text" translatable="1">Do something?</property> - <property name="secondary-text" translatable="1">If you do something, + <property name="secondary-text" translatable="1">If you don't do something, bad things might happen.</property> <property name="hide-on-close">1</property> <child type="action"> diff --git a/gtk/gtkboxlayout.c b/gtk/gtkboxlayout.c index 20b462eb40..e79c5e202a 100644 --- a/gtk/gtkboxlayout.c +++ b/gtk/gtkboxlayout.c @@ -288,6 +288,64 @@ gtk_box_layout_compute_opposite_size (GtkBoxLayout *self, *natural = largest_nat; } +static int +distribute_remaining_size (GtkRequestedSize *sizes, + gsize n_sizes, + GtkOrientation orientation, + int available, + int min, + int max) +{ + int total_size = 0; + gsize i; + + if (n_sizes == 0) + return available; + + for (i = 0; i < n_sizes; i++) + { + gtk_widget_measure (sizes[i].data, + orientation, + min, + &sizes[i].minimum_size, &sizes[i].natural_size, + NULL, NULL); + total_size += sizes[i].minimum_size; + } + + if (total_size <= available) + return available - total_size; + + /* total_size > available happens when we last ran for values too big, + * rerun for the correct value min == max in that case */ + while (min < max || total_size > available) + { + int test; + + if (max == G_MAXINT) + test = min * 2; + else + test = (min + max) / 2; + + total_size = 0; + for (i = 0; i < n_sizes; i++) + { + gtk_widget_measure (sizes[i].data, + orientation, + test, + &sizes[i].minimum_size, &sizes[i].natural_size, + NULL, NULL); + total_size += sizes[i].minimum_size; + } + + if (total_size > available) + min = test + 1; + else + max = test; + } + + return available - total_size; +} + static void gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self, GtkWidget *widget, @@ -305,13 +363,12 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self, int computed_minimum_below = 0, computed_natural_below = 0; int computed_minimum_baseline = -1, computed_natural_baseline = -1; GtkRequestedSize *sizes; - int extra_space, size_given_to_child, i; - int children_minimum_size = 0; + int available, size_given_to_child, i; int child_size, child_minimum, child_natural; int child_minimum_baseline, child_natural_baseline; int n_extra_widgets = 0; int spacing; - gboolean have_baseline; + gboolean have_baseline = FALSE; count_expand_children (widget, self->orientation, &nvis_children, &nexpand_children); @@ -320,96 +377,132 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self, spacing = get_spacing (self, gtk_widget_get_css_node (widget)); sizes = g_newa (GtkRequestedSize, nvis_children); - extra_space = MAX (0, for_size - (nvis_children - 1) * spacing); + g_assert ((nvis_children - 1) * spacing <= for_size); + available = for_size - (nvis_children - 1) * spacing; - /* Retrieve desired size for visible children */ - for (i = 0, child = _gtk_widget_get_first_child (widget); - child != NULL; - child = _gtk_widget_get_next_sibling (child)) + if (self->homogeneous) { - int min_opposite, nat_for_min; - - if (!gtk_widget_should_layout (child)) - continue; + size_given_to_child = available / nvis_children; + n_extra_widgets = available % nvis_children; - gtk_widget_measure (child, - self->orientation, - -1, - &sizes[i].minimum_size, &sizes[i].natural_size, - NULL, NULL); - /* Don't just use the natural size as the max size, - * the natural size is the ideal size, not necessarily - * the maximum size. - * Also check the nat size for opposite min size. - */ - gtk_widget_measure (child, - OPPOSITE_ORIENTATION (self->orientation), - -1, - &min_opposite, NULL, - NULL, NULL); - gtk_widget_measure (child, - self->orientation, - min_opposite, - NULL, &nat_for_min, - NULL, NULL); - sizes[i].natural_size = MAX (sizes[i].natural_size, nat_for_min); + for (child = _gtk_widget_get_first_child (widget); + child != NULL; + child = _gtk_widget_get_next_sibling (child)) + { + if (!gtk_widget_should_layout (child)) + continue; - children_minimum_size += sizes[i].minimum_size; - i += 1; - } + child_size = size_given_to_child; + if (n_extra_widgets) + { + child_size++; + n_extra_widgets--; + } - if (self->homogeneous) - { - /* We still need to run the above loop to populate the minimum sizes for - * children that aren't going to fill. - */ + child_minimum_baseline = child_natural_baseline = -1; + /* Assign the child's position. */ + gtk_widget_measure (child, + OPPOSITE_ORIENTATION (self->orientation), + child_size, + &child_minimum, &child_natural, + &child_minimum_baseline, &child_natural_baseline); - size_given_to_child = extra_space / nvis_children; - n_extra_widgets = extra_space % nvis_children; + if (child_minimum_baseline >= 0) + { + have_baseline = TRUE; + computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline); + computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline); + computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline); + computed_natural_above = MAX (computed_natural_above, child_natural_baseline); + } + else + { + computed_minimum = MAX (computed_minimum, child_minimum); + computed_natural = MAX (computed_natural, child_natural); + } + } } else { + int min_size = 0, child_min_size; + int n_inconstant = 0; + + /* Retrieve desired size for visible children */ + for (i = 0, child = _gtk_widget_get_first_child (widget); + child != NULL; + child = _gtk_widget_get_next_sibling (child)) + { + if (!gtk_widget_should_layout (child)) + continue; + + if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_CONSTANT_SIZE) + { + gtk_widget_measure (child, + self->orientation, + -1, + &sizes[i].minimum_size, &sizes[i].natural_size, + NULL, NULL); + sizes[i].data = child; + g_assert (available >= sizes[i].minimum_size); + available -= sizes[i].minimum_size; + i++; + } + else + { + gtk_widget_measure (child, + OPPOSITE_ORIENTATION (self->orientation), + -1, + &child_min_size, NULL, + NULL, NULL); + min_size = MAX (min_size, child_min_size); + n_inconstant++; + sizes[nvis_children - n_inconstant].data = child; + } + } + + available = distribute_remaining_size (sizes + nvis_children - n_inconstant, + n_inconstant, + self->orientation, + available, + min_size, + G_MAXINT); + /* Bring children up to size first */ - extra_space -= children_minimum_size; - extra_space = MAX (0, extra_space); - extra_space = gtk_distribute_natural_allocation (extra_space, nvis_children, sizes); + available = gtk_distribute_natural_allocation (available, nvis_children, sizes); /* Calculate space which hasn't distributed yet, * and is available for expanding children. */ if (nexpand_children > 0) { - size_given_to_child = extra_space / nexpand_children; - n_extra_widgets = extra_space % nexpand_children; + size_given_to_child = available / nexpand_children; + n_extra_widgets = available % nexpand_children; } else { size_given_to_child = 0; } - } - - have_baseline = FALSE; - for (i = 0, child = _gtk_widget_get_first_child (widget); - child != NULL; - child = _gtk_widget_get_next_sibling (child)) - { - if (!gtk_widget_should_layout (child)) - continue; - /* Assign the child's size. */ - if (self->homogeneous) + i = 0; + n_inconstant = 0; + for (child = _gtk_widget_get_first_child (widget); + child != NULL; + child = _gtk_widget_get_next_sibling (child)) { - child_size = size_given_to_child; + if (!gtk_widget_should_layout (child)) + continue; - if (n_extra_widgets > 0) + if (sizes[i].data == child) { - child_size++; - n_extra_widgets--; + child_size = sizes[i].minimum_size; + i++; + } + else + { + n_inconstant++; + g_assert (sizes[nvis_children - n_inconstant].data == child); + child_size = sizes[nvis_children - n_inconstant].minimum_size; } - } - else - { - child_size = sizes[i].minimum_size; if (gtk_widget_compute_expand (child, self->orientation)) { @@ -421,30 +514,29 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self, n_extra_widgets--; } } - } - child_minimum_baseline = child_natural_baseline = -1; - /* Assign the child's position. */ - gtk_widget_measure (child, - OPPOSITE_ORIENTATION (self->orientation), - child_size, - &child_minimum, &child_natural, - &child_minimum_baseline, &child_natural_baseline); + child_minimum_baseline = child_natural_baseline = -1; + /* Assign the child's position. */ + gtk_widget_measure (child, + OPPOSITE_ORIENTATION (self->orientation), + child_size, + &child_minimum, &child_natural, + &child_minimum_baseline, &child_natural_baseline); - if (child_minimum_baseline >= 0) - { - have_baseline = TRUE; - computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline); - computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline); - computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline); - computed_natural_above = MAX (computed_natural_above, child_natural_baseline); - } - else - { - computed_minimum = MAX (computed_minimum, child_minimum); - computed_natural = MAX (computed_natural, child_natural); + if (child_minimum_baseline >= 0) + { + have_baseline = TRUE; + computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline); + computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline); + computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline); + computed_natural_above = MAX (computed_natural_above, child_natural_baseline); + } + else + { + computed_minimum = MAX (computed_minimum, child_minimum); + computed_natural = MAX (computed_natural, child_natural); + } } - i += 1; } if (have_baseline) diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 3c3be85406..a82ec7bb77 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -1077,14 +1077,15 @@ get_static_size (GtkLabel *self, int *minimum_baseline, int *natural_baseline) { + int minimum_default, natural_default; PangoLayout *layout; - layout = gtk_label_get_measuring_layout (self, NULL, -1); + get_default_widths (self, &minimum_default, &natural_default); + + layout = gtk_label_get_measuring_layout (self, NULL, self->ellipsize ? natural_default : -1); if (orientation == GTK_ORIENTATION_HORIZONTAL) { - int minimum_default, natural_default; - pango_layout_get_size (layout, natural, NULL); if (self->ellipsize) { @@ -1096,11 +1097,8 @@ get_static_size (GtkLabel *self, else *minimum = *natural; - get_default_widths (self, &minimum_default, &natural_default); if (minimum_default > *minimum) *minimum = minimum_default; - if (natural_default > -1) - *natural = natural_default; *natural = MAX (*minimum, *natural); } else @@ -1180,7 +1178,6 @@ get_width_for_height (GtkLabel *self, /* Natural width is natural width - or as wide as possible */ layout = gtk_label_get_measuring_layout (self, layout, natural_default); pango_layout_get_size (layout, natural_width, NULL); - *natural_width = MAX (*natural_width, natural_default); *natural_width = MAX (*natural_width, *minimum_width); } else diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c index 45770d5498..a0f066b997 100644 --- a/gtk/gtksizerequest.c +++ b/gtk/gtksizerequest.c @@ -139,7 +139,6 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget, int *minimum_baseline, int *natural_baseline) { - const gboolean baselines_requested = (minimum_baseline != NULL || natural_baseline != NULL); SizeRequestCache *cache; int min_size = 0; int nat_size = 0; @@ -361,7 +360,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget, nat_size = adjusted_natural; } - if (baselines_requested && (min_baseline != -1 || nat_baseline != -1)) + if (min_baseline != -1 || nat_baseline != -1) { if (orientation == GTK_ORIENTATION_HORIZONTAL) { diff --git a/testsuite/reftests/label-huge-max-width-chars.ref.ui b/testsuite/reftests/label-huge-max-width-chars.ref.ui new file mode 100644 index 0000000000..ec722f56ce --- /dev/null +++ b/testsuite/reftests/label-huge-max-width-chars.ref.ui @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class="GtkWindow" id="window1"> + <property name="decorated">0</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="label">Hello World</property> + </object> + </child> + </object> +</interface> diff --git a/testsuite/reftests/label-huge-max-width-chars.ui b/testsuite/reftests/label-huge-max-width-chars.ui new file mode 100644 index 0000000000..bf1237c1de --- /dev/null +++ b/testsuite/reftests/label-huge-max-width-chars.ui @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class="GtkWindow" id="window1"> + <property name="decorated">0</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="label">Hello World</property> + <property name="max-width-chars">1000</property> + </object> + </child> + </object> +</interface> diff --git a/testsuite/reftests/label-small-max-width-chars.ref.ui b/testsuite/reftests/label-small-max-width-chars.ref.ui new file mode 100644 index 0000000000..ec722f56ce --- /dev/null +++ b/testsuite/reftests/label-small-max-width-chars.ref.ui @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class="GtkWindow" id="window1"> + <property name="decorated">0</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="label">Hello World</property> + </object> + </child> + </object> +</interface> diff --git a/testsuite/reftests/label-small-max-width-chars.ui b/testsuite/reftests/label-small-max-width-chars.ui new file mode 100644 index 0000000000..d3236e8035 --- /dev/null +++ b/testsuite/reftests/label-small-max-width-chars.ui @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class="GtkWindow" id="window1"> + <property name="decorated">0</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="label">Hello World</property> + <property name="max-width-chars">2</property> + </object> + </child> + </object> +</interface> diff --git a/testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui b/testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui new file mode 100644 index 0000000000..5ec6dea124 --- /dev/null +++ b/testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class="GtkWindow" id="window1"> + <property name="decorated">0</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="label">Hello World</property> + <property name="wrap">1</property> + </object> + </child> + </object> +</interface> diff --git a/testsuite/reftests/label-wrapped-huge-max-width-chars.ui b/testsuite/reftests/label-wrapped-huge-max-width-chars.ui new file mode 100644 index 0000000000..cc21161d61 --- /dev/null +++ b/testsuite/reftests/label-wrapped-huge-max-width-chars.ui @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <object class="GtkWindow" id="window1"> + <property name="decorated">0</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="label">Hello World</property> + <property name="max-width-chars">1000</property> + <property name="wrap">1</property> + </object> + </child> + </object> +</interface> diff --git a/testsuite/reftests/meson.build b/testsuite/reftests/meson.build index 7917c1d388..83a06c9c80 100644 --- a/testsuite/reftests/meson.build +++ b/testsuite/reftests/meson.build @@ -347,6 +347,8 @@ testdata = [ 'label-fonts.css', 'label-fonts.ref.ui', 'label-fonts.ui', + 'label-huge-max-width-chars.ref.ui', + 'label-huge-max-width-chars.ui', 'label-max-width-chars-and-halign-and-infinite-width.ui', 'label-max-width-chars-and-halign-and-infinite-width.ref.ui', 'label-shadows.css', @@ -357,6 +359,8 @@ testdata = [ 'label-sizing.ui', 'label-small-ellipsized.ref.ui', 'label-small-ellipsized.ui', + 'label-small-max-width-chars.ref.ui', + 'label-small-max-width-chars.ui', 'label-text-shadow-clipping.css', 'label-text-shadow-clipping.ref.ui', 'label-text-shadow-clipping.ui', @@ -365,6 +369,8 @@ testdata = [ 'label-text-shadow-changes-modify-clip.ui', 'label-width-chars-dont-shrink.ref.ui', 'label-width-chars-dont-shrink.ui', + 'label-wrapped-huge-max-width-chars.ref.ui', + 'label-wrapped-huge-max-width-chars.ui', # this seems to make assumptions on text positioning # that are not valid with subpixel positioning #'label-wrap-justify.ref.ui', @@ -500,6 +506,8 @@ testdata = [ 'unresolvable.css', 'unresolvable.ref.ui', 'unresolvable.ui', + 'vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui', + 'vbox-with-2-wrapping-labels-where-one-should-wrap.ui', 'vbox-with-max-width-chars-label.ref.ui', 'vbox-with-max-width-chars-label.ui', 'window-border-width.ref.ui', diff --git a/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui new file mode 100644 index 0000000000..ec575c07d9 --- /dev/null +++ b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface domain="gtk40"> + <object class="GtkWindow"> + <property name="decorated">0</property> + <child> + <object class="GtkBox"> + <child> + <object class="GtkBox"> + <property name="orientation">1</property> + <child> + <object class="GtkLabel"> + <property name="label">Hello +World</property> + </object> + </child> + <child> + <object class="GtkLabel"> + <property name="label">Hi Ho</property> + </object> + </child> + </object> + </child> + </object> + </child> + </object> +</interface> + diff --git a/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui new file mode 100644 index 0000000000..f398308496 --- /dev/null +++ b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface domain="gtk40"> + <object class="GtkWindow"> + <property name="decorated">0</property> + <child> + <object class="GtkBox"> + <child> + <object class="GtkBox"> + <property name="orientation">1</property> + <child> + <object class="GtkLabel"> + <property name="label">Hello World</property> + <property name="wrap">1</property> + <property name="max-width-chars">1</property> + </object> + </child> + <child> + <object class="GtkLabel"> + <property name="label">Hi Ho</property> + <property name="wrap">1</property> + <property name="max-width-chars">1</property> + </object> + </child> + </object> + </child> + </object> + </child> + </object> +</interface> + |