From 6acc8c0817ecc68be491300d9db8605e3e6ae9be Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 7 Mar 2013 13:45:01 +0100 Subject: [PATCH] GtkAlignment: Support baselines We now report any baselines from the child, and allocate it. Also, in the case of a baselign aligned child we ignore yscale/yalign as that is not supportable. --- gtk/gtkalignment.c | 82 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/gtk/gtkalignment.c b/gtk/gtkalignment.c index ddd627ce86..f85c90dc32 100644 --- a/gtk/gtkalignment.c +++ b/gtk/gtkalignment.c @@ -108,6 +108,12 @@ static void gtk_alignment_get_preferred_height_for_width (GtkWidget *w gint for_size, gint *minimum_size, gint *natural_size); +static void gtk_alignment_get_preferred_height_and_baseline_for_width (GtkWidget *widget, + gint for_size, + gint *minimum_size, + gint *natural_size, + gint *minimum_baseline, + gint *natural_baseline); G_DEFINE_TYPE (GtkAlignment, gtk_alignment, GTK_TYPE_BIN) @@ -128,6 +134,7 @@ gtk_alignment_class_init (GtkAlignmentClass *class) widget_class->get_preferred_height = gtk_alignment_get_preferred_height; widget_class->get_preferred_width_for_height = gtk_alignment_get_preferred_width_for_height; widget_class->get_preferred_height_for_width = gtk_alignment_get_preferred_height_for_width; + widget_class->get_preferred_height_and_baseline_for_width = gtk_alignment_get_preferred_height_and_baseline_for_width; g_object_class_install_property (gobject_class, PROP_XALIGN, @@ -507,6 +514,7 @@ gtk_alignment_size_allocate (GtkWidget *widget, gint width, height; guint border_width; gint padding_horizontal, padding_vertical; + gint baseline; padding_horizontal = 0; padding_vertical = 0; @@ -520,6 +528,7 @@ gtk_alignment_size_allocate (GtkWidget *widget, gint child_nat_width; gint child_nat_height; gint child_width, child_height; + double yalign, yscale; border_width = gtk_container_get_border_width (GTK_CONTAINER (alignment)); @@ -529,6 +538,25 @@ gtk_alignment_size_allocate (GtkWidget *widget, width = MAX (1, allocation->width - padding_horizontal - 2 * border_width); height = MAX (1, allocation->height - padding_vertical - 2 * border_width); + baseline = gtk_widget_get_allocated_baseline (widget); + if (baseline != -1) + baseline -= border_width + priv->padding_top; + + /* If we get a baseline set that means we're baseline aligned, and the parent + honored that. In that case we have to ignore yalign/yscale as we need + yalign based on the baseline and always FILL mode to ensure we can place + the baseline anywhere */ + if (baseline != -1) + { + yalign = 0; + yscale = 1.0; + } + else + { + yalign = priv->yalign; + yscale = priv->yscale; + } + if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) { gtk_widget_get_preferred_width (child, NULL, &child_nat_width); @@ -559,8 +587,8 @@ gtk_alignment_size_allocate (GtkWidget *widget, if (height > child_height) child_allocation.height = (child_height * - (1.0 - priv->yscale) + - height * priv->yscale); + (1.0 - yscale) + + height * yscale); else child_allocation.height = height; @@ -569,9 +597,9 @@ gtk_alignment_size_allocate (GtkWidget *widget, else child_allocation.x = priv->xalign * (width - child_allocation.width) + allocation->x + border_width + priv->padding_left; - child_allocation.y = priv->yalign * (height - child_allocation.height) + allocation->y + border_width + priv->padding_top; + child_allocation.y = yalign * (height - child_allocation.height) + allocation->y + border_width + priv->padding_top; - gtk_widget_size_allocate (child, &child_allocation); + gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline); } } @@ -581,18 +609,30 @@ gtk_alignment_get_preferred_size (GtkWidget *widget, GtkOrientation orientation, gint for_size, gint *minimum_size, - gint *natural_size) + gint *natural_size, + gint *minimum_baseline, + gint *natural_baseline) { GtkAlignment *alignment = GTK_ALIGNMENT (widget); GtkAlignmentPrivate *priv = alignment->priv; GtkWidget *child; guint minimum, natural; + guint top_offset; + guint border; - natural = minimum = gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2; + if (minimum_baseline) + *minimum_baseline = -1; + if (natural_baseline) + *natural_baseline = -1; + + border = gtk_container_get_border_width (GTK_CONTAINER (widget)); + natural = minimum = border * 2; + top_offset = border; if ((child = gtk_bin_get_child (GTK_BIN (widget))) && gtk_widget_get_visible (child)) { gint child_min, child_nat; + gint child_min_baseline = -1, child_nat_baseline = -1; /* Request extra space for the padding: */ if (orientation == GTK_ORIENTATION_HORIZONTAL) @@ -619,9 +659,10 @@ gtk_alignment_get_preferred_size (GtkWidget *widget, else { minimum += (priv->padding_top + priv->padding_bottom); + top_offset += priv->padding_top; if (for_size < 0) - gtk_widget_get_preferred_height (child, &child_min, &child_nat); + gtk_widget_get_preferred_height_and_baseline_for_width (child, -1, &child_min, &child_nat, &child_min_baseline, &child_nat_baseline); else { gint min_width; @@ -634,8 +675,13 @@ gtk_alignment_get_preferred_size (GtkWidget *widget, for_size = (min_width * (1.0 - priv->xscale) + for_size * priv->xscale); - gtk_widget_get_preferred_height_for_width (child, for_size, &child_min, &child_nat); + gtk_widget_get_preferred_height_and_baseline_for_width (child, for_size, &child_min, &child_nat, &child_min_baseline, &child_nat_baseline); } + + if (minimum_baseline && child_min_baseline >= 0) + *minimum_baseline = child_min_baseline + top_offset; + if (natural_baseline && child_nat_baseline >= 0) + *natural_baseline = child_nat_baseline + top_offset; } natural = minimum; @@ -656,7 +702,7 @@ gtk_alignment_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size) { - gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum_size, natural_size); + gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum_size, natural_size, NULL, NULL); } static void @@ -664,7 +710,7 @@ gtk_alignment_get_preferred_height (GtkWidget *widget, gint *minimum_size, gint *natural_size) { - gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum_size, natural_size); + gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum_size, natural_size, NULL, NULL); } @@ -674,7 +720,7 @@ gtk_alignment_get_preferred_width_for_height (GtkWidget *widget, gint *minimum_size, gint *natural_size) { - gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, for_size, minimum_size, natural_size); + gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, for_size, minimum_size, natural_size, NULL, NULL); } static void @@ -683,9 +729,21 @@ gtk_alignment_get_preferred_height_for_width (GtkWidget *widget, gint *minimum_size, gint *natural_size) { - gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size); + gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size, NULL, NULL); } +static void +gtk_alignment_get_preferred_height_and_baseline_for_width (GtkWidget *widget, + gint for_size, + gint *minimum_size, + gint *natural_size, + gint *minimum_baseline, + gint *natural_baseline) +{ + gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size, minimum_baseline, natural_baseline); +} + + /** * gtk_alignment_set_padding: * @alignment: a #GtkAlignment