[gtk+/wip/baseline3: 14/17] GtkButtonBox: Support baseline alignment



commit 115155ff52fe847310b9a000a4799a72f190bfa5
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Mar 25 17:59:55 2013 +0100

    GtkButtonBox: Support baseline alignment

 gtk/gtkbbox.c |  184 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 161 insertions(+), 23 deletions(-)
---
diff --git a/gtk/gtkbbox.c b/gtk/gtkbbox.c
index 8385e2d..638959f 100644
--- a/gtk/gtkbbox.c
+++ b/gtk/gtkbbox.c
@@ -101,6 +101,12 @@ static void gtk_button_box_get_preferred_height_for_width (GtkWidget *widget,
                                                            gint       width,
                                                            gint      *minimum,
                                                            gint      *natural);
+static void gtk_button_box_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
+                                                                       gint       width,
+                                                                       gint      *minimum,
+                                                                       gint      *natural,
+                                                                       gint      *minimum_baseline,
+                                                                       gint      *natural_baseline);
 
 static void gtk_button_box_size_allocate      (GtkWidget         *widget,
                                                GtkAllocation     *allocation);
@@ -143,6 +149,7 @@ gtk_button_box_class_init (GtkButtonBoxClass *class)
   widget_class->get_preferred_height = gtk_button_box_get_preferred_height;
   widget_class->get_preferred_width_for_height = gtk_button_box_get_preferred_width_for_height;
   widget_class->get_preferred_height_for_width = gtk_button_box_get_preferred_height_for_width;
+  widget_class->get_preferred_height_and_baseline_for_width = 
gtk_button_box_get_preferred_height_and_baseline_for_width;
   widget_class->size_allocate = gtk_button_box_size_allocate;
 
   container_class->remove = gtk_button_box_remove;
@@ -438,7 +445,10 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
                                   gint       *nvis_children,
                                   gint       *nvis_secondaries,
                                   gint      **widths,
-                                  gint      **heights)
+                                  gint      **heights,
+                                  gint      **baselines,
+                                 gint       *baseline,
+                                 gint       *baseline_height)
 {
   GtkButtonBox *bbox;
   GList *children, *list;
@@ -446,6 +456,7 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
   gint nsecondaries;
   gint needed_width;
   gint needed_height;
+  gint needed_above, needed_below;
   gint avg_w, avg_h;
   GtkRequisition child_requisition;
   gint ipad_w;
@@ -456,11 +467,15 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
   gint ipad_y;
   gboolean homogeneous;
   gint i;
+  gint max_above, max_below, child_baseline;
+  GtkOrientation orientation;
+  gboolean have_baseline;
 
   g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
 
   bbox = GTK_BUTTON_BOX (widget);
 
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
   homogeneous = gtk_box_get_homogeneous (GTK_BOX (widget));
 
   gtk_widget_style_get (widget,
@@ -475,22 +490,33 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
   list = children = _gtk_box_get_children (GTK_BOX (bbox));
   needed_width = child_min_width;
   needed_height = child_min_height;
+  needed_above = 0;
+  needed_below = 0;
   ipad_w = ipad_x * 2;
   ipad_h = ipad_y * 2;
 
+  have_baseline = FALSE;
+  max_above = max_below = 0;
   avg_w = avg_h = 0;
-  while (children)
+  for (children = list; children != NULL; children = children->next)
     {
       GtkWidget *child;
 
       child = children->data;
-      children = children->next;
 
       if (gtk_widget_get_visible (child))
         {
           nchildren += 1;
-          gtk_widget_get_preferred_size (child,
-                                         &child_requisition, NULL);
+          gtk_widget_get_preferred_size_and_baseline (child,
+                                                     &child_requisition, NULL, &child_baseline, NULL);
+         if (orientation == GTK_ORIENTATION_HORIZONTAL &&
+             gtk_widget_get_valign_with_baseline (child) == GTK_ALIGN_BASELINE &&
+             child_baseline != -1)
+           {
+             have_baseline = TRUE;
+             max_above = MAX (max_above, child_baseline + ipad_y);
+             max_below = MAX (max_below , child_requisition.height + ipad_h - (child_baseline + ipad_y));
+           }
           avg_w += child_requisition.width + ipad_w;
           avg_h += child_requisition.height + ipad_h;
         }
@@ -498,8 +524,14 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
   avg_w /= MAX (nchildren, 1);
   avg_h /= MAX (nchildren, 1);
 
+  if (baseline)
+    *baseline = have_baseline ? max_above : -1;
+  if (baseline_height)
+    *baseline_height = max_above + max_below;
+
   *widths = g_new (gint, nchildren);
   *heights = g_new (gint, nchildren);
+  *baselines = g_new (gint, nchildren);
 
   i = 0;
   children = list;
@@ -520,7 +552,8 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
           if (is_secondary)
             nsecondaries++;
 
-          gtk_widget_get_preferred_size (child, &child_requisition, NULL);
+          gtk_widget_get_preferred_size_and_baseline (child,
+                                                     &child_requisition, NULL, &child_baseline, NULL);
 
           if (homogeneous ||
               (!non_homogeneous && (child_requisition.width + ipad_w < avg_w * 1.5)))
@@ -534,16 +567,38 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
               (*widths)[i] = child_requisition.width + ipad_w;
             }
 
+         (*baselines)[i] = -1;
+
           if (homogeneous ||
               (!non_homogeneous && (child_requisition.height + ipad_h < avg_h * 1.5)))
             {
               (*heights)[i] = -1;
-              if (child_requisition.height + ipad_h > needed_height)
-                needed_height = child_requisition.height + ipad_h;
+
+             if (orientation == GTK_ORIENTATION_HORIZONTAL &&
+                 gtk_widget_get_valign_with_baseline (child) == GTK_ALIGN_BASELINE &&
+                 child_baseline != -1)
+               {
+                 (*baselines)[i] = child_baseline + ipad_y;
+
+                 if (child_baseline + ipad_y > needed_above)
+                   needed_above = child_baseline + ipad_y;
+                 if (child_requisition.height - child_baseline + ipad_y > needed_below)
+                   needed_below = child_requisition.height - child_baseline + ipad_y;
+               }
+             else
+               {
+                 if (child_requisition.height + ipad_h > needed_height)
+                   needed_height = child_requisition.height + ipad_h;
+               }
             }
           else
             {
               (*heights)[i] = child_requisition.height + ipad_h;
+
+             if (orientation == GTK_ORIENTATION_HORIZONTAL &&
+                 gtk_widget_get_valign_with_baseline (child) == GTK_ALIGN_BASELINE &&
+                 child_baseline != -1)
+               (*baselines)[i] = child_baseline + ipad_y;
             }
 
           i++;
@@ -552,12 +607,18 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
 
   g_list_free (list);
 
+  needed_height = MAX (needed_height, needed_above + needed_below);
+
   for (i = 0; i < nchildren; i++)
     {
       if ((*widths)[i] == -1)
         (*widths)[i] = needed_width;
       if ((*heights)[i] == -1)
-        (*heights)[i] = needed_height;
+       {
+         (*heights)[i] = needed_height;
+         if ((*baselines)[i] != -1)
+           (*baselines)[i] = needed_above;
+       }
     }
 
   if (nvis_children)
@@ -569,19 +630,24 @@ gtk_button_box_child_requisition (GtkWidget  *widget,
 
 static void
 gtk_button_box_size_request (GtkWidget      *widget,
-                             GtkRequisition *requisition)
+                             GtkRequisition *requisition,
+                            gint           *baseline)
 {
   GtkButtonBoxPrivate *priv;
   GtkButtonBox *bbox;
   gint nvis_children;
-  gint max_size;
+  gint max_size, max_above, max_below;
   gint total_size;
   gint spacing;
   GtkOrientation orientation;
   gint *widths;
   gint *heights;
+  gint *baselines;
   gint i;
 
+  if (baseline)
+    *baseline = -1;
+
   bbox = GTK_BUTTON_BOX (widget);
   priv = bbox->priv;
 
@@ -591,16 +657,22 @@ gtk_button_box_size_request (GtkWidget      *widget,
   gtk_button_box_child_requisition (widget,
                                     &nvis_children,
                                     NULL,
-                                    &widths, &heights);
+                                    &widths, &heights, &baselines, baseline, NULL);
 
-  max_size = 0;
+  max_size = max_above = max_below = 0;
   total_size = 0;
   for (i = 0; i < nvis_children; i++)
     {
       if (orientation == GTK_ORIENTATION_HORIZONTAL)
         {
           total_size += widths[i];
-          max_size = MAX (max_size, heights[i]);
+         if (baselines[i] == -1)
+           max_size = MAX (max_size, heights[i]);
+         else
+           {
+             max_above = MAX (max_above, baselines[i]);
+             max_below = MAX (max_below, heights[i] - baselines[i]);
+           }
         }
       else
         {
@@ -610,6 +682,23 @@ gtk_button_box_size_request (GtkWidget      *widget,
     }
   g_free (widths);
   g_free (heights);
+  g_free (baselines);
+
+  max_size = MAX (max_size, max_above + max_below);
+
+  switch (gtk_box_get_baseline_position (GTK_BOX (widget)))
+    {
+    case GTK_BASELINE_POSITION_TOP:
+      break;
+    case GTK_BASELINE_POSITION_CENTER:
+      if (baseline != NULL && *baseline != -1)
+       *baseline += (max_size - (max_above + max_below)) / 2;
+      break;
+    case GTK_BASELINE_POSITION_BOTTOM:
+      if (baseline != NULL && *baseline != -1)
+       *baseline += max_size - (max_above + max_below);
+      break;
+    }
 
   if (nvis_children == 0)
     {
@@ -656,7 +745,7 @@ gtk_button_box_get_preferred_width (GtkWidget *widget,
 {
   GtkRequisition requisition;
 
-  gtk_button_box_size_request (widget, &requisition);
+  gtk_button_box_size_request (widget, &requisition, NULL);
 
   *minimum = *natural = requisition.width;
 }
@@ -666,11 +755,9 @@ gtk_button_box_get_preferred_height (GtkWidget *widget,
                                      gint      *minimum,
                                      gint      *natural)
 {
-  GtkRequisition requisition;
-
-  gtk_button_box_size_request (widget, &requisition);
-
-  *minimum = *natural = requisition.height;
+  gtk_button_box_get_preferred_height_and_baseline_for_width (widget, -1,
+                                                             minimum, natural,
+                                                             NULL, NULL);
 }
 
 static void
@@ -692,6 +779,26 @@ gtk_button_box_get_preferred_height_for_width (GtkWidget *widget,
 }
 
 static void
+gtk_button_box_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
+                                                           gint       width,
+                                                           gint      *minimum,
+                                                           gint      *natural,
+                                                           gint      *minimum_baseline,
+                                                           gint      *natural_baseline)
+{
+  GtkRequisition requisition;
+  gint baseline;
+
+  gtk_button_box_size_request (widget, &requisition, &baseline);
+
+  *minimum = *natural = requisition.height;
+  if (minimum_baseline)
+    *minimum_baseline = baseline;
+  if (natural_baseline)
+    *natural_baseline = baseline;
+}
+
+static void
 gtk_button_box_size_allocate (GtkWidget     *widget,
                               GtkAllocation *allocation)
 {
@@ -714,10 +821,13 @@ gtk_button_box_size_allocate (GtkWidget     *widget,
   gint ipad_x, ipad_y;
   gint *widths;
   gint *heights;
+  gint *baselines;
   gint *sizes;
   gint primary_size;
   gint secondary_size;
   gint total_size;
+  gint baseline, baseline_height;
+  gint child_baseline, allocated_baseline;
   gint i;
 
   bbox = GTK_BUTTON_BOX (widget);
@@ -733,7 +843,27 @@ gtk_button_box_size_allocate (GtkWidget     *widget,
   gtk_button_box_child_requisition (widget,
                                     &nvis_children,
                                     &n_secondaries,
-                                    &widths, &heights);
+                                    &widths, &heights, &baselines, &baseline, &baseline_height);
+
+  allocated_baseline = gtk_widget_get_allocated_baseline (widget);
+  if (allocated_baseline != -1)
+    baseline = allocated_baseline;
+  else if (baseline != -1)
+    {
+      /* TODO: modify baseline based on baseline_pos && allocated_baseline*/
+      switch (gtk_box_get_baseline_position (GTK_BOX (widget)))
+       {
+       case GTK_BASELINE_POSITION_TOP:
+         baseline = baseline;
+         break;
+       case GTK_BASELINE_POSITION_CENTER:
+         baseline = baseline + (allocation->height - baseline_height) / 2;
+         break;
+       case GTK_BASELINE_POSITION_BOTTOM:
+         baseline = allocation->height - (baseline_height - baseline);
+         break;
+       }
+    }
 
   n_primaries = nvis_children - n_secondaries;
   primary_size = 0;
@@ -917,10 +1047,17 @@ gtk_button_box_size_allocate (GtkWidget     *widget,
         {
           child_allocation.width = widths[i];
           child_allocation.height = heights[i];
+         child_baseline = -1;
 
           if (orientation == GTK_ORIENTATION_HORIZONTAL)
             {
-              child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+             if (baselines[i] != -1)
+               {
+                 child_allocation.y = allocation->y + baseline - baselines[i];
+                 child_baseline = baselines[i];
+               }
+             else
+               child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
 
               if (gtk_button_box_get_child_secondary (bbox, child))
                 {
@@ -953,7 +1090,7 @@ gtk_button_box_size_allocate (GtkWidget     *widget,
                 }
             }
 
-          gtk_widget_size_allocate (child, &child_allocation);
+          gtk_widget_size_allocate_with_baseline (child, &child_allocation, child_baseline);
           i++;
         }
     }
@@ -961,6 +1098,7 @@ gtk_button_box_size_allocate (GtkWidget     *widget,
   g_list_free (list);
   g_free (widths);
   g_free (heights);
+  g_free (baselines);
 }
 
 /**


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