summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-06-03 15:56:01 -0400
committerMatthias Clasen <mclasen@redhat.com>2017-06-03 15:56:01 -0400
commitcd43686289b99b9e20510f0b8b161912674d7506 (patch)
tree181d9eb7f1c4e5f2f9a33be21db9f4324836d788
parent3dc7e71c32ea16542266390ad9fd05e2174c2429 (diff)
downloadgtk+-cd43686289b99b9e20510f0b8b161912674d7506.tar.gz
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.
-rw-r--r--gtk/gtkcenterbox.c230
1 files changed, 142 insertions, 88 deletions
diff --git a/gtk/gtkcenterbox.c b/gtk/gtkcenterbox.c
index 3a13b0d21c..80abe2cb29 100644
--- a/gtk/gtkcenterbox.c
+++ b/gtk/gtkcenterbox.c
@@ -31,6 +31,9 @@
#include "config.h"
#include "gtkcenterbox.h"
+#include "gtkcssnodeprivate.h"
+#include "gtkwidgetprivate.h"
+
G_DEFINE_TYPE (GtkCenterBox, gtk_center_box, GTK_TYPE_WIDGET);
@@ -45,69 +48,48 @@ 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));
}
+
+if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ g_print ("center box measure: min %d nat %d\n", *minimum, *natural);
}
static void
@@ -118,62 +100,91 @@ 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;
+g_print ("left to right\n");
+ }
+ else
+ {
+ right = self->start_widget;
+ left = self->end_widget;
+g_print ("right to left\n");
+ }
+g_print ("center box allocate: %d\n", allocation->width);
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);
@@ -199,6 +210,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);
@@ -206,6 +250,10 @@ 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");
}
static void
@@ -252,6 +300,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);
}
/**
@@ -273,6 +323,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);
}
/**
@@ -294,6 +346,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);
}
/**