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 | |
19 | G_DECLARE_FINAL_TYPE (SimpleGrid, simple_grid, SIMPLE, GRID, GtkWidget) |
20 | |
21 | struct _SimpleGrid |
22 | { |
23 | GtkWidget parent_instance; |
24 | |
25 | GtkWidget *button1, *button2; |
26 | GtkWidget *button3; |
27 | }; |
28 | |
29 | G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET) |
30 | |
31 | static void |
32 | simple_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 | |
43 | static void |
44 | simple_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 | */ |
89 | static void |
90 | build_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 | |
237 | static void |
238 | simple_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 | |
255 | GtkWidget * |
256 | do_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 | |