diff options
Diffstat (limited to 'gtk/gtkconstraintlayout.c')
-rw-r--r-- | gtk/gtkconstraintlayout.c | 233 |
1 files changed, 232 insertions, 1 deletions
diff --git a/gtk/gtkconstraintlayout.c b/gtk/gtkconstraintlayout.c index bbdd27746c..f8df73f3ca 100644 --- a/gtk/gtkconstraintlayout.c +++ b/gtk/gtkconstraintlayout.c @@ -62,6 +62,7 @@ #include "gtkconstraintlayout.h" #include "gtkconstraintprivate.h" +#include "gtkgridconstraintprivate.h" #include "gtkconstraintexpressionprivate.h" #include "gtkconstraintsolverprivate.h" #include "gtklayoutchild.h" @@ -105,6 +106,8 @@ struct _GtkConstraintLayout * parent widget, using the public API objects. */ GHashTable *constraints; + + GHashTable *grid_constraints; }; G_DEFINE_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK_TYPE_LAYOUT_CHILD) @@ -361,6 +364,7 @@ gtk_constraint_layout_finalize (GObject *gobject) g_clear_pointer (&self->bound_attributes, g_hash_table_unref); g_clear_pointer (&self->constraints, g_hash_table_unref); + g_clear_pointer (&self->grid_constraints, g_hash_table_unref); G_OBJECT_CLASS (gtk_constraint_layout_parent_class)->finalize (gobject); } @@ -977,6 +981,9 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager, gtk_constraint_solver_remove_constraint (solver, stay_l); } +static void layout_add_grid_constraint (GtkConstraintLayout *manager, + GtkGridConstraint *constraint); + static void gtk_constraint_layout_root (GtkLayoutManager *manager) { @@ -996,9 +1003,15 @@ gtk_constraint_layout_root (GtkLayoutManager *manager) while (g_hash_table_iter_next (&iter, &key, NULL)) { GtkConstraint *constraint = key; - layout_add_constraint (self, constraint); } + + g_hash_table_iter_init (&iter, self->grid_constraints); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + GtkGridConstraint *constraint = key; + layout_add_grid_constraint (self, constraint); + } } static void @@ -1020,6 +1033,14 @@ gtk_constraint_layout_unroot (GtkLayoutManager *manager) gtk_constraint_detach (constraint); } + g_hash_table_iter_init (&iter, self->grid_constraints); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + GtkGridConstraint *constraint = key; + + gtk_grid_constraint_detach (constraint); + } + self->solver = NULL; } @@ -1052,6 +1073,10 @@ gtk_constraint_layout_init (GtkConstraintLayout *self) g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL); + self->grid_constraints = + g_hash_table_new_full (NULL, NULL, + (GDestroyNotify) g_object_unref, + NULL); } /** @@ -1121,3 +1146,209 @@ gtk_constraint_layout_remove_constraint (GtkConstraintLayout *manager, gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (manager)); } + +void +gtk_constraint_layout_add_grid_constraint (GtkConstraintLayout *manager, + GtkGridConstraint *constraint) +{ + g_return_if_fail (GTK_IS_CONSTRAINT_LAYOUT (manager)); + g_return_if_fail (GTK_IS_GRID_CONSTRAINT (constraint)); + g_return_if_fail (!gtk_grid_constraint_is_attached (constraint)); + + layout_add_grid_constraint (manager, constraint); + + g_hash_table_add (manager->grid_constraints, constraint); +} + +static GtkConstraintVariable ** +allocate_variables (GtkConstraintSolver *solver, + const char *name, + int n) +{ + GtkConstraintVariable **vars; + int i; + + vars = g_new (GtkConstraintVariable *, n); + for (i = 0; i < n; i++) + { + char *vname = g_strdup_printf ("%s%d", name, i); + vars[i] = gtk_constraint_solver_create_variable (solver, NULL, vname, 0.0); + } + + return vars; +} + +#if 0 +static void +add_ordering_constraints (GtkConstraintSolver *solver, + GtkConstraintVariable **vars, + int n_vars, + GPtrArray *refs) +{ + int i; + + for (i = 1; i < n_vars; i++) + { + GtkConstraintRef *ref; + + ref = gtk_constraint_solver_add_constraint (solver, + vars[i], + GTK_CONSTRAINT_RELATION_GE, + gtk_constraint_expression_new_from_variable (vars[i - 1]), + GTK_CONSTRAINT_WEIGHT_MEDIUM); + g_ptr_array_add (refs, ref); + } +} +#endif + +static void +add_homogeneous_constraints (GtkConstraintSolver *solver, + GtkConstraintVariable **vars, + int n_vars, + GPtrArray *refs) +{ + int i; + + for (i = 2; i < n_vars; i++) + { + GtkConstraintExpressionBuilder builder; + GtkConstraintRef *ref; + + gtk_constraint_expression_builder_init (&builder, solver); + gtk_constraint_expression_builder_term (&builder, vars[i]); + gtk_constraint_expression_builder_plus (&builder); + gtk_constraint_expression_builder_term (&builder, vars[i - 2]); + gtk_constraint_expression_builder_divide_by (&builder); + gtk_constraint_expression_builder_constant (&builder, 2.0); + + ref = gtk_constraint_solver_add_constraint (solver, + vars[i - 1], + GTK_CONSTRAINT_RELATION_EQ, + gtk_constraint_expression_builder_finish (&builder), + GTK_CONSTRAINT_WEIGHT_REQUIRED); + g_ptr_array_add (refs, ref); + } +} + +static void +add_child_constraints (GtkConstraintLayout *manager, + GtkConstraintSolver *solver, + GtkGridConstraintChild *child, + GtkConstraintVariable **rows, + 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 (manager), child->child)); + + var = get_child_attribute (info, solver, child->child, GTK_CONSTRAINT_ATTRIBUTE_LEFT); + var1 = cols[child->left]; + + ref = gtk_constraint_solver_add_constraint (solver, + var, + GTK_CONSTRAINT_RELATION_EQ, + gtk_constraint_expression_new_from_variable (var1), + GTK_CONSTRAINT_WEIGHT_REQUIRED); + g_ptr_array_add (refs, ref); + + var = get_child_attribute (info, solver, child->child, GTK_CONSTRAINT_ATTRIBUTE_RIGHT); + var1 = cols[child->right]; + + ref = gtk_constraint_solver_add_constraint (solver, + var, + GTK_CONSTRAINT_RELATION_EQ, + gtk_constraint_expression_new_from_variable (var1), + GTK_CONSTRAINT_WEIGHT_REQUIRED); + g_ptr_array_add (refs, ref); + + var = get_child_attribute (info, solver, child->child, GTK_CONSTRAINT_ATTRIBUTE_TOP); + var1 = rows[child->top]; + + ref = gtk_constraint_solver_add_constraint (solver, + var, + GTK_CONSTRAINT_RELATION_EQ, + gtk_constraint_expression_new_from_variable (var1), + GTK_CONSTRAINT_WEIGHT_REQUIRED); + g_ptr_array_add (refs, ref); + + var = get_child_attribute (info, solver, child->child, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM); + var1 = rows[child->bottom]; + + ref = gtk_constraint_solver_add_constraint (solver, + var, + GTK_CONSTRAINT_RELATION_EQ, + gtk_constraint_expression_new_from_variable (var1), + GTK_CONSTRAINT_WEIGHT_REQUIRED); + g_ptr_array_add (refs, ref); +} + +static void +layout_add_grid_constraint (GtkConstraintLayout *manager, + GtkGridConstraint *constraint) +{ + GtkWidget *layout_widget; + GtkConstraintSolver *solver; + GtkConstraintVariable **rows; + GtkConstraintVariable **cols; + int n_rows, n_cols; + GPtrArray *refs; + int i; + + if (gtk_grid_constraint_is_attached (constraint)) + return; + + layout_widget = gtk_layout_manager_get_widget (GTK_LAYOUT_MANAGER (manager)); + if (layout_widget == NULL) + return; + + solver = gtk_constraint_layout_get_solver (manager); + if (solver == NULL) + return; + + gtk_constraint_solver_freeze (solver); + + refs = g_ptr_array_new (); + + n_rows = n_cols = 0; + for (i = 0; i < constraint->children->len; i++) + { + GtkGridConstraintChild *child = g_ptr_array_index (constraint->children, i); + n_rows = MAX (n_rows, child->bottom); + n_cols = MAX (n_cols, child->right); + } + n_rows++; + n_cols++; + + rows = allocate_variables (solver, "row", n_rows); + cols = allocate_variables (solver, "col", n_cols); + +#if 0 + //FIXME for some reason, these 'obvious' constraints + // make things unstable (and they are not really needed) + add_ordering_constraints (solver, rows, n_rows, refs); + add_ordering_constraints (solver, cols, n_cols, refs); +#endif + + if (constraint->row_homogeneous) + add_homogeneous_constraints (solver, rows, n_rows, refs); + if (constraint->column_homogeneous) + add_homogeneous_constraints (solver, cols, n_cols, refs); + + for (i = 0; i < constraint->children->len; i++) + { + GtkGridConstraintChild *child = g_ptr_array_index (constraint->children, i); + add_child_constraints (manager, solver, child, rows, cols, refs); + } + + gtk_grid_constraint_attach (constraint, solver, refs); + + g_free (rows); + g_free (cols); + g_ptr_array_unref (refs); + + gtk_constraint_solver_thaw (solver); +} |