Compare commits

..

21 Commits

Author SHA1 Message Date
Matthias Clasen 615f1aed65 Add an interactive constraint solver test
This is an example described in the original
Cassowary paper, reimplemented from scratch.
It exposes some instability and crashiness
in our solver.
2019-06-28 04:51:18 +00:00
Matthias Clasen 19fdb764a6 constraint solver: Add a hack for external linking
Make it possible to build tests which use
GtkConstraintSolver from inside and outside libgtk.
See the test added in the following commit for
how this is used.
2019-06-28 04:49:42 +00:00
Matthias Clasen ee04ad7e96 demo: Use constraint guide api
Use proper api to create and set up
the guide, and also try max-width.
2019-06-27 22:09:24 +00:00
Matthias Clasen d4f6ad74dd constraint guide: Add more private api
This lets us avoid exposing the struct.
2019-06-27 22:09:24 +00:00
Matthias Clasen 4025b9ed00 constraint guide: Fix the max-size implementation
We need to update all constraints, including
the new ones. Do it with a loop to avoid the
same problem reoccurring.
2019-06-27 22:08:31 +00:00
Matthias Clasen f4fe1f4bcf constraint guide: Add setters/getters
We have properties, so we should have setters
and getters.
2019-06-27 22:08:31 +00:00
Matthias Clasen 75e3017f51 constraint guide: Implement gtk_constraint_guide_new
This was in the headers, but not implemented.
2019-06-27 17:18:30 -04:00
Matthias Clasen f2a604ba9f Split GtkConstraintGuide into its own file
Lest gtkconstraintlayout.c turns too big and messy.
2019-06-27 20:25:42 +00:00
Matthias Clasen a691df2a5f Drop an indirection
This struct is not really useful for just
a single hash table, and it gets in the way
of moving the guide code to its own file.
2019-06-27 19:34:03 +00:00
Matthias Clasen 376b5b326e Give guides max-width/height 2019-06-27 19:13:38 +00:00
Matthias Clasen 38156f4454 Detach guides on unroot
We don't want to leave constraints behind.
2019-06-27 19:10:13 +00:00
Matthias Clasen b462988e3c Simplify the guide implementation
Store the values and constraints in
arrays, to facilitate treating them
uniformly.
2019-06-27 19:10:13 +00:00
Matthias Clasen cf702b81a8 Add an interactive constraints demo 2019-06-27 18:48:04 +01:00
Matthias Clasen 04d7e894e2 Make the constraints demo more interesting
Add a max size to the buttons, to force the
space to open up.
2019-06-27 18:43:53 +01:00
Matthias Clasen 4efcad59df Add GtkConstraintGuide
This is meant to be a flexible space.
2019-06-27 18:43:26 +01:00
Emmanuele Bassi 8bacf47c41 Use generic pointers for constraint targets
Since GtkWidget implements GtkConstraintTarget, we can omit the explicit
cast, and validate the type at run time.
2019-06-27 18:26:19 +01:00
Matthias Clasen 8f5515d498 Redefine constraints with GtkConstraintTarget
This is in preparation for allowing non-widgets
to act as constraint targets.
2019-06-27 18:21:33 +01:00
Matthias Clasen 3a8c1abbc1 widget: Implement GtkConstraintTarget 2019-06-27 18:21:16 +01:00
Matthias Clasen 02f4e1a5ae Add GtkConstraintTarget
This is an marker interface that we will
use to accept other things that widgets
in constraints.
2019-06-27 18:20:23 +01:00
Emmanuele Bassi 7afac64225 Notify a layout change when adding and removing constraints
Changing the set of constraints should cause a relayout.
2019-06-27 17:38:02 +01:00
Emmanuele Bassi cb11ba4ca0 Fix the opposite size measurement in GtkConstraintLayout
We cannot use the given "for size" when querying our children, because
the constraint layout has no idea about the opposite size of its
children until the layout is complete.

Additionally, we should only suggest an opposite size for the layout if
we have one, instead of suggesting a weak zero size.
2019-06-27 17:38:02 +01:00
26 changed files with 331 additions and 3241 deletions
+9 -18
View File
@@ -44,21 +44,20 @@ simple_grid_class_init (SimpleGridClass *klass)
/* Layout:
*
* +-------------------------------------+
* | +-----------++-------++-----------+ |
* | | Child 1 || Space || Child 2 | |
* | +-----------++-------++-----------+ |
* | +---------------------------------+ |
* | | Child 3 | |
* | +---------------------------------+ |
* +-------------------------------------+
* +-----------------------------+
* | +-----------+ +-----------+ |
* | | Child 1 | | Child 2 | |
* | +-----------+ +-----------+ |
* | +-------------------------+ |
* | | Child 3 | |
* | +-------------------------+ |
* +-----------------------------+
*
* Constraints:
*
* super.start = child1.start - 8
* child1.width = child2.width
* child1.end = space.start
* space.end = child2.start
* child1.end = child2.start - 12
* child2.end = super.end - 8
* super.start = child3.start - 8
* child3.end = super.end - 8
@@ -70,12 +69,6 @@ simple_grid_class_init (SimpleGridClass *klass)
* child3.height = child2.height
* child3.bottom = super.bottom - 8
*
* To add some flexibility, we make the space
* stretchable:
*
* space.width >= 10
* space.width = 100
* space.width <= 200
*/
static void
build_constraints (SimpleGrid *self,
@@ -84,11 +77,9 @@ build_constraints (SimpleGrid *self,
GtkConstraintGuide *guide;
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, "space");
gtk_constraint_guide_set_min_size (guide, 10, 10);
gtk_constraint_guide_set_nat_size (guide, 100, 10);
gtk_constraint_guide_set_max_size (guide, 200, 20);
gtk_constraint_guide_set_strength (guide, GTK_CONSTRAINT_STRENGTH_STRONG);
gtk_constraint_layout_add_guide (manager, guide);
gtk_constraint_layout_add_constraint (manager,
-190
View File
@@ -1,190 +0,0 @@
/* Constraints/Grid
*
* GtkConstraintLayout lets you define complex layouts
* like grids.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (ComplexGrid, complex_grid, COMPLEX, GRID, GtkWidget)
struct _ComplexGrid
{
GtkWidget parent_instance;
GtkWidget *button1, *button2, *button3;
GtkWidget *button4, *button5;
};
G_DEFINE_TYPE (ComplexGrid, complex_grid, GTK_TYPE_WIDGET)
static void
complex_grid_destroy (GtkWidget *widget)
{
ComplexGrid *self = COMPLEX_GRID (widget);
g_clear_pointer (&self->button1, gtk_widget_destroy);
g_clear_pointer (&self->button2, gtk_widget_destroy);
g_clear_pointer (&self->button3, gtk_widget_destroy);
g_clear_pointer (&self->button4, gtk_widget_destroy);
g_clear_pointer (&self->button5, gtk_widget_destroy);
GTK_WIDGET_CLASS (complex_grid_parent_class)->destroy (widget);
}
static void
complex_grid_class_init (ComplexGridClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->destroy = complex_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
/* Layout:
*
* +--------------------------------------+
* | +-----------+ |
* | | Child 4 | |
* | +-----------+-----------+----------+ |
* | | Child 1 | Child 2 | Child 3 | |
* | +-----------+-----------+----------+ |
* | | Child 5 | |
* | +-----------+ |
* +--------------------------------------+
*
*/
static void
build_constraints (ComplexGrid *self,
GtkConstraintLayout *manager)
{
GtkGridConstraint *constraint;
GtkConstraint *s;
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
self->button1, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (self->button3, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
GTK_CONSTRAINT_RELATION_EQ,
NULL, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
self->button4, GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
self->button5, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
constraint = gtk_grid_constraint_new ();
g_object_set (constraint, "column-homogeneous", TRUE, NULL);
gtk_grid_constraint_add (constraint,
self->button1,
0, 1, 0, 1);
gtk_grid_constraint_add (constraint,
self->button2,
1, 2, 0, 1);
gtk_grid_constraint_add (constraint,
self->button3,
2, 3, 0, 1);
gtk_constraint_layout_add_grid_constraint (manager, constraint);
constraint = gtk_grid_constraint_new ();
g_object_set (constraint, "row-homogeneous", TRUE, NULL);
gtk_grid_constraint_add (constraint,
self->button4,
0, 1, 0, 1);
gtk_grid_constraint_add (constraint,
self->button2,
0, 1, 1, 2);
gtk_grid_constraint_add (constraint,
self->button5,
0, 1, 2, 3);
gtk_constraint_layout_add_grid_constraint (manager, constraint);
}
static void
complex_grid_init (ComplexGrid *self)
{
GtkWidget *widget = GTK_WIDGET (self);
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
gtk_widget_set_name (self->button1, "button1");
self->button2 = gtk_button_new_with_label ("Child 2");
gtk_widget_set_parent (self->button2, widget);
gtk_widget_set_name (self->button2, "button2");
self->button3 = gtk_button_new_with_label ("Child 3");
gtk_widget_set_parent (self->button3, widget);
gtk_widget_set_name (self->button3, "button3");
self->button4 = gtk_button_new_with_label ("Child 4");
gtk_widget_set_parent (self->button4, widget);
gtk_widget_set_name (self->button4, "button4");
self->button5 = gtk_button_new_with_label ("Child 5");
gtk_widget_set_parent (self->button5, widget);
gtk_widget_set_name (self->button5, "button5");
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
}
GtkWidget *
do_constraints3 (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_add (GTK_CONTAINER (window), box);
grid = g_object_new (complex_grid_get_type (), NULL);
gtk_widget_set_hexpand (grid, TRUE);
gtk_widget_set_vexpand (grid, TRUE);
gtk_container_add (GTK_CONTAINER (box), grid);
button = gtk_button_new_with_label ("Close");
gtk_container_add (GTK_CONTAINER (box), button);
gtk_widget_set_hexpand (grid, TRUE);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy), window);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
-355
View File
@@ -1,355 +0,0 @@
/* Constraints/Words
*
* GtkConstraintLayout lets you define big grids.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define WORDS_TYPE_BASE (words_base_get_type ())
#define WORDS_TYPE_GRID (words_grid_get_type ())
#define WORDS_TYPE_CONSTRAINT (words_constraint_get_type ())
typedef struct
{
GtkWidget parent_instance;
} WordsBase;
typedef WordsBase WordsGrid;
typedef WordsBase WordsConstraint;
typedef GtkWidgetClass WordsBaseClass;
typedef GtkWidgetClass WordsGridClass;
typedef GtkWidgetClass WordsConstraintClass;
G_DEFINE_TYPE (WordsBase, words_base, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (WordsGrid, words_grid, WORDS_TYPE_BASE)
G_DEFINE_TYPE (WordsConstraint, words_constraint, WORDS_TYPE_BASE)
static void
words_grid_init (WordsGrid *words)
{
}
static void
words_grid_class_init (WordsGridClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_GRID_LAYOUT);
}
static void
words_constraint_init (WordsGrid *words)
{
}
static void
words_constraint_class_init (WordsConstraintClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
static void
word_base_dispose (GObject *object)
{
GtkWidget *self = GTK_WIDGET (object);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (self)) != NULL)
gtk_widget_unparent (child);
G_OBJECT_CLASS (words_base_parent_class)->dispose (object);
}
static void
words_base_class_init (WordsBaseClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = word_base_dispose;
}
static int num_words = 100;
static gboolean use_constraints = FALSE;
static void
read_words (WordsBase *self)
{
GBytes *data;
const char *words;
int left, top;
GtkWidget *child = NULL;
GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
GtkGridConstraint *grid;
GtkConstraint *constraint;
int count;
int rightmost;
GtkWidget *right_child = NULL;
gboolean use_constraint = GTK_IS_CONSTRAINT_LAYOUT (layout);
if (use_constraint)
{
grid = gtk_grid_constraint_new ();
g_object_set (grid,
"row-homogeneous", TRUE,
"column-homogeneous", FALSE,
NULL);
}
else
{
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), FALSE);
}
data = g_resources_lookup_data ("/constraints4/words", 0, NULL);
words = g_bytes_get_data (data, NULL);
count = 0;
rightmost = 0;
left = 0;
top = 0;
while (words && words[0])
{
char *p = strchr (words, '\n');
char *word;
int len;
if (p)
{
word = strndup (words, p - words);
words = p + 1;
}
else
{
word = strdup (words);
words = NULL;
}
len = strlen (word);
child = gtk_button_new_with_label (word);
if (left + len > 50)
{
top++;
left = 0;
}
gtk_widget_set_parent (child, GTK_WIDGET (self));
if (left + len > rightmost)
{
rightmost = left + len;
right_child = child;
}
if (use_constraint)
{
gtk_grid_constraint_add (grid, child,
left, left + len,
top, top + 1);
if (left == 0 && top == 0)
{
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
}
}
else
{
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (layout, child));
g_object_set (grid_child,
"left-attach", left,
"top-attach", top,
"column-span", len,
"row-span", 1,
NULL);
}
left = left + len;
count++;
if (count >= num_words)
break;
}
if (use_constraint)
{
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
GTK_CONSTRAINT_RELATION_EQ,
right_child,
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
gtk_constraint_layout_add_grid_constraint (GTK_CONSTRAINT_LAYOUT (layout),
grid);
}
g_bytes_unref (data);
}
static void
words_base_init (WordsBase *self)
{
read_words (self);
}
static void
show_words (GtkWidget *parent)
{
GtkWidget *window;
GtkWidget *header, *box, *grid, *button;
GtkWidget *swin;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_transient_for (GTK_WINDOW (window),
GTK_WINDOW (gtk_widget_get_root (parent)));
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), use_constraints ? "Constraints" : "Grid");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), box);
swin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (swin), TRUE);
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (swin), TRUE);
gtk_widget_set_hexpand (swin, TRUE);
gtk_widget_set_vexpand (swin, TRUE);
gtk_widget_set_halign (swin, GTK_ALIGN_FILL);
gtk_widget_set_valign (swin, GTK_ALIGN_FILL);
gtk_container_add (GTK_CONTAINER (box), swin);
if (use_constraints)
grid = g_object_new (WORDS_TYPE_CONSTRAINT, NULL);
else
grid = g_object_new (WORDS_TYPE_GRID, NULL);
gtk_widget_set_halign (swin, GTK_ALIGN_START);
gtk_widget_set_valign (swin, GTK_ALIGN_START);
gtk_container_add (GTK_CONTAINER (swin), grid);
button = gtk_button_new_with_label ("Close");
gtk_container_add (GTK_CONTAINER (box), button);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy), window);
gtk_widget_show (window);
}
static void
use_constraints_cb (GtkButton *button)
{
use_constraints = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
}
static void
word_count_cb (GtkSpinButton *button)
{
num_words = gtk_spin_button_get_value_as_int (button);
}
GtkWidget *
do_constraints4 (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *header, *grid, *button, *label;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Words");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
grid = gtk_grid_new ();
g_object_set (grid,
"margin", 12,
"row-spacing", 12,
"column-spacing", 6,
"halign", GTK_ALIGN_FILL,
"valign", GTK_ALIGN_FILL,
"hexpand", TRUE,
"vexpand", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (window), grid);
label = gtk_label_new ("Constraints:");
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
button = gtk_check_button_new ();
g_signal_connect (button, "clicked", G_CALLBACK (use_constraints_cb), NULL);
gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
label = gtk_label_new ("Words:");
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
button = gtk_spin_button_new_with_range (0, 1300, 1);
g_signal_connect (button, "value-changed", G_CALLBACK (word_count_cb), NULL);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (button), 10);
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
button = gtk_button_new_with_label ("Show");
gtk_widget_set_halign (button, GTK_ALIGN_END);
gtk_widget_set_valign (button, GTK_ALIGN_END);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (show_words), window);
gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 2, 1);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
-5
View File
@@ -12,9 +12,6 @@
<gresource prefix="/builder">
<file>demo.ui</file>
</gresource>
<gresource prefix="/constraints4">
<file>words</file>
</gresource>
<gresource prefix="/css_accordion">
<file>css_accordion.css</file>
<file>reset.css</file>
@@ -155,8 +152,6 @@
<file>combobox.c</file>
<file>constraints.c</file>
<file>constraints2.c</file>
<file>constraints3.c</file>
<file>constraints4.c</file>
<file>css_accordion.c</file>
<file>css_basics.c</file>
<file>css_blendmodes.c</file>
-2
View File
@@ -10,8 +10,6 @@ demos = files([
'combobox.c',
'constraints.c',
'constraints2.c',
'constraints3.c',
'constraints4.c',
'css_accordion.c',
'css_basics.c',
'css_blendmodes.c',
-1315
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -132,7 +132,6 @@
#include <gtk/gtkgesturezoom.h>
#include <gtk/gtkglarea.h>
#include <gtk/gtkgrid.h>
#include <gtk/gtkgridconstraint.h>
#include <gtk/gtkgridlayout.h>
#include <gtk/gtkheaderbar.h>
#include <gtk/gtkicontheme.h>
+33 -40
View File
@@ -384,8 +384,11 @@ gtk_constraint_variable_is_dummy (const GtkConstraintVariable *variable)
* A set of variables.
*/
struct _GtkConstraintVariableSet {
/* List<Variable>, owns a reference */
GSequence *set;
/* HashSet<Variable>, owns a reference */
GHashTable *set;
/* List<Variable>, used for iterating */
GList *ordered_set;
/* Age of the set, to guard against mutations while iterating */
gint64 age;
@@ -402,7 +405,8 @@ gtk_constraint_variable_set_free (GtkConstraintVariableSet *set)
{
g_return_if_fail (set != NULL);
g_sequence_free (set->set);
g_list_free (set->ordered_set);
g_hash_table_unref (set->set);
g_free (set);
}
@@ -419,7 +423,10 @@ gtk_constraint_variable_set_new (void)
{
GtkConstraintVariableSet *res = g_new (GtkConstraintVariableSet, 1);
res->set = g_sequence_new ((GDestroyNotify) gtk_constraint_variable_unref);
res->set = g_hash_table_new_full (NULL, NULL,
(GDestroyNotify) gtk_constraint_variable_unref,
NULL);
res->ordered_set = NULL;
res->age = 0;
@@ -428,8 +435,7 @@ gtk_constraint_variable_set_new (void)
static int
sort_by_variable_id (gconstpointer a,
gconstpointer b,
gpointer data)
gconstpointer b)
{
const GtkConstraintVariable *va = a, *vb = b;
@@ -457,17 +463,16 @@ gboolean
gtk_constraint_variable_set_add (GtkConstraintVariableSet *set,
GtkConstraintVariable *variable)
{
GSequenceIter *iter;
if (g_hash_table_contains (set->set, variable))
return FALSE;
iter = g_sequence_search (set->set, variable, sort_by_variable_id, NULL);
if (!g_sequence_iter_is_end (iter))
{
GtkConstraintVariable *v = g_sequence_get (iter);
if (v->_id == variable->_id)
return FALSE;
}
g_hash_table_add (set->set, gtk_constraint_variable_ref (variable));
g_sequence_insert_before (iter, gtk_constraint_variable_ref (variable));
/* This is a tricky bit; the variables in the set must be ordered
* not by insertion, but by the incremental id of each variable,
* as that's the expected iteration order
*/
set->ordered_set = g_list_insert_sorted (set->ordered_set, variable, sort_by_variable_id);
set->age += 1;
@@ -490,12 +495,10 @@ gboolean
gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
GtkConstraintVariable *variable)
{
GSequenceIter *iter;
iter = g_sequence_lookup (set->set, variable, sort_by_variable_id, NULL);
if (iter != NULL)
if (g_hash_table_contains (set->set, variable))
{
g_sequence_remove (iter);
set->ordered_set = g_list_remove (set->ordered_set, variable);
g_hash_table_remove (set->set, variable);
set->age += 1;
return TRUE;
@@ -515,19 +518,7 @@ gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
int
gtk_constraint_variable_set_size (GtkConstraintVariableSet *set)
{
return g_sequence_get_length (set->set);
}
gboolean
gtk_constraint_variable_set_is_empty (GtkConstraintVariableSet *set)
{
return g_sequence_is_empty (set->set);
}
gboolean
gtk_constraint_variable_set_is_singleton (GtkConstraintVariableSet *set)
{
return g_sequence_iter_next (g_sequence_get_begin_iter (set->set)) == g_sequence_get_end_iter (set->set);
return g_hash_table_size (set->set);
}
/*< private >
@@ -538,7 +529,7 @@ gtk_constraint_variable_set_is_singleton (GtkConstraintVariableSet *set)
/* Keep in sync with GtkConstraintVariableSetIter */
typedef struct {
GtkConstraintVariableSet *set;
GSequenceIter *iter;
GList *current;
gint64 age;
} RealVariableSetIter;
@@ -561,7 +552,7 @@ gtk_constraint_variable_set_iter_init (GtkConstraintVariableSetIter *iter,
g_return_if_fail (set != NULL);
riter->set = set;
riter->iter = g_sequence_get_begin_iter (set->set);
riter->current = NULL;
riter->age = set->age;
}
@@ -585,13 +576,15 @@ gtk_constraint_variable_set_iter_next (GtkConstraintVariableSetIter *iter,
g_assert (riter->age == riter->set->age);
if (g_sequence_iter_is_end (riter->iter))
return FALSE;
if (riter->current == NULL)
riter->current = riter->set->ordered_set;
else
riter->current = riter->current->next;
*variable_p = g_sequence_get (riter->iter);
riter->iter = g_sequence_iter_next (riter->iter);
if (riter->current != NULL)
*variable_p = riter->current->data;
return TRUE;
return riter->current != NULL;
}
/*< private >
-6
View File
@@ -97,12 +97,6 @@ gboolean
gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
GtkConstraintVariable *variable);
gboolean
gtk_constraint_variable_set_is_empty (GtkConstraintVariableSet *set);
gboolean
gtk_constraint_variable_set_is_singleton (GtkConstraintVariableSet *set);
int
gtk_constraint_variable_set_size (GtkConstraintVariableSet *set);
+78 -187
View File
@@ -32,24 +32,20 @@
typedef enum {
MIN_WIDTH,
MIN_HEIGHT,
NAT_WIDTH,
NAT_HEIGHT,
MAX_WIDTH,
MAX_HEIGHT,
LAST_VALUE
GUIDE_MIN_WIDTH,
GUIDE_MIN_HEIGHT,
GUIDE_NAT_WIDTH,
GUIDE_NAT_HEIGHT,
GUIDE_MAX_WIDTH,
GUIDE_MAX_HEIGHT,
LAST_GUIDE_VALUE
} GuideValue;
struct _GtkConstraintGuide
{
GObject parent_instance;
char *name;
int strength;
int values[LAST_VALUE];
int values[LAST_GUIDE_VALUE];
GtkConstraintLayout *layout;
@@ -60,7 +56,7 @@ struct _GtkConstraintGuide
*/
GHashTable *bound_attributes;
GtkConstraintRef *constraints[LAST_VALUE];
GtkConstraintRef *constraints[LAST_GUIDE_VALUE];
};
@@ -69,18 +65,16 @@ struct _GtkConstraintGuideClass {
};
enum {
PROP_MIN_WIDTH = 1,
PROP_MIN_HEIGHT,
PROP_NAT_WIDTH,
PROP_NAT_HEIGHT,
PROP_MAX_WIDTH,
PROP_MAX_HEIGHT,
PROP_STRENGTH,
PROP_NAME,
LAST_PROP
GUIDE_PROP_MIN_WIDTH = 1,
GUIDE_PROP_MIN_HEIGHT,
GUIDE_PROP_NAT_WIDTH,
GUIDE_PROP_NAT_HEIGHT,
GUIDE_PROP_MAX_WIDTH,
GUIDE_PROP_MAX_HEIGHT,
LAST_GUIDE_PROP
};
static GParamSpec *guide_props[LAST_PROP];
static GParamSpec *guide_props[LAST_GUIDE_PROP];
static void
gtk_constraint_guide_constraint_target_iface_init (GtkConstraintTargetInterface *iface)
@@ -94,15 +88,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkConstraintGuide, gtk_constraint_guide, G_TYPE_OBJECT
static void
gtk_constraint_guide_init (GtkConstraintGuide *guide)
{
guide->strength = GTK_CONSTRAINT_STRENGTH_MEDIUM;
guide->values[MIN_WIDTH] = 0;
guide->values[MIN_HEIGHT] = 0;
guide->values[NAT_WIDTH] = 0;
guide->values[NAT_HEIGHT] = 0;
guide->values[MAX_WIDTH] = G_MAXINT;
guide->values[MAX_HEIGHT] = G_MAXINT;
guide->bound_attributes =
g_hash_table_new_full (g_str_hash, g_str_equal,
NULL,
@@ -115,6 +100,30 @@ gtk_constraint_guide_update_constraint (GtkConstraintGuide *guide,
{
GtkConstraintSolver *solver;
GtkConstraintVariable *var;
int attr[LAST_GUIDE_VALUE] = {
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
};
int relation[LAST_GUIDE_VALUE] = {
GTK_CONSTRAINT_RELATION_GE,
GTK_CONSTRAINT_RELATION_GE,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_RELATION_LE,
GTK_CONSTRAINT_RELATION_LE,
};
double weight[LAST_GUIDE_VALUE] = {
GTK_CONSTRAINT_WEIGHT_REQUIRED,
GTK_CONSTRAINT_WEIGHT_REQUIRED,
GTK_CONSTRAINT_WEIGHT_MEDIUM,
GTK_CONSTRAINT_WEIGHT_MEDIUM,
GTK_CONSTRAINT_WEIGHT_REQUIRED,
GTK_CONSTRAINT_WEIGHT_REQUIRED,
};
if (!guide->layout)
return;
@@ -124,48 +133,15 @@ gtk_constraint_guide_update_constraint (GtkConstraintGuide *guide,
return;
if (guide->constraints[index] != NULL)
{
gtk_constraint_solver_remove_constraint (solver, guide->constraints[index]);
guide->constraints[index] = NULL;
}
gtk_constraint_solver_remove_constraint (solver, guide->constraints[index]);
if (index == MIN_WIDTH || index == NAT_WIDTH || index == MAX_WIDTH)
var = gtk_constraint_layout_get_attribute (guide->layout, GTK_CONSTRAINT_ATTRIBUTE_WIDTH, "guide", NULL, guide->bound_attributes);
else
var = gtk_constraint_layout_get_attribute (guide->layout, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT, "guide", NULL, guide->bound_attributes);
/* We always install min-size constraints,
* but we avoid nat-size constraints if min == max
* and we avoid max-size constraints if max == G_MAXINT
*/
if (index == MIN_WIDTH || index == MIN_HEIGHT)
{
guide->constraints[index] =
gtk_constraint_solver_add_constraint (solver,
var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_new (guide->values[index]),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
}
else if ((index == NAT_WIDTH && guide->values[MIN_WIDTH] != guide->values[MAX_WIDTH]) ||
(index == NAT_HEIGHT && guide->values[MIN_HEIGHT] != guide->values[MAX_HEIGHT]))
{
gtk_constraint_variable_set_value (var, guide->values[index]);
guide->constraints[index] =
gtk_constraint_solver_add_stay_variable (solver,
var,
guide->strength);
}
else if ((index == MAX_WIDTH || index == MAX_HEIGHT) &&
guide->values[index] < G_MAXINT)
{
guide->constraints[index] =
gtk_constraint_solver_add_constraint (solver,
var,
GTK_CONSTRAINT_RELATION_LE,
gtk_constraint_expression_new (guide->values[index]),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
}
var = gtk_constraint_layout_get_attribute (guide->layout, attr[index], "guide", NULL, guide->bound_attributes);
guide->constraints[index] =
gtk_constraint_solver_add_constraint (solver,
var,
relation[index],
gtk_constraint_expression_new (guide->values[index]),
weight[index]);
}
void
@@ -173,7 +149,7 @@ gtk_constraint_guide_update (GtkConstraintGuide *guide)
{
int i;
for (i = 0; i < LAST_VALUE; i++)
for (i = 0; i < LAST_GUIDE_VALUE; i++)
gtk_constraint_guide_update_constraint (guide, i);
}
@@ -190,13 +166,10 @@ gtk_constraint_guide_detach (GtkConstraintGuide *guide)
if (!solver)
return;
for (i = 0; i < LAST_VALUE; i++)
for (i = 0; i < LAST_GUIDE_VALUE; i++)
{
if (guide->constraints[i])
{
gtk_constraint_solver_remove_constraint (solver, guide->constraints[i]);
guide->constraints[i] = NULL;
}
gtk_constraint_solver_remove_constraint (solver, guide->constraints[i]);
guide->constraints[i] = NULL;
}
g_hash_table_remove_all (guide->bound_attributes);
@@ -237,35 +210,22 @@ gtk_constraint_guide_set_property (GObject *gobject,
switch (prop_id)
{
case PROP_MIN_WIDTH:
case PROP_MIN_HEIGHT:
case PROP_NAT_WIDTH:
case PROP_NAT_HEIGHT:
case PROP_MAX_WIDTH:
case PROP_MAX_HEIGHT:
case GUIDE_PROP_MIN_WIDTH:
case GUIDE_PROP_MIN_HEIGHT:
case GUIDE_PROP_NAT_WIDTH:
case GUIDE_PROP_NAT_HEIGHT:
case GUIDE_PROP_MAX_WIDTH:
case GUIDE_PROP_MAX_HEIGHT:
val = g_value_get_int (value);
index = prop_id - 1;
if (self->values[index] != val)
{
self->values[index] = val;
g_object_notify_by_pspec (gobject, pspec);
gtk_constraint_guide_update_constraint (self, index);
if (index == MIN_WIDTH || index == MAX_WIDTH)
gtk_constraint_guide_update_constraint (self, NAT_WIDTH);
if (index == MIN_HEIGHT || index == MAX_HEIGHT)
gtk_constraint_guide_update_constraint (self, NAT_HEIGHT);
}
break;
case PROP_STRENGTH:
gtk_constraint_guide_set_strength (self, g_value_get_enum (value));
break;
case PROP_NAME:
gtk_constraint_guide_set_name (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@@ -282,23 +242,15 @@ gtk_constraint_guide_get_property (GObject *gobject,
switch (prop_id)
{
case PROP_MIN_WIDTH:
case PROP_MIN_HEIGHT:
case PROP_NAT_WIDTH:
case PROP_NAT_HEIGHT:
case PROP_MAX_WIDTH:
case PROP_MAX_HEIGHT:
case GUIDE_PROP_MIN_WIDTH:
case GUIDE_PROP_MIN_HEIGHT:
case GUIDE_PROP_NAT_WIDTH:
case GUIDE_PROP_NAT_HEIGHT:
case GUIDE_PROP_MAX_WIDTH:
case GUIDE_PROP_MAX_HEIGHT:
g_value_set_int (value, self->values[prop_id - 1]);
break;
case PROP_STRENGTH:
g_value_set_int (value, self->strength);
break;
case PROP_NAME:
g_value_set_string (value, self->name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@@ -310,8 +262,6 @@ gtk_constraint_guide_finalize (GObject *object)
{
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (object);
g_free (self->name);
g_clear_pointer (&self->bound_attributes, g_hash_table_unref);
G_OBJECT_CLASS (gtk_constraint_guide_parent_class)->finalize (object);
@@ -326,42 +276,42 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
object_class->set_property = gtk_constraint_guide_set_property;
object_class->get_property = gtk_constraint_guide_get_property;
guide_props[PROP_MIN_WIDTH] =
guide_props[GUIDE_PROP_MIN_WIDTH] =
g_param_spec_int ("min-width",
"Minimum width",
"Minimum width",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_MIN_HEIGHT] =
guide_props[GUIDE_PROP_MIN_HEIGHT] =
g_param_spec_int ("min-height",
"Minimum height",
"Minimum height",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_NAT_WIDTH] =
guide_props[GUIDE_PROP_NAT_WIDTH] =
g_param_spec_int ("nat-width",
"Natural width",
"Natural width",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_NAT_HEIGHT] =
guide_props[GUIDE_PROP_NAT_HEIGHT] =
g_param_spec_int ("nat-height",
"Natural height",
"Natural height",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_MAX_WIDTH] =
guide_props[GUIDE_PROP_MAX_WIDTH] =
g_param_spec_int ("max-width",
"Maximum width",
"Maximum width",
0, G_MAXINT, G_MAXINT,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_MAX_HEIGHT] =
guide_props[GUIDE_PROP_MAX_HEIGHT] =
g_param_spec_int ("max-height",
"Maximum height",
"Maximum height",
@@ -369,23 +319,7 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_STRENGTH] =
g_param_spec_enum ("strength",
"Strength",
"The strength to use for natural size",
GTK_TYPE_CONSTRAINT_STRENGTH,
GTK_CONSTRAINT_STRENGTH_MEDIUM,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
guide_props[PROP_NAME] =
g_param_spec_string ("name",
"Name",
"A name to use in debug message",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, guide_props);
g_object_class_install_properties (object_class, LAST_GUIDE_PROP, guide_props);
}
/**
@@ -450,9 +384,9 @@ gtk_constraint_guide_get_min_size (GtkConstraintGuide *guide,
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (width)
*width = guide->values[MIN_WIDTH];
*width = guide->values[GUIDE_MIN_WIDTH];
if (height)
*height = guide->values[MIN_HEIGHT];
*height = guide->values[GUIDE_MIN_HEIGHT];
}
/**
@@ -504,9 +438,9 @@ gtk_constraint_guide_get_nat_size (GtkConstraintGuide *guide,
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (width)
*width = guide->values[NAT_WIDTH];
*width = guide->values[GUIDE_NAT_WIDTH];
if (height)
*height = guide->values[NAT_HEIGHT];
*height = guide->values[GUIDE_NAT_HEIGHT];
}
/**
@@ -558,50 +492,7 @@ gtk_constraint_guide_get_max_size (GtkConstraintGuide *guide,
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (width)
*width = guide->values[MAX_WIDTH];
*width = guide->values[GUIDE_MAX_WIDTH];
if (height)
*height = guide->values[MAX_HEIGHT];
}
const char *
gtk_constraint_guide_get_name (GtkConstraintGuide *guide)
{
g_return_val_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide), NULL);
return guide->name;
}
void
gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
const char *name)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
g_free (guide->name);
guide->name = g_strdup (name);
g_object_notify_by_pspec (G_OBJECT (guide), guide_props[PROP_NAME]);
}
GtkConstraintStrength
gtk_constraint_guide_get_strength (GtkConstraintGuide *guide)
{
g_return_val_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide),
GTK_CONSTRAINT_STRENGTH_MEDIUM);
return guide->strength;
}
void
gtk_constraint_guide_set_strength (GtkConstraintGuide *guide,
GtkConstraintStrength strength)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (guide->strength == strength)
return;
guide->strength = strength;
g_object_notify_by_pspec (G_OBJECT (guide), guide_props[PROP_STRENGTH]);
gtk_constraint_guide_update_constraint (guide, NAT_WIDTH);
gtk_constraint_guide_update_constraint (guide, NAT_HEIGHT);
*height = guide->values[GUIDE_MAX_HEIGHT];
}
-13
View File
@@ -21,7 +21,6 @@
#include <gtk/gtktypes.h>
#include <gtk/gtkenums.h>
#include <gtk/gtktypebuiltins.h>
G_BEGIN_DECLS
@@ -69,16 +68,4 @@ void gtk_constraint_guide_get_max_size (GtkConstraintGu
int *width,
int *height);
GDK_AVAILABLE_IN_ALL
GtkConstraintStrength gtk_constraint_guide_get_strength (GtkConstraintGuide *guide);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_strength (GtkConstraintGuide *guide,
GtkConstraintStrength strength);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
const char *name);
GDK_AVAILABLE_IN_ALL
const char * gtk_constraint_guide_get_name (GtkConstraintGuide *guide);
G_END_DECLS
+139 -309
View File
@@ -63,7 +63,6 @@
#include "gtkconstraintlayoutprivate.h"
#include "gtkconstraintprivate.h"
#include "gtkgridconstraintprivate.h"
#include "gtkconstraintexpressionprivate.h"
#include "gtkconstraintsolverprivate.h"
#include "gtklayoutchild.h"
@@ -75,21 +74,10 @@
#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
@@ -122,9 +110,6 @@ struct _GtkConstraintLayout
/* HashSet<GtkConstraintGuide> */
GHashTable *guides;
/* HashSet<GtkGridConstraint> */
GHashTable *grid_constraints;
};
G_DEFINE_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK_TYPE_LAYOUT_CHILD)
@@ -406,7 +391,6 @@ 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->guides, g_hash_table_unref);
g_clear_pointer (&self->grid_constraints, g_hash_table_unref);
G_OBJECT_CLASS (gtk_constraint_layout_parent_class)->finalize (gobject);
}
@@ -702,58 +686,6 @@ 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,
@@ -767,15 +699,15 @@ 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;
int value;
solver = gtk_constraint_layout_get_solver (self);
if (solver == NULL)
return;
gtk_constraint_solver_freeze (solver);
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
@@ -785,24 +717,64 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager,
child != NULL;
child = _gtk_widget_get_next_sibling (child))
{
GtkConstraintLayoutChild *info;
GtkRequisition min_req, nat_req;
GtkConstraintVariable *width_var, *height_var;
GtkConstraintRef *constraint;
int min_size = 0, nat_size = 0;
if (!gtk_widget_should_layout (child))
continue;
gtk_widget_get_preferred_size (child, &min_req, &nat_req);
gtk_widget_measure (child, orientation, -1,
&min_size, &nat_size,
NULL, NULL);
info = GTK_CONSTRAINT_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (manager, child));
switch (orientation)
{
case GTK_ORIENTATION_HORIZONTAL:
width_var = get_child_attribute (self, child, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
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);
constraint =
gtk_constraint_solver_add_constraint (solver,
width_var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_new (min_size),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
g_ptr_array_add (size_constraints, constraint);
constraint =
gtk_constraint_solver_add_constraint (solver,
width_var,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_new (nat_size),
GTK_CONSTRAINT_WEIGHT_MEDIUM);
g_ptr_array_add (size_constraints, constraint);
break;
case GTK_ORIENTATION_VERTICAL:
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_size),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
g_ptr_array_add (size_constraints, constraint);
constraint =
gtk_constraint_solver_add_constraint (solver,
height_var,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_new (nat_size),
GTK_CONSTRAINT_WEIGHT_MEDIUM);
g_ptr_array_add (size_constraints, constraint);
break;
default:
break;
}
}
gtk_constraint_solver_thaw (solver);
switch (orientation)
{
case GTK_ORIENTATION_HORIZONTAL:
@@ -821,41 +793,44 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager,
g_assert (size != NULL && opposite_size != NULL);
nat_value = gtk_constraint_variable_get_value (size);
/* We impose a temporary value on the size and opposite size of the
* layout, with a low weight to let the solver settle towards the
* natural state of the system. Once we get the value out, we can
* remove these constraints
*/
gtk_constraint_solver_add_edit_variable (solver, size, GTK_CONSTRAINT_WEIGHT_STRONG * 2);
if (for_size > 0)
gtk_constraint_solver_add_edit_variable (solver, opposite_size, GTK_CONSTRAINT_WEIGHT_STRONG * 2);
gtk_constraint_solver_begin_edit (solver);
gtk_constraint_solver_suggest_value (solver, size, 0.0);
if (for_size > 0)
gtk_constraint_solver_suggest_value (solver, opposite_size, for_size);
gtk_constraint_solver_resolve (solver);
min_value = gtk_constraint_variable_get_value (size);
gtk_constraint_solver_remove_edit_variable (solver, size);
if (for_size > 0)
gtk_constraint_solver_remove_edit_variable (solver, opposite_size);
gtk_constraint_solver_end_edit (solver);
{
gtk_constraint_solver_add_edit_variable (solver, opposite_size, GTK_CONSTRAINT_WEIGHT_MEDIUM * 2.0);
gtk_constraint_solver_begin_edit (solver);
gtk_constraint_solver_suggest_value (solver, opposite_size, for_size);
gtk_constraint_solver_resolve (solver);
gtk_constraint_solver_remove_edit_variable (solver, opposite_size);
gtk_constraint_solver_end_edit (solver);
}
GTK_NOTE (LAYOUT,
g_print ("layout %p %s size: min %d nat %d (for opposite size: %d)\n",
g_print ("layout %p preferred %s size: %.3f (for opposite size: %d)\n",
self,
orientation == GTK_ORIENTATION_HORIZONTAL ? "horizontal" : "vertical",
min_value, nat_value,
gtk_constraint_variable_get_value (size),
for_size));
value = gtk_constraint_variable_get_value (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;
*minimum = value;
if (natural != NULL)
*natural = nat_value;
*natural = value;
}
static void
@@ -870,6 +845,7 @@ 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);
@@ -908,6 +884,61 @@ 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
*/
for (child = _gtk_widget_get_first_child (widget);
child != NULL;
child = _gtk_widget_get_next_sibling (child))
{
GtkConstraintVariable *width_var, *height_var;
GtkRequisition min_req, nat_req;
GtkConstraintRef *constraint;
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);
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);
constraint =
gtk_constraint_solver_add_constraint (solver,
width_var,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_new (nat_req.width),
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);
constraint =
gtk_constraint_solver_add_constraint (solver,
height_var,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_new (nat_req.height),
GTK_CONSTRAINT_WEIGHT_MEDIUM);
g_ptr_array_add (size_constraints, constraint);
}
for (child = _gtk_widget_get_first_child (widget);
child != NULL;
child = _gtk_widget_get_next_sibling (child))
@@ -949,29 +980,15 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager,
child_baseline);
}
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (LAYOUT))
/* The constraints on the children sizes can be removed now */
for (guint i = 0; i < size_constraints->len; i++)
{
GHashTableIter iter;
gpointer key;
g_hash_table_iter_init (&iter, self->guides);
while (g_hash_table_iter_next (&iter, &key, NULL))
{
GtkConstraintGuide *guide = key;
GtkConstraintVariable *var_top, *var_left, *var_width, *var_height;
var_top = gtk_constraint_guide_get_attribute (guide, GTK_CONSTRAINT_ATTRIBUTE_TOP);
var_left = gtk_constraint_guide_get_attribute (guide, GTK_CONSTRAINT_ATTRIBUTE_LEFT);
var_width = gtk_constraint_guide_get_attribute (guide, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
var_height = gtk_constraint_guide_get_attribute (guide, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
g_print ("Allocating guide '%s'[%p] with { .x: %g .y: %g .w: %g .h: %g }\n",
gtk_constraint_guide_get_name (guide), guide,
gtk_constraint_variable_get_value (var_left),
gtk_constraint_variable_get_value (var_top),
gtk_constraint_variable_get_value (var_width),
gtk_constraint_variable_get_value (var_height));
}
GtkConstraintRef *ref = g_ptr_array_index (size_constraints, i);
gtk_constraint_solver_remove_constraint (solver, ref);
}
#endif
g_ptr_array_unref (size_constraints);
/* The allocation stay constraints are not needed any more */
gtk_constraint_solver_remove_constraint (solver, stay_w);
@@ -980,9 +997,6 @@ 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)
{
@@ -1011,13 +1025,6 @@ gtk_constraint_layout_root (GtkLayoutManager *manager)
GtkConstraintGuide *guide = key;
gtk_constraint_guide_update (guide);
}
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
@@ -1045,13 +1052,6 @@ gtk_constraint_layout_unroot (GtkLayoutManager *manager)
gtk_constraint_guide_detach (guide);
}
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;
}
@@ -1089,11 +1089,6 @@ 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);
}
/**
@@ -1213,168 +1208,3 @@ gtk_constraint_layout_remove_guide (GtkConstraintLayout *layout,
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
}
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 *
ensure_variable (GtkConstraintSolver *solver,
const char *name,
int pos,
GPtrArray *vars)
{
GtkConstraintVariable *var;
var = g_ptr_array_index (vars, pos);
if (!var)
{
char *varname;
varname = g_strdup_printf ("%s%d", name, pos);
var = gtk_constraint_solver_create_variable (solver, NULL, varname, 0.0);
g_free (varname);
g_ptr_array_index (vars, pos) = var;
}
return var;
}
static void
add_homogeneous_constraints (GtkConstraintSolver *solver,
const char *name,
GPtrArray *vars,
GPtrArray *refs)
{
int i;
for (i = 2; i < vars->len; i++)
{
GtkConstraintExpressionBuilder builder;
GtkConstraintVariable *var0, *var1, *var2;
GtkConstraintRef *ref;
var0 = ensure_variable (solver, name, i - 2, vars);
var1 = ensure_variable (solver, name, i - 1, vars);
var2 = ensure_variable (solver, name, i, vars);
gtk_constraint_expression_builder_init (&builder, solver);
gtk_constraint_expression_builder_term (&builder, var2);
gtk_constraint_expression_builder_plus (&builder);
gtk_constraint_expression_builder_term (&builder, var0);
gtk_constraint_expression_builder_divide_by (&builder);
gtk_constraint_expression_builder_constant (&builder, 2.0);
ref = gtk_constraint_solver_add_constraint (solver,
var1,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_builder_finish (&builder),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
g_ptr_array_add (refs, ref);
}
}
static void
add_child_constraint (GtkConstraintSolver *solver,
GtkConstraintVariable *var,
int pos,
GPtrArray *vars,
GPtrArray *refs)
{
if (vars->len <= pos)
{
g_ptr_array_set_size (vars, pos + 1);
g_ptr_array_index (vars, pos) = var;
}
else
{
GtkConstraintVariable *var1;
var1 = g_ptr_array_index (vars, pos);
if (var1 == NULL)
{
g_ptr_array_index (vars, pos) = var;
}
else
{
GtkConstraintRef *ref;
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;
GPtrArray *refs;
GPtrArray *rows;
GPtrArray *cols;
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 ();
rows = g_ptr_array_new ();
cols = g_ptr_array_new ();
for (i = 0; i < constraint->children->len; i++)
{
GtkGridConstraintChild *child = g_ptr_array_index (constraint->children, i);
GtkConstraintVariable *var;
var = get_child_attribute (manager, child->child, GTK_CONSTRAINT_ATTRIBUTE_TOP);
add_child_constraint (solver, var, child->top, rows, refs);
var = get_child_attribute (manager, child->child, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM);
add_child_constraint (solver, var, child->bottom, rows, refs);
var = get_child_attribute (manager, child->child, GTK_CONSTRAINT_ATTRIBUTE_LEFT);
add_child_constraint (solver, var, child->left, cols, refs);
var = get_child_attribute (manager, child->child, GTK_CONSTRAINT_ATTRIBUTE_RIGHT);
add_child_constraint (solver, var, child->right, cols, refs);
}
if (constraint->row_homogeneous)
add_homogeneous_constraints (solver, "row", rows, refs);
if (constraint->column_homogeneous)
add_homogeneous_constraints (solver, "col", cols, refs);
gtk_grid_constraint_attach (constraint, solver, refs);
g_ptr_array_unref (rows);
g_ptr_array_unref (cols);
g_ptr_array_unref (refs);
gtk_constraint_solver_thaw (solver);
}
-5
View File
@@ -21,7 +21,6 @@
#include <gtk/gtklayoutmanager.h>
#include <gtk/gtkconstraint.h>
#include <gtk/gtkconstraintguide.h>
#include <gtk/gtkgridconstraint.h>
G_BEGIN_DECLS
@@ -55,10 +54,6 @@ GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_remove_constraint (GtkConstraintLayout *manager,
GtkConstraint *constraint);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_add_grid_constraint (GtkConstraintLayout *manager,
GtkGridConstraint *constraint);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_add_guide (GtkConstraintLayout *manager,
GtkConstraintGuide *guide);
-37
View File
@@ -1,37 +0,0 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
#pragma once
#include "gtkconstraintlayout.h"
#include "gtkconstraintsolverprivate.h"
G_BEGIN_DECLS
GtkConstraintSolver *
gtk_constraint_layout_get_solver (GtkConstraintLayout *layout);
GtkConstraintVariable *
gtk_constraint_layout_get_attribute (GtkConstraintLayout *layout,
GtkConstraintAttribute attr,
const char *prefix,
GtkWidget *widget,
GHashTable *bound_attributes);
G_END_DECLS
+60 -98
View File
@@ -736,12 +736,17 @@ gtk_constraint_solver_optimize (GtkConstraintSolver *self,
self->optimize_count += 1;
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *str = gtk_constraint_variable_to_string (z);
g_message ("optimize: %s", str);
g_free (str);
}
{
char *str;
str = gtk_constraint_variable_to_string (z);
g_debug ("optimize: %s\n", str);
g_free (str);
str = gtk_constraint_solver_to_string (self);
g_debug ("%s\n", str);
g_free (str);
}
#endif
while (TRUE)
@@ -797,28 +802,28 @@ gtk_constraint_solver_optimize (GtkConstraintSolver *self,
if (min_ratio == DBL_MAX)
{
GTK_NOTE (CONSTRAINTS, g_message ("Unbounded objective variable during optimization"));
g_debug ("Unbounded objective variable during optimization");
break;
}
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *entry_s = gtk_constraint_variable_to_string (entry);
char *exit_s = gtk_constraint_variable_to_string (exit);
g_message ("pivot(entry: %s, exit: %s)", entry_s, exit_s);
g_free (entry_s);
g_free (exit_s);
}
{
char *entry_s = gtk_constraint_variable_to_string (entry);
char *exit_s = gtk_constraint_variable_to_string (exit);
g_debug ("pivot(entry: %s, exit: %s)", entry_s, exit_s);
g_free (entry_s);
g_free (exit_s);
}
#endif
gtk_constraint_solver_pivot (self, entry, exit);
}
GTK_NOTE (CONSTRAINTS,
g_message ("solver.optimize.time := %.3f ms (pass: %d)",
(float) (g_get_monotonic_time () - start_time) / 1000.f,
self->optimize_count));
#ifdef G_ENABLE_DEBUG
g_debug ("solver.optimize.time := %.3f ms (pass: %d)",
(float) (g_get_monotonic_time () - start_time) / 1000.f,
self->optimize_count);
#endif
}
/*< private >
@@ -939,6 +944,8 @@ gtk_constraint_solver_new_expression (GtkConstraintSolver *self,
gtk_constraint_expression_set_variable (expr, dummy_var, 1.0);
g_hash_table_insert (self->marker_vars, constraint, dummy_var);
gtk_constraint_variable_unref (dummy_var);
}
else
{
@@ -1049,17 +1056,15 @@ gtk_constraint_solver_dual_optimize (GtkConstraintSolver *self)
}
if (ratio == DBL_MAX)
{
g_critical ("INTERNAL: ratio == DBL_MAX in dual_optimize");
break;
}
g_critical ("INTERNAL: ratio == DBL_MAX in dual_optimize");
gtk_constraint_solver_pivot (self, entry_var, exit_var);
}
GTK_NOTE (CONSTRAINTS,
g_message ("dual_optimize.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f));
#ifdef G_ENABLE_DEBUG
g_debug ("dual_optimize.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f);
#endif
}
static void
@@ -1163,7 +1168,7 @@ gtk_constraint_solver_choose_subject (GtkConstraintSolver *self,
GtkConstraintVariableSet *cset = g_hash_table_lookup (self->columns, t_v);
if (cset == NULL ||
(gtk_constraint_variable_set_is_singleton (cset) &&
(gtk_constraint_variable_set_size (cset) == 1 &&
g_hash_table_contains (self->columns, self->objective)))
{
subject = t_v;
@@ -1200,8 +1205,7 @@ gtk_constraint_solver_choose_subject (GtkConstraintSolver *self,
if (!G_APPROX_VALUE (gtk_constraint_expression_get_constant (expression), 0.0, 0.001))
{
GTK_NOTE (CONSTRAINTS,
g_message ("Unable to satisfy required constraint (choose_subject)"));
g_debug ("Unable to satisfy required constraint (choose_subject)");
return NULL;
}
@@ -1262,17 +1266,14 @@ gtk_constraint_solver_add_with_artificial_variable (GtkConstraintSolver *self,
az_tableau_row = g_hash_table_lookup (self->rows, az);
if (!G_APPROX_VALUE (gtk_constraint_expression_get_constant (az_tableau_row), 0.0, 0.001))
{
char *str = gtk_constraint_expression_to_string (expression);
gtk_constraint_solver_remove_column (self, av);
gtk_constraint_solver_remove_row (self, az, TRUE);
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *str = gtk_constraint_expression_to_string (expression);
g_message ("Unable to satisfy a required constraint (add): %s", str);
g_free (str);
}
#endif
g_debug ("Unable to satisfy a required constraint (add): %s", str);
g_free (str);
return;
}
@@ -1317,14 +1318,15 @@ gtk_constraint_solver_add_constraint_internal (GtkConstraintSolver *self,
&prev_constant);
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *expr_s = gtk_constraint_expression_to_string (expr);
char *ref_s = gtk_constraint_ref_to_string (constraint);
g_message ("Adding constraint '%s' (normalized expression: '%s')", ref_s, expr_s);
g_free (ref_s);
g_free (expr_s);
}
{
char *expr_s = gtk_constraint_expression_to_string (expr);
char *ref_s = gtk_constraint_ref_to_string (constraint);
g_debug ("Adding constraint '%s' (normalized expression: '%s')\n", ref_s, expr_s);
g_free (ref_s);
g_free (expr_s);
}
#endif
if (constraint->is_stay)
@@ -1480,8 +1482,6 @@ gtk_constraint_solver_create_variable (GtkConstraintSolver *self,
{
GtkConstraintVariable *res;
self->var_counter++;
res = gtk_constraint_variable_new (name);
gtk_constraint_variable_set_prefix (res, prefix);
gtk_constraint_variable_set_value (res, value);
@@ -1511,9 +1511,10 @@ gtk_constraint_solver_resolve (GtkConstraintSolver *solver)
gtk_constraint_solver_reset_stay_constants (solver);
GTK_NOTE (CONSTRAINTS,
g_message ("resolve.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f));
#ifdef G_ENABLE_DEBUG
g_debug ("resolve.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f);
#endif
solver->needs_solving = FALSE;
}
@@ -1632,12 +1633,11 @@ gtk_constraint_solver_add_stay_variable (GtkConstraintSolver *self,
self);
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *str = gtk_constraint_expression_to_string (res->expression);
g_message ("Adding stay variable: %s", str);
g_free (str);
}
{
char *str = gtk_constraint_expression_to_string (res->expression);
g_debug ("Adding stay variable: %s", str);
g_free (str);
}
#endif
gtk_constraint_solver_add_constraint_internal (self, res);
@@ -1735,7 +1735,7 @@ gtk_constraint_solver_remove_edit_variable (GtkConstraintSolver *self,
{
char *str = gtk_constraint_variable_to_string (variable);
g_critical ("Unknown edit variable '%s'", str);
g_critical ("Unknown stay variable '%s'", str);
g_free (str);
@@ -1866,7 +1866,7 @@ gtk_constraint_solver_remove_constraint (GtkConstraintSolver *self,
if (exit_var == NULL)
{
if (gtk_constraint_variable_set_is_empty (set))
if (gtk_constraint_variable_set_size (set) == 0)
gtk_constraint_solver_remove_column (self, marker);
else
{
@@ -1972,7 +1972,6 @@ gtk_constraint_solver_suggest_value (GtkConstraintSolver *self,
double value)
{
EditInfo *ei = g_hash_table_lookup (self->edit_var_map, variable);
double delta;
if (ei == NULL)
{
g_critical ("Suggesting value '%g' but variable %p is not editable",
@@ -1988,10 +1987,9 @@ gtk_constraint_solver_suggest_value (GtkConstraintSolver *self,
return;
}
delta = value - ei->prev_constant;
ei->prev_constant = value;
ei->prev_constant = value - ei->prev_constant;
gtk_constraint_solver_delta_edit_constant (self, delta, ei->eplus, ei->eminus);
gtk_constraint_solver_delta_edit_constant (self, ei->prev_constant, ei->eplus, ei->eminus);
}
/*< private >
@@ -2208,39 +2206,3 @@ gtk_constraint_solver_to_string (GtkConstraintSolver *solver)
return g_string_free (buf, FALSE);
}
char *
gtk_constraint_solver_statistics (GtkConstraintSolver *solver)
{
GString *buf = g_string_new (NULL);
g_string_append_printf (buf, "Variables: %d\n", solver->var_counter);
g_string_append_printf (buf, "Slack vars: %d\n", solver->slack_counter);
g_string_append_printf (buf, "Artificial vars: %d\n", solver->artificial_counter);
g_string_append_printf (buf, "Dummy vars: %d\n", solver->dummy_counter);
g_string_append_printf (buf, "Stay vars: %d\n", g_hash_table_size (solver->stay_var_map));
g_string_append_printf (buf, "Optimize count: %d\n", solver->optimize_count);
g_string_append_printf (buf, "Rows: %d\n", g_hash_table_size (solver->rows));
g_string_append_printf (buf, "Columns: %d\n", g_hash_table_size (solver->columns));
if (g_hash_table_size (solver->columns) > 0)
{
GHashTableIter iter;
gpointer val;
double sum = 0;
g_hash_table_iter_init (&iter, solver->columns);
while (g_hash_table_iter_next (&iter, NULL, &val))
{
GtkConstraintVariableSet *set = val;
sum += gtk_constraint_variable_set_size (set);
}
g_string_append_printf (buf, "Avg column size: %g\n", sum / g_hash_table_size (solver->columns));
}
g_string_append_printf (buf, "Infeasible rows: %d\n", solver->infeasible_rows->len);
g_string_append_printf (buf, "External basic variables: %d\n", g_hash_table_size (solver->external_rows));
g_string_append_printf (buf, "External parametric variables: %d\n", g_hash_table_size (solver->external_parametric_vars));
return g_string_free (buf, FALSE);
}
-3
View File
@@ -162,7 +162,4 @@ gtk_constraint_solver_clear (GtkConstraintSolver *solver);
char *
gtk_constraint_solver_to_string (GtkConstraintSolver *solver);
char *
gtk_constraint_solver_statistics (GtkConstraintSolver *solver);
G_END_DECLS
+1 -2
View File
@@ -51,8 +51,7 @@ typedef enum {
GTK_DEBUG_ACTIONS = 1 << 13,
GTK_DEBUG_RESIZE = 1 << 14,
GTK_DEBUG_LAYOUT = 1 << 15,
GTK_DEBUG_SNAPSHOT = 1 << 16,
GTK_DEBUG_CONSTRAINTS = 1 << 17,
GTK_DEBUG_SNAPSHOT = 1 << 16
} GtkDebugFlag;
#ifdef G_ENABLE_DEBUG
-206
View File
@@ -1,206 +0,0 @@
/* gtkgridconstraint.c: Make a grid with constraints
* Copyright 2019 Red Hat, inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
#include "config.h"
#include "gtkgridconstraint.h"
#include "gtkgridconstraintprivate.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
enum {
PROP_ROW_HOMOGENEOUS = 1,
PROP_COLUMN_HOMOGENEOUS,
N_PROPERTIES
};
static GParamSpec *obj_props[N_PROPERTIES];
G_DEFINE_TYPE (GtkGridConstraint, gtk_grid_constraint, G_TYPE_OBJECT)
static void
gtk_constraint_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkGridConstraint *self = GTK_GRID_CONSTRAINT (gobject);
switch (prop_id)
{
case PROP_ROW_HOMOGENEOUS:
self->row_homogeneous = g_value_get_boolean (value);
break;
case PROP_COLUMN_HOMOGENEOUS:
self->column_homogeneous = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_constraint_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkGridConstraint *self = GTK_GRID_CONSTRAINT (gobject);
switch (prop_id)
{
case PROP_ROW_HOMOGENEOUS:
g_value_set_boolean (value, self->row_homogeneous);
break;
case PROP_COLUMN_HOMOGENEOUS:
g_value_set_boolean (value, self->column_homogeneous);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_constraint_finalize (GObject *gobject)
{
GtkGridConstraint *self = GTK_GRID_CONSTRAINT (gobject);
gtk_grid_constraint_detach (self);
g_ptr_array_free (self->children, TRUE);
G_OBJECT_CLASS (gtk_grid_constraint_parent_class)->finalize (gobject);
}
static void
gtk_grid_constraint_class_init (GtkGridConstraintClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gtk_constraint_set_property;
gobject_class->get_property = gtk_constraint_get_property;
gobject_class->finalize = gtk_constraint_finalize;
/**
* GtkGridConstraint:row-homogeneous:
*
* Whether to make all rows the same height.
*/
obj_props[PROP_ROW_HOMOGENEOUS] =
g_param_spec_boolean ("row-homogeneous",
P_("Row homogeneous"),
P_("Row homogeneous"),
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
/**
* GtkGridConstraint:column-homogeneous:
*
* Whether to make all columns the same width.
*/
obj_props[PROP_COLUMN_HOMOGENEOUS] =
g_param_spec_boolean ("column-homogeneous",
P_("Column homogeneous"),
P_("Column homogeneous"),
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPERTIES, obj_props);
}
static void
gtk_grid_constraint_init (GtkGridConstraint *self)
{
self->children = g_ptr_array_new_with_free_func (g_free);
}
GtkGridConstraint *
gtk_grid_constraint_new (void)
{
return g_object_new (GTK_TYPE_GRID_CONSTRAINT, NULL);
}
void
gtk_grid_constraint_add (GtkGridConstraint *self,
GtkWidget *child,
int left,
int right,
int top,
int bottom)
{
GtkGridConstraintChild *data;
g_return_if_fail (GTK_IS_GRID_CONSTRAINT (self));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (left < right);
g_return_if_fail (top < bottom);
g_return_if_fail (self->refs == NULL);
data = g_new0 (GtkGridConstraintChild, 1);
data->child = child;
data->left = left;
data->right = right;
data->top = top;
data->bottom = bottom;
g_ptr_array_add (self->children, data);
}
gboolean
gtk_grid_constraint_is_attached (GtkGridConstraint *self)
{
return self->refs != NULL;
}
void
gtk_grid_constraint_attach (GtkGridConstraint *self,
GtkConstraintSolver *solver,
GPtrArray *refs)
{
g_return_if_fail (self->refs == NULL);
self->solver = solver;
self->refs = g_ptr_array_ref (refs);
}
void gtk_grid_constraint_detach (GtkGridConstraint *self)
{
int i;
if (self->refs == NULL)
return;
for (i = 0; i < self->refs->len; i++)
{
GtkConstraintRef *ref = g_ptr_array_index (self->refs, i);
gtk_constraint_solver_remove_constraint (self->solver, ref);
}
g_clear_pointer (&self->refs, g_ptr_array_unref);
}
-49
View File
@@ -1,49 +0,0 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_GRID_CONSTRAINT_H__
#define __GTK_GRID_CONSTRAINT_H__
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
#define GTK_TYPE_GRID_CONSTRAINT (gtk_grid_constraint_get_type ())
/**
* GtkGridConstraint:
*
* An object used for managing constraints for children in
* a constraints layout that are to be arranged in a grid.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkGridConstraint, gtk_grid_constraint, GTK, GRID_CONSTRAINT, GObject)
GDK_AVAILABLE_IN_ALL
GtkGridConstraint * gtk_grid_constraint_new (void);
GDK_AVAILABLE_IN_ALL
void gtk_grid_constraint_add (GtkGridConstraint *self,
GtkWidget *child,
int left,
int right,
int top,
int bottom);
G_END_DECLS
#endif /* __GTK_GRID_CONSTRAINT_H__ */
-47
View File
@@ -1,47 +0,0 @@
/*
* Copyright 2019 Red Hat, inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
#include "gtkgridconstraint.h"
#include "gtkconstraintsolverprivate.h"
typedef struct {
GtkWidget *child;
int left;
int right;
int top;
int bottom;
} GtkGridConstraintChild;
struct _GtkGridConstraint {
GObject parent;
gboolean row_homogeneous;
gboolean column_homogeneous;
GPtrArray *children;
GtkConstraintSolver *solver;
GPtrArray *refs;
};
gboolean gtk_grid_constraint_is_attached (GtkGridConstraint *constraint);
void gtk_grid_constraint_attach (GtkGridConstraint *constraint,
GtkConstraintSolver *solver,
GPtrArray *refs);
void gtk_grid_constraint_detach (GtkGridConstraint *constraint);
+1 -2
View File
@@ -179,8 +179,7 @@ static const GDebugKey gtk_debug_keys[] = {
{ "actions", GTK_DEBUG_ACTIONS },
{ "resize", GTK_DEBUG_RESIZE },
{ "layout", GTK_DEBUG_LAYOUT },
{ "snapshot", GTK_DEBUG_SNAPSHOT },
{ "constraints", GTK_DEBUG_CONSTRAINTS },
{ "snapshot", GTK_DEBUG_SNAPSHOT }
};
#endif /* G_ENABLE_DEBUG */
-1
View File
@@ -253,7 +253,6 @@ gtk_public_sources = files([
'gtkgesturezoom.c',
'gtkglarea.c',
'gtkgrid.c',
'gtkgridconstraint.c',
'gtkgridlayout.c',
'gtkheaderbar.c',
'gtkicontheme.c',
+10 -11
View File
@@ -211,14 +211,6 @@ drag_begin (GtkGestureDrag *drag,
drag_start_x = start_x;
drag_start_y = start_y;
gtk_widget_queue_draw (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag)));
gtk_constraint_solver_add_edit_variable (solver,
drag_node->x_var,
GTK_CONSTRAINT_WEIGHT_STRONG);
gtk_constraint_solver_add_edit_variable (solver,
drag_node->y_var,
GTK_CONSTRAINT_WEIGHT_STRONG);
gtk_constraint_solver_begin_edit (solver);
}
static void
@@ -243,6 +235,13 @@ drag_update (GtkGestureDrag *drag,
if (!drag_node)
return;
gtk_constraint_solver_add_edit_variable (solver,
drag_node->x_var,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_edit_variable (solver,
drag_node->y_var,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_begin_edit (solver);
gtk_constraint_solver_suggest_value (solver,
drag_node->x_var,
drag_start_x + offset_x);
@@ -253,6 +252,9 @@ drag_update (GtkGestureDrag *drag,
update_tree (tree);
gtk_constraint_solver_remove_edit_variable (solver, drag_node->x_var);
gtk_constraint_solver_remove_edit_variable (solver, drag_node->y_var);
gtk_constraint_solver_end_edit (solver);
gtk_widget_queue_draw (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag)));
}
@@ -265,9 +267,6 @@ drag_end (GtkGestureDrag *drag,
if (!drag_node)
return;
gtk_constraint_solver_remove_edit_variable (solver, drag_node->x_var);
gtk_constraint_solver_remove_edit_variable (solver, drag_node->y_var);
gtk_constraint_solver_end_edit (solver);
drag_node = NULL;
-326
View File
@@ -1,326 +0,0 @@
/* Copyright (C) 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtk/gtk.h>
#define GTK_TYPE_GIZMO (gtk_gizmo_get_type ())
#define GTK_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GIZMO, GtkGizmo))
#define GTK_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GIZMO, GtkGizmoClass))
#define GTK_IS_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GIZMO))
#define GTK_IS_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GIZMO))
#define GTK_GIZMO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GIZMO, GtkGizmoClass))
typedef struct _GtkGizmo GtkGizmo;
struct _GtkGizmo {
GtkWidget parent;
int min_width;
int min_height;
int nat_width;
int nat_height;
int width;
int height;
};
typedef GtkWidgetClass GtkGizmoClass;
G_DEFINE_TYPE (GtkGizmo, gtk_gizmo, GTK_TYPE_WIDGET);
static void
gtk_gizmo_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkGizmo *self = GTK_GIZMO (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum = self->min_width;
*natural = self->nat_width;
}
else
{
*minimum = self->min_height;
*natural = self->nat_height;
}
}
static void
gtk_gizmo_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkGizmo *self = GTK_GIZMO (widget);
self->width = width;
self->height = height;
}
static void
gtk_gizmo_class_init (GtkGizmoClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->measure = gtk_gizmo_measure;
widget_class->size_allocate = gtk_gizmo_size_allocate;
}
static void
gtk_gizmo_init (GtkGizmo *self)
{
}
/* Create a layout with three children
*
* +--------+--------+
* | child1 | child2 |
* +--------+--------+
* | child3 |
* +-----------------+
*
* Verify that
* - the layout has the expected min and nat sizes
* - the children get their >=nat width when the layout does
* - test that allocating the layout larger keeps
* child1 and child2 at the same size
*/
static void
test_simple_layout (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkConstraintLayout *manager;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_widget_set_name (parent, "parent");
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (parent, layout);
manager = GTK_CONSTRAINT_LAYOUT (layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_widget_set_name (GTK_WIDGET (child1), "child1");
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 50;
child1->nat_height = 50;
gtk_widget_set_name (GTK_WIDGET (child2), "child2");
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 50;
child2->nat_height = 50;
gtk_widget_set_name (GTK_WIDGET (child3), "child3");
child3->min_width = 50;
child3->min_height = 10;
child3->nat_width = 50;
child3->nat_height = 50;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
child1,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child2,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child3,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
child1,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child2,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child3,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
#if 0
gtk_widget_show (window);
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
gtk_main ();
#endif
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 50);
g_assert_cmpint (natural, ==, 100);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 40);
g_assert_cmpint (natural, ==, 100);
gtk_layout_manager_allocate (layout, parent, 100, 100, 0);
g_assert_cmpint (child1->width, ==, 50);
g_assert_cmpint (child2->width, ==, 50);
g_assert_cmpint (child3->width, ==, 100);
g_assert_cmpint (child1->height, ==, 50);
g_assert_cmpint (child2->height, ==, 50);
g_assert_cmpint (child3->height, ==, 50);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_destroy (parent);
}
int
main (int argc,
char *argv[])
{
gtk_test_init (&argc, &argv);
g_test_add_func ("/constraint-layout/simple", test_simple_layout);
return g_test_run();
}
-12
View File
@@ -254,27 +254,15 @@ constraint_solver_edit_var_suggest (void)
gtk_constraint_solver_suggest_value (solver, a, 2.0);
gtk_constraint_solver_resolve (solver);
g_test_message ("Check values after first edit");
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 2.0, 0.001);
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 2.0, 0.001);
gtk_constraint_solver_suggest_value (solver, a, 10.0);
gtk_constraint_solver_resolve (solver);
g_test_message ("Check values after second edit");
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 10.0, 0.001);
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 10.0, 0.001);
gtk_constraint_solver_suggest_value (solver, a, 12.0);
gtk_constraint_solver_resolve (solver);
g_test_message ("Check values after third edit");
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 12.0, 0.001);
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 12.0, 0.001);
gtk_constraint_variable_unref (a);
gtk_constraint_variable_unref (b);
-1
View File
@@ -17,7 +17,6 @@ tests = [
['builderparser'],
['cellarea'],
['check-icon-names'],
['constraint-layout'],
['constraint-solver', [
'../../gtk/gtkconstraintsolver.c',
'../../gtk/gtkconstraintexpression.c',