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.
This commit is contained in:
Matthias Clasen
2019-06-29 04:17:46 +00:00
parent 0695869e57
commit 267227aa75

View File

@@ -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<static string, Variable>; 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];