[gtk+/wip/baseline: 5/7] GtkAlignment: Support baselines



commit 169ba01c2ae29a91116ce68bac7196e58270f9f4
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Mar 7 13:45:01 2013 +0100

    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 files changed, 70 insertions(+), 12 deletions(-)
---
diff --git a/gtk/gtkalignment.c b/gtk/gtkalignment.c
index ddd627c..f85c90d 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


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