[gtk+/wip/baseline3: 13/17] GtkCheckButton and GtkRadioButton: Implement baseline alignment



commit b8f1f78e4a909e06391f9696b322b49e76a8a32c
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Mar 22 12:01:26 2013 +0100

    GtkCheckButton and GtkRadioButton: Implement baseline alignment

 gtk/gtkbuttonprivate.h |    3 ++
 gtk/gtkcheckbutton.c   |   76 +++++++++++++++++++++++++++++++++++++++++++----
 gtk/gtkradiobutton.c   |    8 ++++-
 3 files changed, 79 insertions(+), 8 deletions(-)
---
diff --git a/gtk/gtkbuttonprivate.h b/gtk/gtkbuttonprivate.h
index ea44b71..54483de 100644
--- a/gtk/gtkbuttonprivate.h
+++ b/gtk/gtkbuttonprivate.h
@@ -39,6 +39,9 @@ struct _GtkButtonPrivate
   gfloat                 xalign;
   gfloat                 yalign;
 
+  /* This is only used by checkbox and subclasses */
+  gfloat                 baseline_align;
+
   guint                  activate_timeout;
   guint32                grab_time;
 
diff --git a/gtk/gtkcheckbutton.c b/gtk/gtkcheckbutton.c
index d7df5a9..48f9a96 100644
--- a/gtk/gtkcheckbutton.c
+++ b/gtk/gtkcheckbutton.c
@@ -58,6 +58,12 @@ static void gtk_check_button_get_preferred_width  (GtkWidget          *widget,
 static void gtk_check_button_get_preferred_height (GtkWidget          *widget,
                                                    gint               *minimum,
                                                    gint               *natural);
+static void gtk_check_button_get_preferred_height_and_baseline_for_width (GtkWidget          *widget,
+                                                                         gint                width,
+                                                                         gint               *minimum,
+                                                                         gint               *natural,
+                                                                         gint               
*minimum_baseline,
+                                                                         gint               
*natural_baseline);
 static void gtk_check_button_size_allocate       (GtkWidget           *widget,
                                                  GtkAllocation       *allocation);
 static gboolean gtk_check_button_draw            (GtkWidget           *widget,
@@ -80,6 +86,7 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
 
   widget_class->get_preferred_width = gtk_check_button_get_preferred_width;
   widget_class->get_preferred_height = gtk_check_button_get_preferred_height;
+  widget_class->get_preferred_height_and_baseline_for_width = 
gtk_check_button_get_preferred_height_and_baseline_for_width;
   widget_class->size_allocate = gtk_check_button_size_allocate;
   widget_class->draw = gtk_check_button_draw;
 
@@ -287,9 +294,12 @@ gtk_check_button_get_preferred_width (GtkWidget *widget,
 }
 
 static void
-gtk_check_button_get_preferred_height (GtkWidget *widget,
-                                       gint      *minimum,
-                                       gint      *natural)
+gtk_check_button_get_preferred_height_and_baseline_for_width (GtkWidget          *widget,
+                                                             gint                width,
+                                                             gint               *minimum,
+                                                             gint               *natural,
+                                                             gint               *minimum_baseline,
+                                                             gint               *natural_baseline)
 {
   GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (widget);
 
@@ -301,6 +311,7 @@ gtk_check_button_get_preferred_height (GtkWidget *widget,
       gint indicator_spacing;
       gint focus_width;
       gint focus_pad;
+      gint old_minimum, old_natural;
       guint border_width;
 
       border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
@@ -320,29 +331,61 @@ gtk_check_button_get_preferred_height (GtkWidget *widget,
       if (child && gtk_widget_get_visible (child))
         {
           gint child_min, child_nat;
+         gint child_min_baseline = -1, child_nat_baseline = -1;
 
-          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);
+
+         if (minimum_baseline && child_min_baseline >= 0)
+           *minimum_baseline = child_min_baseline + border_width;
+         if (natural_baseline && child_nat_baseline >= 0)
+           *natural_baseline = child_nat_baseline + border_width;
 
           *minimum += child_min;
           *natural += child_nat;
+
         }
 
+      old_minimum = *minimum;
+      old_natural = *natural;
+
       temp = indicator_size + indicator_spacing * 2;
       *minimum = MAX (*minimum, temp) + 2 * (focus_width + focus_pad);
       *natural = MAX (*natural, temp) + 2 * (focus_width + focus_pad);
+
+      if (minimum_baseline && *minimum_baseline != -1)
+       minimum_baseline += (*minimum - old_minimum) / 2;
+      if (natural_baseline && *natural_baseline != -1)
+       natural_baseline += (*natural - old_natural) / 2;
     }
   else
-    GTK_WIDGET_CLASS (gtk_check_button_parent_class)->get_preferred_height (widget, minimum, natural);
+    GTK_WIDGET_CLASS (gtk_check_button_parent_class)->get_preferred_height_and_baseline_for_width (widget, 
width,
+                                                                                                  minimum, 
natural,
+                                                                                                  
minimum_baseline, natural_baseline);
+}
+
+static void
+gtk_check_button_get_preferred_height (GtkWidget *widget,
+                                       gint      *minimum,
+                                       gint      *natural)
+{
+  gtk_check_button_get_preferred_height_and_baseline_for_width (widget, -1,
+                                                               minimum, natural,
+                                                               NULL, NULL);
 }
 
 static void
 gtk_check_button_size_allocate (GtkWidget     *widget,
                                GtkAllocation *allocation)
 {
+  PangoContext *pango_context;
+  PangoFontMetrics *metrics;
   GtkCheckButton *check_button;
   GtkToggleButton *toggle_button;
   GtkButton *button;
   GtkAllocation child_allocation;
+  gint baseline;
 
   button = GTK_BUTTON (widget);
   check_button = GTK_CHECK_BUTTON (widget);
@@ -389,8 +432,21 @@ gtk_check_button_size_allocate (GtkWidget     *widget,
            child_allocation.x = allocation->x + allocation->width
              - (child_allocation.x - allocation->x + child_allocation.width);
          
-         gtk_widget_size_allocate (child, &child_allocation);
+         baseline = gtk_widget_get_allocated_baseline (widget);
+         if (baseline != -1)
+           baseline -= child_allocation.y - allocation->y;
+         gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline);
        }
+
+      pango_context = gtk_widget_get_pango_context (widget);
+      metrics = pango_context_get_metrics (pango_context,
+                                          pango_context_get_font_description (pango_context),
+                                          pango_context_get_language (pango_context));
+      button->priv->baseline_align =
+       (double)pango_font_metrics_get_ascent (metrics) /
+       (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics));
+      pango_font_metrics_unref (metrics);
+
     }
   else
     GTK_WIDGET_CLASS (gtk_check_button_parent_class)->size_allocate (widget, allocation);
@@ -448,6 +504,7 @@ gtk_real_check_button_draw_indicator (GtkCheckButton *check_button,
   gint indicator_spacing;
   gint focus_width;
   gint focus_pad;
+  gint baseline;
   guint border_width;
   gboolean interior_focus;
   GtkAllocation allocation;
@@ -458,6 +515,7 @@ gtk_real_check_button_draw_indicator (GtkCheckButton *check_button,
   toggle_button = GTK_TOGGLE_BUTTON (check_button);
 
   gtk_widget_get_allocation (widget, &allocation);
+  baseline = gtk_widget_get_allocated_baseline (widget);
   context = gtk_widget_get_style_context (widget);
   state = gtk_widget_get_state_flags (widget);
 
@@ -472,7 +530,11 @@ gtk_real_check_button_draw_indicator (GtkCheckButton *check_button,
   border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
 
   x = indicator_spacing + border_width;
-  y = (allocation.height - indicator_size) / 2;
+  if (baseline == -1)
+    y = (allocation.height - indicator_size) / 2;
+  else
+    y = CLAMP (baseline - indicator_size * button->priv->baseline_align,
+              0, allocation.height - indicator_size);
 
   child = gtk_bin_get_child (GTK_BIN (check_button));
   if (!interior_focus || !(child && gtk_widget_get_visible (child)))
diff --git a/gtk/gtkradiobutton.c b/gtk/gtkradiobutton.c
index 82ab28c..56bb999 100644
--- a/gtk/gtkradiobutton.c
+++ b/gtk/gtkradiobutton.c
@@ -903,6 +903,7 @@ gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
   gint indicator_size, indicator_spacing;
   gint focus_width;
   gint focus_pad;
+  gint baseline;
   guint border_width;
   gboolean interior_focus;
 
@@ -923,9 +924,14 @@ gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
   _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing);
 
   gtk_widget_get_allocation (widget, &allocation);
+  baseline = gtk_widget_get_allocated_baseline (widget);
 
   x = indicator_spacing + border_width;
-  y = (allocation.height - indicator_size) / 2;
+  if (baseline == -1)
+    y = (allocation.height - indicator_size) / 2;
+  else
+    y = CLAMP (baseline - indicator_size * button->priv->baseline_align,
+              0, allocation.height - indicator_size);
 
   child = gtk_bin_get_child (GTK_BIN (check_button));
   if (!interior_focus || !(child && gtk_widget_get_visible (child)))


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