From 267227aa75c390a37d99c7e0925517597d7bee4e Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 29 Jun 2019 04:17:46 +0000 Subject: [PATCH] constraint layout: go back to keeping constraints We want to minimize changes to the solver, so keep the size constraints around and only update them when the size changes. --- gtk/gtkconstraintlayout.c | 171 +++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 96 deletions(-) diff --git a/gtk/gtkconstraintlayout.c b/gtk/gtkconstraintlayout.c index 094098d4eb..b3d0fe1d63 100644 --- a/gtk/gtkconstraintlayout.c +++ b/gtk/gtkconstraintlayout.c @@ -75,10 +75,21 @@ #include "gtksizerequest.h" #include "gtkwidgetprivate.h" +enum { + MIN_WIDTH, + MIN_HEIGHT, + NAT_WIDTH, + NAT_HEIGHT, + LAST_VALUE +}; + struct _GtkConstraintLayoutChild { GtkLayoutChild parent_instance; + int values[LAST_VALUE]; + GtkConstraintRef *constraints[LAST_VALUE]; + /* HashTable; a hash table of variables, * one for each attribute; we use these to query and suggest the * values for the solver. The string is static and does not need @@ -691,6 +702,58 @@ layout_add_constraint (GtkConstraintLayout *self, gtk_constraint_get_weight (constraint)); } +static void +update_child_constraint (GtkConstraintLayout *self, + GtkConstraintLayoutChild *child_info, + GtkWidget *child, + int index, + int value) +{ + + GtkConstraintVariable *var; + int attr[LAST_VALUE] = { + GTK_CONSTRAINT_ATTRIBUTE_WIDTH, + GTK_CONSTRAINT_ATTRIBUTE_HEIGHT, + GTK_CONSTRAINT_ATTRIBUTE_WIDTH, + GTK_CONSTRAINT_ATTRIBUTE_HEIGHT + }; + int relation[LAST_VALUE] = { + GTK_CONSTRAINT_RELATION_GE, + GTK_CONSTRAINT_RELATION_GE, + GTK_CONSTRAINT_RELATION_EQ, + GTK_CONSTRAINT_RELATION_EQ + }; + + if (child_info->values[index] != value) + { + child_info->values[index] = value; + + if (child_info->constraints[index]) + gtk_constraint_solver_remove_constraint (self->solver, + child_info->constraints[index]); + + var = get_child_attribute (self, child, attr[index]); + + if (relation[index] == GTK_CONSTRAINT_RELATION_EQ) + { + gtk_constraint_variable_set_value (var, value); + child_info->constraints[index] = + gtk_constraint_solver_add_stay_variable (self->solver, + var, + GTK_CONSTRAINT_WEIGHT_MEDIUM); + } + else + { + child_info->constraints[index] = + gtk_constraint_solver_add_constraint (self->solver, + var, + relation[index], + gtk_constraint_expression_new (value), + GTK_CONSTRAINT_WEIGHT_REQUIRED); + } + } +} + static void gtk_constraint_layout_measure (GtkLayoutManager *manager, GtkWidget *widget, @@ -704,7 +767,6 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager, GtkConstraintLayout *self = GTK_CONSTRAINT_LAYOUT (manager); GtkConstraintVariable *size, *opposite_size; GtkConstraintSolver *solver; - GPtrArray *size_constraints; GtkWidget *child; int min_value; int nat_value; @@ -713,8 +775,6 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager, if (solver == NULL) return; - size_constraints = g_ptr_array_new (); - /* We measure each child in the layout and impose restrictions on the * minimum and natural size, so we can solve the size of the overall * layout later on @@ -723,8 +783,7 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager, child != NULL; child = _gtk_widget_get_next_sibling (child)) { - GtkConstraintVariable *width_var, *height_var; - GtkConstraintRef *constraint; + GtkConstraintLayoutChild *info; GtkRequisition min_req, nat_req; if (!gtk_widget_should_layout (child)) @@ -732,39 +791,12 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager, gtk_widget_get_preferred_size (child, &min_req, &nat_req); - width_var = get_child_attribute (self, child, GTK_CONSTRAINT_ATTRIBUTE_WIDTH); + info = GTK_CONSTRAINT_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (manager, child)); - constraint = - gtk_constraint_solver_add_constraint (solver, - width_var, - GTK_CONSTRAINT_RELATION_GE, - gtk_constraint_expression_new (min_req.width), - GTK_CONSTRAINT_WEIGHT_REQUIRED); - g_ptr_array_add (size_constraints, constraint); - - gtk_constraint_variable_set_value (width_var, nat_req.width); - constraint = - gtk_constraint_solver_add_stay_variable (solver, - width_var, - GTK_CONSTRAINT_WEIGHT_MEDIUM); - g_ptr_array_add (size_constraints, constraint); - - height_var = get_child_attribute (self, child, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT); - - constraint = - gtk_constraint_solver_add_constraint (solver, - height_var, - GTK_CONSTRAINT_RELATION_GE, - gtk_constraint_expression_new (min_req.height), - GTK_CONSTRAINT_WEIGHT_REQUIRED); - g_ptr_array_add (size_constraints, constraint); - - gtk_constraint_variable_set_value (height_var, nat_req.height); - constraint = - gtk_constraint_solver_add_stay_variable (solver, - height_var, - GTK_CONSTRAINT_WEIGHT_MEDIUM); - g_ptr_array_add (size_constraints, constraint); + update_child_constraint (self, info, child, MIN_WIDTH, min_req.width); + update_child_constraint (self, info, child, MIN_HEIGHT, min_req.height); + update_child_constraint (self, info, child, NAT_WIDTH, nat_req.width); + update_child_constraint (self, info, child, NAT_HEIGHT, nat_req.height); } switch (orientation) @@ -815,15 +847,6 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager, min_value, nat_value, for_size)); - for (guint i = 0; i < size_constraints->len; i++) - { - GtkConstraintRef *ref = g_ptr_array_index (size_constraints, i); - - gtk_constraint_solver_remove_constraint (solver, ref); - } - - g_ptr_array_unref (size_constraints); - if (minimum != NULL) *minimum = min_value; @@ -843,7 +866,6 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager, GtkConstraintSolver *solver; GtkConstraintVariable *layout_top, *layout_height; GtkConstraintVariable *layout_left, *layout_width; - GPtrArray *size_constraints; GtkWidget *child; solver = gtk_constraint_layout_get_solver (self); @@ -882,8 +904,6 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager, gtk_constraint_variable_get_value (layout_width), gtk_constraint_variable_get_value (layout_height))); - size_constraints = g_ptr_array_new (); - /* We reset the constraints on the size of each child, so we are sure the * layout is up to date */ @@ -891,48 +911,20 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager, child != NULL; child = _gtk_widget_get_next_sibling (child)) { - GtkConstraintVariable *width_var, *height_var; GtkRequisition min_req, nat_req; - GtkConstraintRef *constraint; + GtkConstraintLayoutChild *info; if (!gtk_widget_should_layout (child)) continue; gtk_widget_get_preferred_size (child, &min_req, &nat_req); - width_var = get_child_attribute (self, child, GTK_CONSTRAINT_ATTRIBUTE_WIDTH); + info = GTK_CONSTRAINT_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (manager, child)); - constraint = - gtk_constraint_solver_add_constraint (solver, - width_var, - GTK_CONSTRAINT_RELATION_GE, - gtk_constraint_expression_new (min_req.width), - GTK_CONSTRAINT_WEIGHT_REQUIRED); - g_ptr_array_add (size_constraints, constraint); - - gtk_constraint_variable_set_value (width_var, nat_req.width); - constraint = - gtk_constraint_solver_add_stay_variable (solver, - width_var, - GTK_CONSTRAINT_WEIGHT_MEDIUM); - g_ptr_array_add (size_constraints, constraint); - - height_var = get_child_attribute (self, child, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT); - - constraint = - gtk_constraint_solver_add_constraint (solver, - height_var, - GTK_CONSTRAINT_RELATION_GE, - gtk_constraint_expression_new (min_req.height), - GTK_CONSTRAINT_WEIGHT_REQUIRED); - g_ptr_array_add (size_constraints, constraint); - - gtk_constraint_variable_set_value (height_var, nat_req.height); - constraint = - gtk_constraint_solver_add_stay_variable (solver, - height_var, - GTK_CONSTRAINT_WEIGHT_MEDIUM); - g_ptr_array_add (size_constraints, constraint); + update_child_constraint (self, info, child, MIN_WIDTH, min_req.width); + update_child_constraint (self, info, child, MIN_HEIGHT, min_req.height); + update_child_constraint (self, info, child, NAT_WIDTH, nat_req.width); + update_child_constraint (self, info, child, NAT_HEIGHT, nat_req.height); } for (child = _gtk_widget_get_first_child (widget); @@ -1000,16 +992,6 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager, } #endif - /* The constraints on the children sizes can be removed now */ - for (guint i = 0; i < size_constraints->len; i++) - { - GtkConstraintRef *ref = g_ptr_array_index (size_constraints, i); - - gtk_constraint_solver_remove_constraint (solver, ref); - } - - g_ptr_array_unref (size_constraints); - /* The allocation stay constraints are not needed any more */ gtk_constraint_solver_remove_constraint (solver, stay_w); gtk_constraint_solver_remove_constraint (solver, stay_h); @@ -1342,13 +1324,10 @@ add_child_constraints (GtkConstraintLayout *self, GtkConstraintVariable **cols, GPtrArray *refs) { - GtkConstraintLayoutChild *info; GtkConstraintVariable *var; GtkConstraintVariable *var1; GtkConstraintRef *ref; - info = GTK_CONSTRAINT_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), child->child)); - var = get_child_attribute (self, child->child, GTK_CONSTRAINT_ATTRIBUTE_LEFT); var1 = cols[child->left];