forked from AuroraMiddleware/gtk
Add GtkConstraintGuide
This is meant to be a flexible space.
This commit is contained in:
parent
7ae04ba36b
commit
38d353dc1a
@ -74,6 +74,16 @@ 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 (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
@ -94,12 +104,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,
|
||||
|
@ -572,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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
@ -871,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);
|
||||
|
||||
@ -972,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)
|
||||
{
|
||||
@ -991,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
|
||||
@ -1011,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);
|
||||
}
|
||||
|
||||
@ -1047,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1116,3 +1220,368 @@ gtk_constraint_layout_remove_constraint (GtkConstraintLayout *manager,
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user