Compare commits
11 Commits
constraint
...
repeat-edi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
463dffe48d | ||
|
|
d42c26b117 | ||
|
|
12d45c01b0 | ||
|
|
fc3f4aafe5 | ||
|
|
ffd8b19a87 | ||
|
|
20c4a4bb21 | ||
|
|
f8647b02eb | ||
|
|
4b11e73be6 | ||
|
|
4de3e99fbe | ||
|
|
c81e04755d | ||
|
|
e4466dd4fe |
@@ -1,4 +1,4 @@
|
||||
/* Constraints
|
||||
/* Constraints/Simple
|
||||
*
|
||||
* GtkConstraintLayout provides a layout manager that uses relations
|
||||
* between widgets (also known as "constraints") to compute the position
|
||||
@@ -74,6 +74,22 @@ static void
|
||||
build_constraints (SimpleGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE,
|
||||
"min-width", 10,
|
||||
"min-height", 10,
|
||||
"nat-width", 100,
|
||||
"nat-height", 10,
|
||||
NULL);
|
||||
gtk_constraint_layout_add_guide (manager, guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_LE,
|
||||
200.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
@@ -94,12 +110,21 @@ build_constraints (SimpleGrid *self,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-12.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
|
||||
245
demos/gtk-demo/constraints2.c
Normal file
245
demos/gtk-demo/constraints2.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* Constraints/Interactive
|
||||
*
|
||||
* Demonstrate how constraints can be updates during
|
||||
* user interaction.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (InteractiveGrid, interactive_grid, INTERACTIVE, GRID, GtkWidget)
|
||||
|
||||
struct _InteractiveGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
GtkConstraintGuide *guide;
|
||||
GtkConstraint *constraint;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (InteractiveGrid, interactive_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
interactive_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
InteractiveGrid *self = INTERACTIVE_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);
|
||||
|
||||
GTK_WIDGET_CLASS (interactive_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_class_init (InteractiveGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = interactive_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
build_constraints (InteractiveGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
self->guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
|
||||
gtk_constraint_layout_add_guide (manager, self->guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
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,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
drag_cb (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
InteractiveGrid *self)
|
||||
{
|
||||
GtkConstraintLayout *layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (self)));
|
||||
double x, y;
|
||||
|
||||
if (self->constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (layout, self->constraint);
|
||||
g_clear_object (&self->constraint);
|
||||
}
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
self->constraint = gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x + offset_x,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (layout, g_object_ref (self->constraint));
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_init (InteractiveGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkGesture *drag;
|
||||
|
||||
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");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints2 (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 (interactive_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;
|
||||
}
|
||||
@@ -151,6 +151,7 @@
|
||||
<file>colorsel.c</file>
|
||||
<file>combobox.c</file>
|
||||
<file>constraints.c</file>
|
||||
<file>constraints2.c</file>
|
||||
<file>css_accordion.c</file>
|
||||
<file>css_basics.c</file>
|
||||
<file>css_blendmodes.c</file>
|
||||
|
||||
@@ -9,6 +9,7 @@ demos = files([
|
||||
'colorsel.c',
|
||||
'combobox.c',
|
||||
'constraints.c',
|
||||
'constraints2.c',
|
||||
'css_accordion.c',
|
||||
'css_basics.c',
|
||||
'css_blendmodes.c',
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
#include "gtkwidget.h"
|
||||
|
||||
enum {
|
||||
PROP_TARGET_WIDGET = 1,
|
||||
PROP_TARGET = 1,
|
||||
PROP_TARGET_ATTRIBUTE,
|
||||
PROP_RELATION,
|
||||
PROP_SOURCE_WIDGET,
|
||||
PROP_SOURCE,
|
||||
PROP_SOURCE_ATTRIBUTE,
|
||||
PROP_MULTIPLIER,
|
||||
PROP_CONSTANT,
|
||||
@@ -72,8 +72,8 @@ gtk_constraint_set_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TARGET_WIDGET:
|
||||
self->target_widget = g_value_get_object (value);
|
||||
case PROP_TARGET:
|
||||
self->target = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_TARGET_ATTRIBUTE:
|
||||
@@ -84,8 +84,8 @@ gtk_constraint_set_property (GObject *gobject,
|
||||
self->relation = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_WIDGET:
|
||||
self->source_widget = g_value_get_object (value);
|
||||
case PROP_SOURCE:
|
||||
self->source = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_ATTRIBUTE:
|
||||
@@ -120,8 +120,8 @@ gtk_constraint_get_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TARGET_WIDGET:
|
||||
g_value_set_object (value, self->target_widget);
|
||||
case PROP_TARGET:
|
||||
g_value_set_object (value, self->target);
|
||||
break;
|
||||
|
||||
case PROP_TARGET_ATTRIBUTE:
|
||||
@@ -132,8 +132,8 @@ gtk_constraint_get_property (GObject *gobject,
|
||||
g_value_set_enum (value, self->relation);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_WIDGET:
|
||||
g_value_set_object (value, self->source_widget);
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, self->source);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_ATTRIBUTE:
|
||||
@@ -178,31 +178,31 @@ gtk_constraint_class_init (GtkConstraintClass *klass)
|
||||
gobject_class->finalize = gtk_constraint_finalize;
|
||||
|
||||
/**
|
||||
* GtkConstraint:target-widget:
|
||||
* GtkConstraint:target:
|
||||
*
|
||||
* The target widget of the constraint.
|
||||
* The target of the constraint.
|
||||
*
|
||||
* The constraint will set the #GtkConstraint:target-attribute of the
|
||||
* target widget using the #GtkConstraint:source-attribute of the source
|
||||
* target using the #GtkConstraint:source-attribute of the source
|
||||
* widget.
|
||||
*/
|
||||
obj_props[PROP_TARGET_WIDGET] =
|
||||
g_param_spec_object ("target-widget",
|
||||
P_("Target Widget"),
|
||||
P_("The target widget of the constraint"),
|
||||
GTK_TYPE_WIDGET,
|
||||
obj_props[PROP_TARGET] =
|
||||
g_param_spec_object ("target",
|
||||
P_("Target"),
|
||||
P_("The target of the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_TARGET,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:target-attribute:
|
||||
*
|
||||
* The attribute of the #GtkConstraint:target-widget set by the constraint.
|
||||
* The attribute of the #GtkConstraint:target set by the constraint.
|
||||
*/
|
||||
obj_props[PROP_TARGET_ATTRIBUTE] =
|
||||
g_param_spec_enum ("target-attribute",
|
||||
P_("Target Attribute"),
|
||||
P_("The attribute of the target widget set by the constraint"),
|
||||
P_("The attribute of the target set by the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_ATTRIBUTE,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_NONE,
|
||||
G_PARAM_READWRITE |
|
||||
@@ -223,26 +223,25 @@ gtk_constraint_class_init (GtkConstraintClass *klass)
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:source-widget:
|
||||
* GtkConstraint:source:
|
||||
*
|
||||
* The source widget of the constraint.
|
||||
* The source of the constraint.
|
||||
*
|
||||
* The constraint will set the #GtkConstraint:target-attribute of the
|
||||
* target widget using the #GtkConstraint:source-attribute of the source
|
||||
* widget.
|
||||
* target using the #GtkConstraint:source-attribute of the source.
|
||||
*/
|
||||
obj_props[PROP_SOURCE_WIDGET] =
|
||||
g_param_spec_object ("source-widget",
|
||||
P_("Source Widget"),
|
||||
P_("The source widget of the constraint"),
|
||||
GTK_TYPE_WIDGET,
|
||||
obj_props[PROP_SOURCE] =
|
||||
g_param_spec_object ("source",
|
||||
P_("Source"),
|
||||
P_("The source of the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_TARGET,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:source-attribute:
|
||||
*
|
||||
* The attribute of the #GtkConstraint:source-widget read by the constraint.
|
||||
* The attribute of the #GtkConstraint:source read by the constraint.
|
||||
*/
|
||||
obj_props[PROP_SOURCE_ATTRIBUTE] =
|
||||
g_param_spec_enum ("source-attribute",
|
||||
@@ -316,39 +315,38 @@ gtk_constraint_init (GtkConstraint *self)
|
||||
|
||||
/**
|
||||
* gtk_constraint_new:
|
||||
* @target_widget: (nullable): a #GtkWidget
|
||||
* @target_attribute: the attribute of @target_widget to be set
|
||||
* @target: (nullable) (type GtkConstraintTarget): a #GtkConstraintTarget
|
||||
* @target_attribute: the attribute of @target to be set
|
||||
* @relation: the relation equivalence between @target_attribute and @source_attribute
|
||||
* @source_widget: (nullable): a #GtkWidget
|
||||
* @source_attribute: the attribute of @source_widget to be read
|
||||
* @source: (nullable) (type GtkConstraintTarget): a #GtkConstraintTarget
|
||||
* @source_attribute: the attribute of @source to be read
|
||||
* @multiplier: a multiplication factor to be applied to @source_attribute
|
||||
* @constant: a constant factor to be added to @source_attribute
|
||||
* @strength: the strength of the constraint
|
||||
*
|
||||
* Creates a new #GtkConstraint representing a relation between a layout
|
||||
* attribute on a source #GtkWidget and a layout attribute on a target
|
||||
* #GtkWidget.
|
||||
* attribute on a source and a layout attribute on a target.
|
||||
*
|
||||
* Returns: the newly created #GtkConstraint
|
||||
*/
|
||||
GtkConstraint *
|
||||
gtk_constraint_new (GtkWidget *target_widget,
|
||||
gtk_constraint_new (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
GtkWidget *source_widget,
|
||||
gpointer source,
|
||||
GtkConstraintAttribute source_attribute,
|
||||
double multiplier,
|
||||
double constant,
|
||||
int strength)
|
||||
{
|
||||
g_return_val_if_fail (target_widget == NULL || GTK_IS_WIDGET (target_widget), NULL);
|
||||
g_return_val_if_fail (source_widget == NULL || GTK_IS_WIDGET (source_widget), NULL);
|
||||
g_return_val_if_fail (target == NULL || GTK_IS_CONSTRAINT_TARGET (target), NULL);
|
||||
g_return_val_if_fail (source == NULL || GTK_IS_CONSTRAINT_TARGET (source), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_CONSTRAINT,
|
||||
"target-widget", target_widget,
|
||||
"target", target,
|
||||
"target-attribute", target_attribute,
|
||||
"relation", relation,
|
||||
"source-widget", source_widget,
|
||||
"source", source,
|
||||
"source-attribute", source_attribute,
|
||||
"multiplier", multiplier,
|
||||
"constant", constant,
|
||||
@@ -358,28 +356,28 @@ gtk_constraint_new (GtkWidget *target_widget,
|
||||
|
||||
/**
|
||||
* gtk_constraint_new_constant:
|
||||
* @target_widget: (nullable): a #GtkWidget
|
||||
* @target_attribute: the attribute of @target_widget to be set
|
||||
* @target: (nullable) (type GtkConstraintTarget): a #GtkConstraintTarget
|
||||
* @target_attribute: the attribute of @target to be set
|
||||
* @relation: the relation equivalence between @target_attribute and @constant
|
||||
* @constant: a constant factor to be set on @target_attribute
|
||||
* @strength: the strength of the constraint
|
||||
*
|
||||
* Creates a new #GtkConstraint representing a relation between a layout
|
||||
* attribute on a target #GtkWidget and a constant value.
|
||||
* attribute on a target and a constant value.
|
||||
*
|
||||
* Returns: the newly created #GtkConstraint
|
||||
*/
|
||||
GtkConstraint *
|
||||
gtk_constraint_new_constant (GtkWidget *target_widget,
|
||||
gtk_constraint_new_constant (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
double constant,
|
||||
int strength)
|
||||
{
|
||||
g_return_val_if_fail (target_widget == NULL || GTK_IS_WIDGET (target_widget), NULL);
|
||||
g_return_val_if_fail (target == NULL || GTK_IS_CONSTRAINT_TARGET (target), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_CONSTRAINT,
|
||||
"target-widget", target_widget,
|
||||
"target", target,
|
||||
"target-attribute", target_attribute,
|
||||
"relation", relation,
|
||||
"source-attribute", GTK_CONSTRAINT_ATTRIBUTE_NONE,
|
||||
@@ -401,7 +399,18 @@ gtk_constraint_get_target_widget (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->target_widget;
|
||||
if (GTK_IS_WIDGET (constraint->target))
|
||||
return GTK_WIDGET (constraint->target);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkConstraintTarget *
|
||||
gtk_constraint_get_target (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->target;
|
||||
}
|
||||
|
||||
GtkConstraintAttribute
|
||||
@@ -425,7 +434,18 @@ gtk_constraint_get_source_widget (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->source_widget;
|
||||
if (GTK_IS_WIDGET (constraint->source))
|
||||
return GTK_WIDGET (constraint->source);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkConstraintTarget *
|
||||
gtk_constraint_get_source (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->source;
|
||||
}
|
||||
|
||||
GtkConstraintAttribute
|
||||
@@ -552,7 +572,7 @@ gtk_constraint_is_constant (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), FALSE);
|
||||
|
||||
return constraint->source_widget == NULL &&
|
||||
return constraint->source == NULL &&
|
||||
constraint->source_attribute == GTK_CONSTRAINT_ATTRIBUTE_NONE;
|
||||
}
|
||||
|
||||
@@ -581,3 +601,17 @@ gtk_constraint_detach (GtkConstraint *constraint)
|
||||
constraint->constraint_ref = NULL;
|
||||
constraint->solver = NULL;
|
||||
}
|
||||
|
||||
typedef struct _GtkConstraintTargetInterface GtkConstraintTargetInterface;
|
||||
|
||||
struct _GtkConstraintTargetInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
};
|
||||
|
||||
G_DEFINE_INTERFACE (GtkConstraintTarget, gtk_constraint_target, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_constraint_target_default_init (GtkConstraintTargetInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,6 +24,21 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkConstraintTarget GtkConstraintTarget;
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT_TARGET (gtk_constraint_target_get_type ())
|
||||
|
||||
/**
|
||||
* GtkConstraintTarget:
|
||||
*
|
||||
* The GtkConstraintTarget interface is implemented by objects that
|
||||
* can be used as source or target in #GtkConstraints. Besides
|
||||
* #GtkWidget, it is also implemented by #GtkConstraintGuide.
|
||||
*/
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_INTERFACE (GtkConstraintTarget, gtk_constraint_target, GTK, CONSTRAINT_TARGET, GObject)
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT (gtk_constraint_get_type ())
|
||||
|
||||
/**
|
||||
@@ -43,16 +58,16 @@ GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraint, gtk_constraint, GTK, CONSTRAINT, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraint * gtk_constraint_new (GtkWidget *target_widget,
|
||||
GtkConstraint * gtk_constraint_new (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
GtkWidget *source_widget,
|
||||
gpointer source,
|
||||
GtkConstraintAttribute source_attribute,
|
||||
double multiplier,
|
||||
double constant,
|
||||
int strength);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraint * gtk_constraint_new_constant (GtkWidget *target_widget,
|
||||
GtkConstraint * gtk_constraint_new_constant (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
double constant,
|
||||
@@ -61,10 +76,14 @@ GtkConstraint * gtk_constraint_new_constant (GtkWidget
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_constraint_get_target_widget (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintTarget * gtk_constraint_get_target (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintAttribute gtk_constraint_get_target_attribute (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_constraint_get_source_widget (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintTarget * gtk_constraint_get_source (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintAttribute gtk_constraint_get_source_attribute (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintRelation gtk_constraint_get_relation (GtkConstraint *constraint);
|
||||
|
||||
@@ -72,16 +72,38 @@
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
struct _GtkConstraintLayoutChild
|
||||
typedef struct
|
||||
{
|
||||
GtkLayoutChild parent_instance;
|
||||
|
||||
/* 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
|
||||
* to be freed.
|
||||
*/
|
||||
GHashTable *bound_attributes;
|
||||
} ConstraintSolverChildData;
|
||||
|
||||
struct _GtkConstraintLayoutChild
|
||||
{
|
||||
GtkLayoutChild parent_instance;
|
||||
|
||||
ConstraintSolverChildData data;
|
||||
};
|
||||
|
||||
struct _GtkConstraintGuide
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
int min_width;
|
||||
int min_height;
|
||||
int nat_width;
|
||||
int nat_height;
|
||||
|
||||
GtkConstraintLayout *layout;
|
||||
|
||||
ConstraintSolverChildData data;
|
||||
|
||||
GtkConstraintRef *width_constraint[2];
|
||||
GtkConstraintRef *height_constraint[2];
|
||||
};
|
||||
|
||||
struct _GtkConstraintLayout
|
||||
@@ -105,6 +127,9 @@ struct _GtkConstraintLayout
|
||||
* parent widget, using the public API objects.
|
||||
*/
|
||||
GHashTable *constraints;
|
||||
|
||||
/* HashSet<GtkConstraintGuide> */
|
||||
GHashTable *guides;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK_TYPE_LAYOUT_CHILD)
|
||||
@@ -154,44 +179,20 @@ get_attribute_name (GtkConstraintAttribute attr)
|
||||
}
|
||||
|
||||
static GtkConstraintVariable *
|
||||
get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
GtkConstraintSolver *solver,
|
||||
GtkWidget *widget,
|
||||
GtkConstraintAttribute attr)
|
||||
get_attribute (ConstraintSolverChildData *self,
|
||||
GtkConstraintSolver *solver,
|
||||
const char *prefix,
|
||||
GtkConstraintAttribute attr)
|
||||
{
|
||||
GtkTextDirection text_dir;
|
||||
const char *attr_name;
|
||||
GtkConstraintVariable *res;
|
||||
|
||||
g_assert (attr != GTK_CONSTRAINT_ATTRIBUTE_NONE);
|
||||
|
||||
/* Resolve the start/end attributes depending on the layout's text direction */
|
||||
if (attr == GTK_CONSTRAINT_ATTRIBUTE_START)
|
||||
{
|
||||
text_dir = gtk_widget_get_direction (widget);
|
||||
if (text_dir == GTK_TEXT_DIR_RTL)
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
|
||||
else
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_LEFT;
|
||||
}
|
||||
else if (attr == GTK_CONSTRAINT_ATTRIBUTE_END)
|
||||
{
|
||||
text_dir = gtk_widget_get_direction (widget);
|
||||
if (text_dir == GTK_TEXT_DIR_RTL)
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_LEFT;
|
||||
else
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
|
||||
}
|
||||
|
||||
attr_name = get_attribute_name (attr);
|
||||
res = g_hash_table_lookup (self->bound_attributes, attr_name);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
|
||||
res = gtk_constraint_solver_create_variable (solver,
|
||||
gtk_widget_get_name (widget),
|
||||
attr_name,
|
||||
0.0);
|
||||
res = gtk_constraint_solver_create_variable (solver, prefix, attr_name, 0.0);
|
||||
g_hash_table_insert (self->bound_attributes, (gpointer) attr_name, res);
|
||||
|
||||
/* Some attributes are really constraints computed from other
|
||||
@@ -207,8 +208,8 @@ get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
GtkConstraintVariable *left, *width;
|
||||
GtkConstraintExpression *expr;
|
||||
|
||||
left = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_LEFT);
|
||||
width = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
left = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_LEFT);
|
||||
width = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, left);
|
||||
@@ -229,8 +230,8 @@ get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
GtkConstraintVariable *top, *height;
|
||||
GtkConstraintExpression *expr;
|
||||
|
||||
top = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_TOP);
|
||||
height = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
top = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_TOP);
|
||||
height = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, top);
|
||||
@@ -251,8 +252,8 @@ get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
GtkConstraintVariable *left, *width;
|
||||
GtkConstraintExpression *expr;
|
||||
|
||||
left = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_LEFT);
|
||||
width = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
left = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_LEFT);
|
||||
width = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, width);
|
||||
@@ -275,8 +276,8 @@ get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
GtkConstraintVariable *top, *height;
|
||||
GtkConstraintExpression *expr;
|
||||
|
||||
top = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_TOP);
|
||||
height = get_child_attribute (self, solver, widget, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
top = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_TOP);
|
||||
height = get_attribute (self, solver, prefix, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, height);
|
||||
@@ -325,12 +326,81 @@ get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
return res;
|
||||
}
|
||||
|
||||
static GtkConstraintAttribute
|
||||
resolve_direction (GtkConstraintAttribute attr,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkTextDirection text_dir;
|
||||
|
||||
/* Resolve the start/end attributes depending on the layout's text direction */
|
||||
|
||||
if (widget)
|
||||
text_dir = gtk_widget_get_direction (widget);
|
||||
else
|
||||
text_dir = GTK_TEXT_DIR_LTR;
|
||||
|
||||
if (attr == GTK_CONSTRAINT_ATTRIBUTE_START)
|
||||
{
|
||||
if (text_dir == GTK_TEXT_DIR_RTL)
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
|
||||
else
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_LEFT;
|
||||
}
|
||||
else if (attr == GTK_CONSTRAINT_ATTRIBUTE_END)
|
||||
{
|
||||
if (text_dir == GTK_TEXT_DIR_RTL)
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_LEFT;
|
||||
else
|
||||
attr = GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
static GtkConstraintVariable *
|
||||
get_child_attribute (GtkConstraintLayoutChild *self,
|
||||
GtkConstraintSolver *solver,
|
||||
GtkWidget *widget,
|
||||
GtkConstraintAttribute attr)
|
||||
{
|
||||
const char *prefix = gtk_widget_get_name (widget);
|
||||
|
||||
attr = resolve_direction (attr, widget);
|
||||
|
||||
return get_attribute (&self->data, solver, prefix, attr);
|
||||
}
|
||||
|
||||
static GtkConstraintVariable *
|
||||
get_guide_attribute (GtkConstraintLayout *layout,
|
||||
GtkConstraintGuide *guide,
|
||||
GtkConstraintSolver *solver,
|
||||
GtkConstraintAttribute attr)
|
||||
{
|
||||
GtkLayoutManager *manager = GTK_LAYOUT_MANAGER (layout);
|
||||
GtkWidget *widget = gtk_layout_manager_get_widget (manager);
|
||||
|
||||
attr = resolve_direction (attr, widget);
|
||||
|
||||
return get_attribute (&guide->data, solver, "guide", attr);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_constraint_solver_data (GtkConstraintSolver *solver,
|
||||
ConstraintSolverChildData *data)
|
||||
{
|
||||
g_clear_pointer (&data->bound_attributes, g_hash_table_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_layout_child_finalize (GObject *gobject)
|
||||
{
|
||||
GtkConstraintLayoutChild *self = GTK_CONSTRAINT_LAYOUT_CHILD (gobject);
|
||||
GtkLayoutManager *manager;
|
||||
GtkConstraintSolver *solver;
|
||||
|
||||
g_clear_pointer (&self->bound_attributes, g_hash_table_unref);
|
||||
manager = gtk_layout_child_get_layout_manager (GTK_LAYOUT_CHILD (self));
|
||||
solver = gtk_constraint_layout_get_solver (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
clear_constraint_solver_data (solver, &self->data);
|
||||
|
||||
G_OBJECT_CLASS (gtk_constraint_layout_child_parent_class)->finalize (gobject);
|
||||
}
|
||||
@@ -346,7 +416,7 @@ gtk_constraint_layout_child_class_init (GtkConstraintLayoutChildClass *klass)
|
||||
static void
|
||||
gtk_constraint_layout_child_init (GtkConstraintLayoutChild *self)
|
||||
{
|
||||
self->bound_attributes =
|
||||
self->data.bound_attributes =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL,
|
||||
(GDestroyNotify) gtk_constraint_variable_unref);
|
||||
@@ -361,6 +431,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->guides, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_constraint_layout_parent_class)->finalize (gobject);
|
||||
}
|
||||
@@ -553,7 +624,7 @@ layout_add_constraint (GtkConstraintLayout *self,
|
||||
GtkConstraintExpression *expr;
|
||||
GtkConstraintSolver *solver;
|
||||
GtkConstraintAttribute attr;
|
||||
GtkWidget *target_widget, *source_widget;
|
||||
GtkConstraintTarget *target, *source;
|
||||
GtkWidget *layout_widget;
|
||||
|
||||
if (gtk_constraint_is_attached (constraint))
|
||||
@@ -572,25 +643,33 @@ layout_add_constraint (GtkConstraintLayout *self,
|
||||
return;
|
||||
|
||||
attr = gtk_constraint_get_target_attribute (constraint);
|
||||
target_widget = gtk_constraint_get_target_widget (constraint);
|
||||
if (target_widget == NULL || target_widget == layout_widget)
|
||||
target = gtk_constraint_get_target (constraint);
|
||||
if (target == NULL || target == GTK_CONSTRAINT_TARGET (layout_widget))
|
||||
{
|
||||
/* A NULL target widget is assumed to be referring to the layout itself */
|
||||
target_attr = get_layout_attribute (self, layout_widget, attr);
|
||||
}
|
||||
else if (gtk_widget_get_parent (target_widget) == layout_widget)
|
||||
else if (GTK_IS_WIDGET (target) &&
|
||||
gtk_widget_get_parent (GTK_WIDGET (target)) == layout_widget)
|
||||
{
|
||||
GtkLayoutChild *child_info;
|
||||
|
||||
child_info = gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), target_widget);
|
||||
child_info = gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), GTK_WIDGET (target));
|
||||
target_attr = get_child_attribute (GTK_CONSTRAINT_LAYOUT_CHILD (child_info),
|
||||
solver,
|
||||
target_widget,
|
||||
GTK_WIDGET (target),
|
||||
attr);
|
||||
}
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (target))
|
||||
{
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide = (GtkConstraintGuide*)g_hash_table_lookup (self->guides, target);
|
||||
target_attr = get_guide_attribute (self, guide, solver, attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical ("Unknown target widget '%s'", gtk_widget_get_name (target_widget));
|
||||
g_critical ("Unknown target widget '%p'", target);
|
||||
target_attr = NULL;
|
||||
}
|
||||
|
||||
@@ -598,7 +677,7 @@ layout_add_constraint (GtkConstraintLayout *self,
|
||||
return;
|
||||
|
||||
attr = gtk_constraint_get_source_attribute (constraint);
|
||||
source_widget = gtk_constraint_get_source_widget (constraint);
|
||||
source = gtk_constraint_get_source (constraint);
|
||||
|
||||
/* The constraint is a constant */
|
||||
if (attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)
|
||||
@@ -607,23 +686,31 @@ layout_add_constraint (GtkConstraintLayout *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (source_widget == NULL || source_widget == layout_widget)
|
||||
if (source == NULL || source == GTK_CONSTRAINT_TARGET (layout_widget))
|
||||
{
|
||||
source_attr = get_layout_attribute (self, layout_widget, attr);
|
||||
}
|
||||
else if (gtk_widget_get_parent (source_widget) == layout_widget)
|
||||
else if (GTK_IS_WIDGET (source) &&
|
||||
gtk_widget_get_parent (GTK_WIDGET (source)) == layout_widget)
|
||||
{
|
||||
GtkLayoutChild *child_info;
|
||||
|
||||
child_info = gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), source_widget);
|
||||
child_info = gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), GTK_WIDGET (source));
|
||||
source_attr = get_child_attribute (GTK_CONSTRAINT_LAYOUT_CHILD (child_info),
|
||||
solver,
|
||||
source_widget,
|
||||
GTK_WIDGET (source),
|
||||
attr);
|
||||
}
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (source))
|
||||
{
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide = (GtkConstraintGuide*)g_hash_table_lookup (self->guides, source);
|
||||
source_attr = get_guide_attribute (self, guide, solver, attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical ("Unknown source widget '%s'", gtk_widget_get_name (source_widget));
|
||||
g_critical ("Unknown source widget '%p'", source);
|
||||
source_attr = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -693,57 +780,47 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager,
|
||||
|
||||
child_info = GTK_CONSTRAINT_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (manager, child));
|
||||
|
||||
gtk_widget_measure (child, orientation, for_size,
|
||||
gtk_widget_measure (child, orientation, -1,
|
||||
&min_size, &nat_size,
|
||||
NULL, NULL);
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case GTK_ORIENTATION_HORIZONTAL:
|
||||
width_var = get_child_attribute (child_info, solver, child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
width_var = get_child_attribute (child_info, solver, child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
|
||||
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_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;
|
||||
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);
|
||||
|
||||
case GTK_ORIENTATION_VERTICAL:
|
||||
height_var = get_child_attribute (child_info, solver, child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
height_var = get_child_attribute (child_info, solver, 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_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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
switch (orientation)
|
||||
@@ -769,15 +846,22 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager,
|
||||
* 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_WEAK + 1);
|
||||
gtk_constraint_solver_add_edit_variable (solver, opposite_size, GTK_CONSTRAINT_WEIGHT_WEAK + 2);
|
||||
if (for_size > 0)
|
||||
{
|
||||
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_begin_edit (solver);
|
||||
value = gtk_constraint_variable_get_value (size);
|
||||
|
||||
gtk_constraint_solver_suggest_value (solver, size, 0.0);
|
||||
gtk_constraint_solver_suggest_value (solver, opposite_size, for_size >= 0 ? for_size : 0.0);
|
||||
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
gtk_constraint_solver_remove_edit_variable (solver, opposite_size);
|
||||
gtk_constraint_solver_end_edit (solver);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = gtk_constraint_variable_get_value (size);
|
||||
}
|
||||
|
||||
GTK_NOTE (LAYOUT,
|
||||
g_print ("layout %p preferred %s size: %.3f (for opposite size: %d)\n",
|
||||
@@ -786,13 +870,6 @@ gtk_constraint_layout_measure (GtkLayoutManager *manager,
|
||||
gtk_constraint_variable_get_value (size),
|
||||
for_size));
|
||||
|
||||
value = gtk_constraint_variable_get_value (size);
|
||||
|
||||
gtk_constraint_solver_remove_edit_variable (solver, size);
|
||||
gtk_constraint_solver_remove_edit_variable (solver, opposite_size);
|
||||
|
||||
gtk_constraint_solver_end_edit (solver);
|
||||
|
||||
for (guint i = 0; i < size_constraints->len; i++)
|
||||
{
|
||||
GtkConstraintRef *ref = g_ptr_array_index (size_constraints, i);
|
||||
@@ -881,7 +958,6 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager,
|
||||
|
||||
gtk_widget_get_preferred_size (child, &min_req, &nat_req);
|
||||
|
||||
|
||||
width_var = get_child_attribute (child_info, solver, child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
|
||||
@@ -982,6 +1058,11 @@ gtk_constraint_layout_allocate (GtkLayoutManager *manager,
|
||||
gtk_constraint_solver_remove_constraint (solver, stay_l);
|
||||
}
|
||||
|
||||
static void update_min_width (GtkConstraintGuide *guide);
|
||||
static void update_nat_width (GtkConstraintGuide *guide);
|
||||
static void update_min_height (GtkConstraintGuide *guide);
|
||||
static void update_nat_height (GtkConstraintGuide *guide);
|
||||
|
||||
static void
|
||||
gtk_constraint_layout_root (GtkLayoutManager *manager)
|
||||
{
|
||||
@@ -1001,9 +1082,18 @@ 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->guides);
|
||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||
{
|
||||
GtkConstraintGuide *guide = key;
|
||||
update_min_width (guide);
|
||||
update_nat_width (guide);
|
||||
update_min_height (guide);
|
||||
update_nat_height (guide);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1021,7 +1111,6 @@ gtk_constraint_layout_unroot (GtkLayoutManager *manager)
|
||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||
{
|
||||
GtkConstraint *constraint = key;
|
||||
|
||||
gtk_constraint_detach (constraint);
|
||||
}
|
||||
|
||||
@@ -1057,6 +1146,11 @@ gtk_constraint_layout_init (GtkConstraintLayout *self)
|
||||
g_hash_table_new_full (NULL, NULL,
|
||||
(GDestroyNotify) g_object_unref,
|
||||
NULL);
|
||||
|
||||
self->guides =
|
||||
g_hash_table_new_full (NULL, NULL,
|
||||
(GDestroyNotify) g_object_unref,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1079,7 +1173,7 @@ gtk_constraint_layout_new (void)
|
||||
*
|
||||
* Adds a #GtkConstraint to the layout manager.
|
||||
*
|
||||
* The #GtkConstraint:source-widget and #GtkConstraint:target-widget
|
||||
* The #GtkConstraint:source and #GtkConstraint:target
|
||||
* properties of @constraint can be:
|
||||
*
|
||||
* - set to %NULL to indicate that the constraint refers to the
|
||||
@@ -1101,6 +1195,8 @@ gtk_constraint_layout_add_constraint (GtkConstraintLayout *manager,
|
||||
layout_add_constraint (manager, constraint);
|
||||
|
||||
g_hash_table_add (manager->constraints, constraint);
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (manager));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1121,4 +1217,371 @@ gtk_constraint_layout_remove_constraint (GtkConstraintLayout *manager,
|
||||
|
||||
gtk_constraint_detach (constraint);
|
||||
g_hash_table_remove (manager->constraints, constraint);
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (manager));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_constraint_target_iface_init (GtkConstraintTargetInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
struct _GtkConstraintGuideClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_MIN_WIDTH = 1,
|
||||
PROP_MIN_HEIGHT,
|
||||
PROP_NAT_WIDTH,
|
||||
PROP_NAT_HEIGHT,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *guide_props[LAST_PROP];
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkConstraintGuide, gtk_constraint_guide, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_CONSTRAINT_TARGET,
|
||||
gtk_constraint_guide_constraint_target_iface_init))
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_init (GtkConstraintGuide *guide)
|
||||
{
|
||||
guide->data.bound_attributes =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL,
|
||||
(GDestroyNotify) gtk_constraint_variable_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
update_min_width (GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
GtkConstraintVariable *var;
|
||||
|
||||
if (!guide->layout)
|
||||
return;
|
||||
|
||||
solver = guide->layout->solver;
|
||||
|
||||
if (!solver)
|
||||
return;
|
||||
|
||||
if (guide->width_constraint[0] != NULL)
|
||||
gtk_constraint_solver_remove_constraint (solver, guide->width_constraint[0]);
|
||||
|
||||
var = get_guide_attribute (guide->layout, guide, solver, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
guide->width_constraint[0] =
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
var,
|
||||
GTK_CONSTRAINT_RELATION_GE,
|
||||
gtk_constraint_expression_new (guide->min_width),
|
||||
GTK_CONSTRAINT_WEIGHT_REQUIRED);
|
||||
}
|
||||
|
||||
static void
|
||||
update_min_height (GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
GtkConstraintVariable *var;
|
||||
|
||||
if (!guide->layout)
|
||||
return;
|
||||
|
||||
solver = guide->layout->solver;
|
||||
|
||||
if (!solver)
|
||||
return;
|
||||
|
||||
if (guide->height_constraint[0] != NULL)
|
||||
gtk_constraint_solver_remove_constraint (solver, guide->height_constraint[0]);
|
||||
|
||||
var = get_guide_attribute (guide->layout, guide, solver, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
guide->height_constraint[0] =
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
var,
|
||||
GTK_CONSTRAINT_RELATION_GE,
|
||||
gtk_constraint_expression_new (guide->min_height),
|
||||
GTK_CONSTRAINT_WEIGHT_REQUIRED);
|
||||
}
|
||||
|
||||
static void
|
||||
update_nat_width (GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
GtkConstraintVariable *var;
|
||||
|
||||
if (!guide->layout)
|
||||
return;
|
||||
|
||||
solver = guide->layout->solver;
|
||||
|
||||
if (!solver)
|
||||
return;
|
||||
|
||||
if (guide->width_constraint[1] != NULL)
|
||||
gtk_constraint_solver_remove_constraint (solver, guide->width_constraint[1]);
|
||||
|
||||
var = get_guide_attribute (guide->layout, guide, solver, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
|
||||
guide->width_constraint[1] =
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
var,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
gtk_constraint_expression_new (guide->nat_width),
|
||||
GTK_CONSTRAINT_WEIGHT_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
update_nat_height (GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
GtkConstraintVariable *var;
|
||||
|
||||
if (!guide->layout)
|
||||
return;
|
||||
|
||||
solver = guide->layout->solver;
|
||||
|
||||
if (!solver)
|
||||
return;
|
||||
|
||||
if (guide->height_constraint[1] != NULL)
|
||||
gtk_constraint_solver_remove_constraint (solver, guide->height_constraint[1]);
|
||||
|
||||
var = get_guide_attribute (guide->layout, guide, solver, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
|
||||
guide->height_constraint[1] =
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
var,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
gtk_constraint_expression_new (guide->nat_height),
|
||||
GTK_CONSTRAINT_WEIGHT_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
set_min_width (GtkConstraintGuide *guide,
|
||||
int min_width)
|
||||
{
|
||||
if (guide->min_width == min_width)
|
||||
return;
|
||||
|
||||
guide->min_width = min_width;
|
||||
g_object_notify_by_pspec (G_OBJECT (guide),
|
||||
guide_props[PROP_MIN_WIDTH]);
|
||||
|
||||
update_min_width (guide);
|
||||
}
|
||||
|
||||
static void
|
||||
set_min_height (GtkConstraintGuide *guide,
|
||||
int min_height)
|
||||
{
|
||||
if (guide->min_height == min_height)
|
||||
return;
|
||||
|
||||
guide->min_height = min_height;
|
||||
g_object_notify_by_pspec (G_OBJECT (guide),
|
||||
guide_props[PROP_MIN_HEIGHT]);
|
||||
|
||||
update_min_height (guide);
|
||||
}
|
||||
|
||||
static void
|
||||
set_nat_width (GtkConstraintGuide *guide,
|
||||
int nat_width)
|
||||
{
|
||||
if (guide->nat_width == nat_width)
|
||||
return;
|
||||
|
||||
guide->nat_width = nat_width;
|
||||
g_object_notify_by_pspec (G_OBJECT (guide),
|
||||
guide_props[PROP_NAT_WIDTH]);
|
||||
|
||||
update_nat_width (guide);
|
||||
}
|
||||
static void
|
||||
set_nat_height (GtkConstraintGuide *guide,
|
||||
int nat_height)
|
||||
{
|
||||
if (guide->nat_height == nat_height)
|
||||
return;
|
||||
|
||||
guide->nat_height = nat_height;
|
||||
g_object_notify_by_pspec (G_OBJECT (guide),
|
||||
guide_props[PROP_NAT_HEIGHT]);
|
||||
|
||||
update_nat_height (guide);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MIN_WIDTH:
|
||||
set_min_width (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_MIN_HEIGHT:
|
||||
set_min_height (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_NAT_WIDTH:
|
||||
set_nat_width (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_NAT_HEIGHT:
|
||||
set_nat_height (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MIN_WIDTH:
|
||||
g_value_set_int (value, self->min_width);
|
||||
break;
|
||||
|
||||
case PROP_MIN_HEIGHT:
|
||||
g_value_set_int (value, self->min_height);
|
||||
break;
|
||||
|
||||
case PROP_NAT_WIDTH:
|
||||
g_value_set_int (value, self->nat_width);
|
||||
break;
|
||||
|
||||
case PROP_NAT_HEIGHT:
|
||||
g_value_set_int (value, self->nat_height);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_finalize (GObject *object)
|
||||
{
|
||||
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (object);
|
||||
GtkConstraintSolver *solver;
|
||||
|
||||
if (self->layout)
|
||||
{
|
||||
solver = gtk_constraint_layout_get_solver (self->layout);
|
||||
clear_constraint_solver_data (solver, &self->data);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gtk_constraint_guide_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_constraint_guide_finalize;
|
||||
object_class->set_property = gtk_constraint_guide_set_property;
|
||||
object_class->get_property = gtk_constraint_guide_get_property;
|
||||
|
||||
guide_props[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] =
|
||||
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] =
|
||||
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] =
|
||||
g_param_spec_int ("nat-height",
|
||||
"Natural height",
|
||||
"Natural height",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, guide_props);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_layout_add_guide:
|
||||
* @layout: a #GtkConstraintLayout
|
||||
* @guide: (transfer full): a #GtkConstraintGuide object
|
||||
*
|
||||
* Adds a guide to @layout. A guide can be used as
|
||||
* the source or target of constraints, like a widget,
|
||||
* but it is not visible.
|
||||
*
|
||||
* The @manager acquires the ownership of @guide after calling
|
||||
* this function.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_layout_add_guide (GtkConstraintLayout *layout,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_LAYOUT (layout));
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
g_return_if_fail (guide->layout == NULL);
|
||||
|
||||
guide->layout = layout;
|
||||
|
||||
g_hash_table_add (layout->guides, guide);
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_layout_remove_guide:
|
||||
* @layout: a #GtkConstraintManager
|
||||
* @guide: a #GtkConstraintGuide object
|
||||
*
|
||||
* Removes @guide from the layout manager,
|
||||
* so that it no longer influences the layout.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_layout_remove_guide (GtkConstraintLayout *layout,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_LAYOUT (layout));
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
g_return_if_fail (guide->layout == layout);
|
||||
|
||||
solver = gtk_constraint_layout_get_solver (guide->layout);
|
||||
clear_constraint_solver_data (solver, &guide->data);
|
||||
guide->layout = NULL;
|
||||
|
||||
g_hash_table_remove (layout->guides, guide);
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
|
||||
}
|
||||
|
||||
@@ -25,6 +25,30 @@ G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT_LAYOUT (gtk_constraint_layout_get_type ())
|
||||
#define GTK_TYPE_CONSTRAINT_LAYOUT_CHILD (gtk_constraint_layout_child_get_type ())
|
||||
#define GTK_TYPE_CONSTRAINT_GUIDE (gtk_constraint_guide_get_type ())
|
||||
|
||||
/**
|
||||
* GtkConstraintLayoutChild:
|
||||
*
|
||||
* A #GtkLayoutChild in a #GtkConstraintLayout.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK, CONSTRAINT_LAYOUT_CHILD, GtkLayoutChild)
|
||||
|
||||
/**
|
||||
* GtkConstraintGuide:
|
||||
*
|
||||
* An object that can be added to a #GtkConstraintLayout and be
|
||||
* used in constraints like a widget, without being drawn. Guides
|
||||
* have a minimal and natural size. Depending on the constraints
|
||||
* that are applied, they can act like a guideline that widgets
|
||||
* can be aligned to, or like 'flexible space'.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintGuide, gtk_constraint_guide, GTK, CONSTRAINT_GUIDE, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintGuide * gtk_constraint_guide_new (void);
|
||||
|
||||
/**
|
||||
* GtkConstraintLayout:
|
||||
@@ -45,12 +69,11 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_remove_constraint (GtkConstraintLayout *manager,
|
||||
GtkConstraint *constraint);
|
||||
|
||||
/**
|
||||
* GtkConstraintLayoutChild:
|
||||
*
|
||||
* A #GtkLayoutChild in a #GtkConstraintLayout.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK, CONSTRAINT_LAYOUT_CHILD, GtkLayoutChild)
|
||||
void gtk_constraint_layout_add_guide (GtkConstraintLayout *manager,
|
||||
GtkConstraintGuide *guide);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_remove_guide (GtkConstraintLayout *manager,
|
||||
GtkConstraintGuide *guide);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -31,8 +31,8 @@ struct _GtkConstraint
|
||||
GtkConstraintAttribute target_attribute;
|
||||
GtkConstraintAttribute source_attribute;
|
||||
|
||||
GtkWidget *target_widget;
|
||||
GtkWidget *source_widget;
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintTarget *source;
|
||||
|
||||
GtkConstraintRelation relation;
|
||||
|
||||
|
||||
@@ -1972,6 +1972,7 @@ 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",
|
||||
@@ -1987,9 +1988,10 @@ gtk_constraint_solver_suggest_value (GtkConstraintSolver *self,
|
||||
return;
|
||||
}
|
||||
|
||||
ei->prev_constant = value - ei->prev_constant;
|
||||
delta = value - ei->prev_constant;
|
||||
ei->prev_constant = value;
|
||||
|
||||
gtk_constraint_solver_delta_edit_constant (self, ei->prev_constant, ei->eplus, ei->eminus);
|
||||
gtk_constraint_solver_delta_edit_constant (self, delta, ei->eplus, ei->eminus);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include "gtkwindowgroup.h"
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtknativeprivate.h"
|
||||
#include "gtkconstraint.h"
|
||||
|
||||
#include "a11y/gtkwidgetaccessible.h"
|
||||
#include "inspector/window.h"
|
||||
@@ -770,6 +771,13 @@ gtk_widget_get_type (void)
|
||||
NULL /* interface data */
|
||||
};
|
||||
|
||||
const GInterfaceInfo constraint_target_info =
|
||||
{
|
||||
(GInterfaceInitFunc) NULL,
|
||||
(GInterfaceFinalizeFunc) NULL,
|
||||
NULL /* interface data */
|
||||
};
|
||||
|
||||
widget_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, g_intern_static_string ("GtkWidget"),
|
||||
&widget_info, G_TYPE_FLAG_ABSTRACT);
|
||||
|
||||
@@ -782,6 +790,8 @@ gtk_widget_get_type (void)
|
||||
&accessibility_info) ;
|
||||
g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
|
||||
&buildable_info) ;
|
||||
g_type_add_interface_static (widget_type, GTK_TYPE_CONSTRAINT_TARGET,
|
||||
&constraint_target_info) ;
|
||||
}
|
||||
|
||||
return widget_type;
|
||||
|
||||
@@ -254,15 +254,27 @@ 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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user