[gtk+] center box: implement natural size and rtl flipping



commit b4cb05ace9a0d9544c9666a665cba06a8be3b36f
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jun 3 15:56:01 2017 -0400

    center box: implement natural size and rtl flipping
    
    We prefer to give the center widget its natural size,
    and we center it as long as possible.

 gtk/gtkcenterbox.c |  218 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 130 insertions(+), 88 deletions(-)
---
diff --git a/gtk/gtkcenterbox.c b/gtk/gtkcenterbox.c
index abc3722..91a7a04 100644
--- a/gtk/gtkcenterbox.c
+++ b/gtk/gtkcenterbox.c
@@ -76,68 +76,44 @@ gtk_center_box_measure (GtkWidget      *widget,
                         int            *natural_baseline)
 {
   GtkCenterBox *self = GTK_CENTER_BOX (widget);
-  int min, nat, min_baseline, nat_baseline;
-
-  *minimum = *natural = 0;
+  int min_baseline, nat_baseline;
+  int start_min = 0;
+  int start_nat = 0;
+  int center_min = 0;
+  int center_nat = 0;
+  int end_min = 0;
+  int end_nat = 0;
 
   if (self->start_widget)
-    {
-      gtk_widget_measure (self->start_widget,
-                          orientation,
-                          for_size,
-                          &min, &nat,
-                          &min_baseline, &nat_baseline);
-
-      if (orientation == GTK_ORIENTATION_HORIZONTAL)
-        {
-          *minimum = *minimum + min;
-          *natural = *natural + nat;
-        }
-      else /* GTK_ORIENTATION_VERTICAL */
-        {
-          *minimum = MAX (*minimum, min);
-          *natural = MAX (*minimum, nat);
-        }
-    }
+    gtk_widget_measure (self->start_widget,
+                        orientation,
+                        for_size,
+                        &start_min, &start_nat,
+                        &min_baseline, &nat_baseline);
 
   if (self->center_widget)
-    {
-      gtk_widget_measure (self->center_widget,
-                          orientation,
-                          for_size,
-                          &min, &nat,
-                          &min_baseline, &nat_baseline);
-
-      if (orientation == GTK_ORIENTATION_HORIZONTAL)
-        {
-          *minimum = *minimum + min;
-          *natural = *natural + nat;
-        }
-      else /* GTK_ORIENTATION_VERTICAL */
-        {
-          *minimum = MAX (*minimum, min);
-          *natural = MAX (*minimum, nat);
-        }
-    }
+    gtk_widget_measure (self->center_widget,
+                        orientation,
+                        for_size,
+                        &center_min, &center_nat,
+                        &min_baseline, &nat_baseline);
 
   if (self->end_widget)
+    gtk_widget_measure (self->end_widget,
+                        orientation,
+                        for_size,
+                        &end_min, &end_nat,
+                        &min_baseline, &nat_baseline);
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      *minimum = start_min + center_min + end_min;
+      *natural = center_nat + 2 * MAX (start_nat, end_nat);
+    }
+  else /* GTK_ORIENTATION_VERTICAL */
     {
-      gtk_widget_measure (self->end_widget,
-                          orientation,
-                          for_size,
-                          &min, &nat,
-                          &min_baseline, &nat_baseline);
-
-      if (orientation == GTK_ORIENTATION_HORIZONTAL)
-        {
-          *minimum = *minimum + min;
-          *natural = *natural + nat;
-        }
-      else /* GTK_ORIENTATION_VERTICAL */
-        {
-          *minimum = MAX (*minimum, min);
-          *natural = MAX (*minimum, nat);
-        }
+      *minimum = MAX (start_min, MAX (center_min, end_min));
+      *natural = MAX (start_nat, MAX (center_nat, end_nat));
     }
 }
 
@@ -149,62 +125,88 @@ gtk_center_box_size_allocate (GtkWidget     *widget,
   GtkAllocation child_allocation;
   GtkAllocation clip = *allocation;
   GtkAllocation child_clip;
-  int start_size = 0;
-  int end_size = 0;
-  int min, nat;
+  GtkWidget *left;
+  GtkWidget *right;
+  int left_size = 0;
+  int left_min = 0;
+  int left_nat = 0;
+  int center_size = 0;
+  int center_min = 0;
+  int center_nat = 0;
+  int right_size = 0;
+  int right_min = 0;
+  int right_nat = 0;
+  int avail;
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+    {
+      left = self->start_widget;
+      right = self->end_widget;
+    }
+  else
+    {
+      right = self->start_widget;
+      left = self->end_widget;
+    }
 
   GTK_WIDGET_CLASS (gtk_center_box_parent_class)->size_allocate (widget, allocation);
 
-  /* TODO: Allocate natural sizes if possible? */
+  if (left)
+    gtk_widget_measure (left, GTK_ORIENTATION_HORIZONTAL,
+                        allocation->height,
+                        &left_min, &left_nat, NULL, NULL);
+
+  if (right)
+    gtk_widget_measure (right, GTK_ORIENTATION_HORIZONTAL,
+                        allocation->height,
+                        &right_min, &right_nat, NULL, NULL);
+
+  if (self->center_widget)
+    gtk_widget_measure (self->center_widget, GTK_ORIENTATION_HORIZONTAL,
+                        allocation->height,
+                        &center_min, &center_nat, NULL, NULL);
 
   child_allocation.y = allocation->y;
   child_allocation.height = allocation->height;
 
-  if (self->start_widget)
+  center_size = CLAMP (allocation->width - (left_min + right_min), center_min, center_nat);
+
+  if (left)
     {
-      gtk_widget_measure (self->start_widget, GTK_ORIENTATION_HORIZONTAL,
-                          allocation->height,
-                          &min, &nat, NULL, NULL);
+      avail = MIN ((allocation->width - center_size) / 2, allocation->width - (center_size + right_min));
+      child_allocation.width = CLAMP (avail, left_min, left_nat);
       child_allocation.x = allocation->x;
-      child_allocation.width = min;
 
-      gtk_widget_size_allocate (self->start_widget, &child_allocation);
-      gtk_widget_get_clip (self->start_widget, &child_clip);
+      gtk_widget_size_allocate (left, &child_allocation);
+      gtk_widget_get_clip (left, &child_clip);
       gdk_rectangle_union (&clip, &clip, &child_clip);
-      start_size = child_allocation.width;
+      left_size = child_allocation.width;
     }
 
-  if (self->end_widget)
+  if (right)
     {
-      gtk_widget_measure (self->end_widget, GTK_ORIENTATION_HORIZONTAL,
-                          allocation->height,
-                          &min, &nat, NULL, NULL);
-      child_allocation.x = allocation->x + allocation->width - min;
-      child_allocation.width = min;
-
-      gtk_widget_size_allocate (self->end_widget, &child_allocation);
-      gtk_widget_get_clip (self->end_widget, &child_clip);
+      avail = MIN ((allocation->width - center_size) / 2, allocation->width - (center_size + left_min));
+      child_allocation.width = CLAMP (avail, right_min, right_nat);
+      child_allocation.x = allocation->x + allocation->width - child_allocation.width;
+
+      gtk_widget_size_allocate (right, &child_allocation);
+      gtk_widget_get_clip (right, &child_clip);
       gdk_rectangle_union (&clip, &clip, &child_clip);
-      end_size = child_allocation.width;
+      right_size = child_allocation.width;
     }
 
-  /* Center Widget */
   if (self->center_widget)
     {
-      gtk_widget_measure (self->center_widget, GTK_ORIENTATION_HORIZONTAL,
-                          allocation->height,
-                          &min, &nat, NULL, NULL);
-
-      child_allocation.x = (allocation->width / 2) - (min / 2);
+      child_allocation.width = center_size;
+      child_allocation.x = (allocation->width / 2) - (child_allocation.width / 2);
 
       /* Push in from start/end */
-      if (start_size > child_allocation.x)
-        child_allocation.x = start_size;
-      else if (allocation->width - end_size < child_allocation.x + min)
-        child_allocation.x = allocation->width - min - end_size;
+      if (left_size > child_allocation.x)
+        child_allocation.x = left_size;
+      else if (allocation->width - right_size < child_allocation.x + child_allocation.width)
+        child_allocation.x = allocation->width - child_allocation.width - right_size;
 
       child_allocation.x += allocation->x;
-      child_allocation.width = min;
       gtk_widget_size_allocate (self->center_widget, &child_allocation);
       gtk_widget_get_clip (self->center_widget, &child_clip);
       gdk_rectangle_union (&clip, &clip, &child_clip);
@@ -230,6 +232,39 @@ gtk_center_box_snapshot (GtkWidget   *widget,
 }
 
 static void
+update_css_node_order (GtkCenterBox *self)
+{
+  GtkCssNode *parent;
+  GtkCssNode *first;
+  GtkCssNode *last;
+
+  parent = gtk_widget_get_css_node (GTK_WIDGET (self));
+
+  if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_LTR)
+    {
+      first = self->start_widget ? gtk_widget_get_css_node (self->start_widget) : NULL;
+      last = self->end_widget ? gtk_widget_get_css_node (self->end_widget) : NULL;
+    }
+  else
+    {
+      first = self->end_widget ? gtk_widget_get_css_node (self->end_widget) : NULL;
+      last = self->start_widget ? gtk_widget_get_css_node (self->start_widget) : NULL;
+    }
+
+  if (first)
+    gtk_css_node_insert_after (parent, first, NULL);
+  if (last)
+    gtk_css_node_insert_before (parent, last, NULL);
+}
+
+static void
+gtk_center_box_direction_changed (GtkWidget        *widget,
+                                  GtkTextDirection  previous_direction)
+{
+  update_css_node_order (GTK_CENTER_BOX (widget));
+}
+
+static void
 gtk_center_box_class_init (GtkCenterBoxClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
@@ -237,6 +272,7 @@ gtk_center_box_class_init (GtkCenterBoxClass *klass)
   widget_class->measure = gtk_center_box_measure;
   widget_class->size_allocate = gtk_center_box_size_allocate;
   widget_class->snapshot = gtk_center_box_snapshot;
+  widget_class->direction_changed = gtk_center_box_direction_changed;
 
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_FILLER);
   gtk_widget_class_set_css_name (widget_class, "box");
@@ -286,6 +322,8 @@ gtk_center_box_set_start_widget (GtkCenterBox *self,
   self->start_widget = child;
   if (child)
     gtk_widget_set_parent (child, GTK_WIDGET (self));
+
+  update_css_node_order (self);
 }
 
 /**
@@ -307,6 +345,8 @@ gtk_center_box_set_center_widget (GtkCenterBox *self,
   self->center_widget = child;
   if (child)
     gtk_widget_set_parent (child, GTK_WIDGET (self));
+
+  update_css_node_order (self);
 }
 
 /**
@@ -328,6 +368,8 @@ gtk_center_box_set_end_widget (GtkCenterBox *self,
   self->end_widget = child;
   if (child)
     gtk_widget_set_parent (child, GTK_WIDGET (self));
+
+  update_css_node_order (self);
 }
 
 /**


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