diff --git a/gtk/gtkcenterbox.c b/gtk/gtkcenterbox.c index abc37224ab..91a7a0477f 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, + ¢er_min, ¢er_nat, + &min_baseline, &nat_baseline); if (self->end_widget) - { - gtk_widget_measure (self->end_widget, - orientation, - for_size, - &min, &nat, - &min_baseline, &nat_baseline); + gtk_widget_measure (self->end_widget, + orientation, + for_size, + &end_min, &end_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); - } + 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 */ + { + *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, + ¢er_min, ¢er_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; + 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 (self->end_widget, &child_allocation); - gtk_widget_get_clip (self->end_widget, &child_clip); + 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); @@ -229,6 +231,39 @@ gtk_center_box_snapshot (GtkWidget *widget, gtk_widget_snapshot_child (widget, self->end_widget, snapshot); } +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) { @@ -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); } /**