1/* Constraints/Simple Constraints
2 * #Keywords: GtkLayoutManager
3 *
4 * GtkConstraintLayout provides a layout manager that uses relations
5 * between widgets (also known as “constraints”) to compute the position
6 * and size of each child.
7 *
8 * In addition to child widgets, the constraints can involve spacer
9 * objects (also known as “guides”). This example has a guide between
10 * the two buttons in the top row.
11 *
12 * Try resizing the window to see how the constraints react to update
13 * the layout.
14 */
15
16#include <glib/gi18n.h>
17#include <gtk/gtk.h>
18
19G_DECLARE_FINAL_TYPE (SimpleGrid, simple_grid, SIMPLE, GRID, GtkWidget)
20
21struct _SimpleGrid
22{
23 GtkWidget parent_instance;
24
25 GtkWidget *button1, *button2;
26 GtkWidget *button3;
27};
28
29G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET)
30
31static void
32simple_grid_dispose (GObject *object)
33{
34 SimpleGrid *self = SIMPLE_GRID (ptr: object);
35
36 g_clear_pointer (&self->button1, gtk_widget_unparent);
37 g_clear_pointer (&self->button2, gtk_widget_unparent);
38 g_clear_pointer (&self->button3, gtk_widget_unparent);
39
40 G_OBJECT_CLASS (simple_grid_parent_class)->dispose (object);
41}
42
43static void
44simple_grid_class_init (SimpleGridClass *klass)
45{
46 GObjectClass *object_class = G_OBJECT_CLASS (klass);
47 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
48
49 object_class->dispose = simple_grid_dispose;
50
51 gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
52}
53
54/* Layout:
55 *
56 * +-------------------------------------+
57 * | +-----------++-------++-----------+ |
58 * | | Child 1 || Space || Child 2 | |
59 * | +-----------++-------++-----------+ |
60 * | +---------------------------------+ |
61 * | | Child 3 | |
62 * | +---------------------------------+ |
63 * +-------------------------------------+
64 *
65 * Constraints:
66 *
67 * super.start = child1.start - 8
68 * child1.width = child2.width
69 * child1.end = space.start
70 * space.end = child2.start
71 * child2.end = super.end - 8
72 * super.start = child3.start - 8
73 * child3.end = super.end - 8
74 * super.top = child1.top - 8
75 * super.top = child2.top - 8
76 * child1.bottom = child3.top - 12
77 * child2.bottom = child3.top - 12
78 * child3.height = child1.height
79 * child3.height = child2.height
80 * child3.bottom = super.bottom - 8
81 *
82 * To add some flexibility, we make the space
83 * stretchable:
84 *
85 * space.width >= 10
86 * space.width = 100
87 * space.width <= 200
88 */
89static void
90build_constraints (SimpleGrid *self,
91 GtkConstraintLayout *manager)
92{
93 GtkConstraintGuide *guide;
94
95 guide = gtk_constraint_guide_new ();
96 gtk_constraint_guide_set_name (guide, name: "space");
97 gtk_constraint_guide_set_min_size (guide, width: 10, height: 10);
98 gtk_constraint_guide_set_nat_size (guide, width: 100, height: 10);
99 gtk_constraint_guide_set_max_size (guide, width: 200, height: 20);
100 gtk_constraint_guide_set_strength (guide, strength: GTK_CONSTRAINT_STRENGTH_STRONG);
101 gtk_constraint_layout_add_guide (layout: manager, guide);
102
103 gtk_constraint_layout_add_constraint (layout: manager,
104 constraint: gtk_constraint_new_constant (target: GTK_CONSTRAINT_TARGET (ptr: self->button1),
105 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
106 relation: GTK_CONSTRAINT_RELATION_LE,
107 constant: 200.0,
108 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
109 gtk_constraint_layout_add_constraint (layout: manager,
110 constraint: gtk_constraint_new (NULL,
111 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_START,
112 relation: GTK_CONSTRAINT_RELATION_EQ,
113 source: self->button1,
114 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_START,
115 multiplier: 1.0,
116 constant: -8.0,
117 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
118 gtk_constraint_layout_add_constraint (layout: manager,
119 constraint: gtk_constraint_new (target: self->button1,
120 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
121 relation: GTK_CONSTRAINT_RELATION_EQ,
122 source: self->button2,
123 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
124 multiplier: 1.0,
125 constant: 0.0,
126 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
127 gtk_constraint_layout_add_constraint (layout: manager,
128 constraint: gtk_constraint_new (target: self->button1,
129 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_END,
130 relation: GTK_CONSTRAINT_RELATION_EQ,
131 source: guide,
132 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_START,
133 multiplier: 1.0,
134 constant: 0.0,
135 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
136 gtk_constraint_layout_add_constraint (layout: manager,
137 constraint: gtk_constraint_new (target: guide,
138 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_END,
139 relation: GTK_CONSTRAINT_RELATION_EQ,
140 source: self->button2,
141 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_START,
142 multiplier: 1.0,
143 constant: 0.0,
144 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
145 gtk_constraint_layout_add_constraint (layout: manager,
146 constraint: gtk_constraint_new (target: self->button2,
147 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_END,
148 relation: GTK_CONSTRAINT_RELATION_EQ,
149 NULL,
150 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_END,
151 multiplier: 1.0,
152 constant: -8.0,
153 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
154 gtk_constraint_layout_add_constraint (layout: manager,
155 constraint: gtk_constraint_new (NULL,
156 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_START,
157 relation: GTK_CONSTRAINT_RELATION_EQ,
158 source: self->button3,
159 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_START,
160 multiplier: 1.0,
161 constant: -8.0,
162 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
163 gtk_constraint_layout_add_constraint (layout: manager,
164 constraint: gtk_constraint_new (target: self->button3,
165 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_END,
166 relation: GTK_CONSTRAINT_RELATION_EQ,
167 NULL,
168 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_END,
169 multiplier: 1.0,
170 constant: -8.0,
171 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
172 gtk_constraint_layout_add_constraint (layout: manager,
173 constraint: gtk_constraint_new (NULL,
174 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_TOP,
175 relation: GTK_CONSTRAINT_RELATION_EQ,
176 source: self->button1,
177 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_TOP,
178 multiplier: 1.0,
179 constant: -8.0,
180 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
181 gtk_constraint_layout_add_constraint (layout: manager,
182 constraint: gtk_constraint_new (NULL,
183 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_TOP,
184 relation: GTK_CONSTRAINT_RELATION_EQ,
185 source: self->button2,
186 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_TOP,
187 multiplier: 1.0,
188 constant: -8.0,
189 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
190 gtk_constraint_layout_add_constraint (layout: manager,
191 constraint: gtk_constraint_new (target: self->button1,
192 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
193 relation: GTK_CONSTRAINT_RELATION_EQ,
194 source: self->button3,
195 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_TOP,
196 multiplier: 1.0,
197 constant: -12.0,
198 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
199 gtk_constraint_layout_add_constraint (layout: manager,
200 constraint: gtk_constraint_new (target: self->button2,
201 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
202 relation: GTK_CONSTRAINT_RELATION_EQ,
203 source: self->button3,
204 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_TOP,
205 multiplier: 1.0,
206 constant: -12.0,
207 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
208 gtk_constraint_layout_add_constraint (layout: manager,
209 constraint: gtk_constraint_new (target: self->button3,
210 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
211 relation: GTK_CONSTRAINT_RELATION_EQ,
212 source: self->button1,
213 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
214 multiplier: 1.0,
215 constant: 0.0,
216 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
217 gtk_constraint_layout_add_constraint (layout: manager,
218 constraint: gtk_constraint_new (target: self->button3,
219 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
220 relation: GTK_CONSTRAINT_RELATION_EQ,
221 source: self->button2,
222 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
223 multiplier: 1.0,
224 constant: 0.0,
225 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
226 gtk_constraint_layout_add_constraint (layout: manager,
227 constraint: gtk_constraint_new (target: self->button3,
228 target_attribute: GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
229 relation: GTK_CONSTRAINT_RELATION_EQ,
230 NULL,
231 source_attribute: GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
232 multiplier: 1.0,
233 constant: -8.0,
234 strength: GTK_CONSTRAINT_STRENGTH_REQUIRED));
235}
236
237static void
238simple_grid_init (SimpleGrid *self)
239{
240 GtkWidget *widget = GTK_WIDGET (self);
241
242 self->button1 = gtk_button_new_with_label (label: "Child 1");
243 gtk_widget_set_parent (widget: self->button1, parent: widget);
244
245 self->button2 = gtk_button_new_with_label (label: "Child 2");
246 gtk_widget_set_parent (widget: self->button2, parent: widget);
247
248 self->button3 = gtk_button_new_with_label (label: "Child 3");
249 gtk_widget_set_parent (widget: self->button3, parent: widget);
250
251 GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
252 build_constraints (self, manager: GTK_CONSTRAINT_LAYOUT (ptr: manager));
253}
254
255GtkWidget *
256do_constraints (GtkWidget *do_widget)
257{
258 static GtkWidget *window;
259
260 if (!window)
261 {
262 GtkWidget *box, *grid;
263
264 window = gtk_window_new ();
265 gtk_window_set_display (GTK_WINDOW (window), display: gtk_widget_get_display (widget: do_widget));
266 gtk_window_set_title (GTK_WINDOW (window), title: "Simple Constraints");
267 gtk_window_set_default_size (GTK_WINDOW (window), width: 260, height: -1);
268 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
269
270 box = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 12);
271 gtk_window_set_child (GTK_WINDOW (window), child: box);
272
273 grid = g_object_new (object_type: simple_grid_get_type (), NULL);
274 gtk_widget_set_hexpand (widget: grid, TRUE);
275 gtk_widget_set_vexpand (widget: grid, TRUE);
276 gtk_box_append (GTK_BOX (box), child: grid);
277 }
278
279 if (!gtk_widget_get_visible (widget: window))
280 gtk_widget_show (widget: window);
281 else
282 gtk_window_destroy (GTK_WINDOW (window));
283
284 return window;
285}
286

source code of gtk/demos/gtk-demo/constraints.c