1 | /* GTK - The GIMP Toolkit |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GTK+ Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GTK+ at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | /** |
26 | * GtkBox: |
27 | * |
28 | * The `GtkBox` widget arranges child widgets into a single row or column. |
29 | * |
30 | * ![An example GtkBox](box.png) |
31 | * |
32 | * Whether it is a row or column depends on the value of its |
33 | * [property@Gtk.Orientable:orientation] property. Within the other |
34 | * dimension, all children are allocated the same size. Of course, the |
35 | * [property@Gtk.Widget:halign] and [property@Gtk.Widget:valign] properties |
36 | * can be used on the children to influence their allocation. |
37 | * |
38 | * Use repeated calls to [method@Gtk.Box.append] to pack widgets into a |
39 | * `GtkBox` from start to end. Use [method@Gtk.Box.remove] to remove widgets |
40 | * from the `GtkBox`. [method@Gtk.Box.insert_child_after] can be used to add |
41 | * a child at a particular position. |
42 | * |
43 | * Use [method@Gtk.Box.set_homogeneous] to specify whether or not all children |
44 | * of the `GtkBox` are forced to get the same amount of space. |
45 | * |
46 | * Use [method@Gtk.Box.set_spacing] to determine how much space will be minimally |
47 | * placed between all children in the `GtkBox`. Note that spacing is added |
48 | * *between* the children. |
49 | * |
50 | * Use [method@Gtk.Box.reorder_child_after] to move a child to a different |
51 | * place in the box. |
52 | * |
53 | * # CSS nodes |
54 | * |
55 | * `GtkBox` uses a single CSS node with name box. |
56 | * |
57 | * # Accessibility |
58 | * |
59 | * `GtkBox` uses the %GTK_ACCESSIBLE_ROLE_GROUP role. |
60 | */ |
61 | |
62 | #include "config.h" |
63 | |
64 | #include "gtkbox.h" |
65 | #include "gtkboxlayout.h" |
66 | #include "gtkbuildable.h" |
67 | #include "gtkintl.h" |
68 | #include "gtkorientable.h" |
69 | #include "gtkprivate.h" |
70 | #include "gtktypebuiltins.h" |
71 | #include "gtksizerequest.h" |
72 | #include "gtkwidgetprivate.h" |
73 | |
74 | |
75 | enum { |
76 | PROP_0, |
77 | PROP_SPACING, |
78 | PROP_HOMOGENEOUS, |
79 | PROP_BASELINE_POSITION, |
80 | |
81 | /* orientable */ |
82 | PROP_ORIENTATION, |
83 | LAST_PROP = PROP_ORIENTATION |
84 | }; |
85 | |
86 | typedef struct |
87 | { |
88 | gint16 spacing; |
89 | |
90 | guint homogeneous : 1; |
91 | guint baseline_pos : 2; |
92 | } GtkBoxPrivate; |
93 | |
94 | static GParamSpec *props[LAST_PROP] = { NULL, }; |
95 | |
96 | static void gtk_box_buildable_iface_init (GtkBuildableIface *iface); |
97 | |
98 | G_DEFINE_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_WIDGET, |
99 | G_ADD_PRIVATE (GtkBox) |
100 | G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL) |
101 | G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, |
102 | gtk_box_buildable_iface_init)) |
103 | |
104 | |
105 | static void |
106 | gtk_box_set_property (GObject *object, |
107 | guint prop_id, |
108 | const GValue *value, |
109 | GParamSpec *pspec) |
110 | { |
111 | GtkBox *box = GTK_BOX (object); |
112 | GtkLayoutManager *box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box)); |
113 | |
114 | switch (prop_id) |
115 | { |
116 | case PROP_ORIENTATION: |
117 | { |
118 | GtkOrientation orientation = g_value_get_enum (value); |
119 | if (gtk_orientable_get_orientation (GTK_ORIENTABLE (box_layout)) != orientation) |
120 | { |
121 | gtk_orientable_set_orientation (GTK_ORIENTABLE (box_layout), orientation); |
122 | gtk_widget_update_orientation (GTK_WIDGET (box), orientation); |
123 | g_object_notify_by_pspec (G_OBJECT (box), pspec); |
124 | } |
125 | } |
126 | break; |
127 | case PROP_SPACING: |
128 | gtk_box_set_spacing (box, spacing: g_value_get_int (value)); |
129 | break; |
130 | case PROP_BASELINE_POSITION: |
131 | gtk_box_set_baseline_position (box, position: g_value_get_enum (value)); |
132 | break; |
133 | case PROP_HOMOGENEOUS: |
134 | gtk_box_set_homogeneous (box, homogeneous: g_value_get_boolean (value)); |
135 | break; |
136 | default: |
137 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
138 | break; |
139 | } |
140 | } |
141 | |
142 | static void |
143 | gtk_box_get_property (GObject *object, |
144 | guint prop_id, |
145 | GValue *value, |
146 | GParamSpec *pspec) |
147 | { |
148 | GtkBox *box = GTK_BOX (object); |
149 | GtkBoxLayout *box_layout = GTK_BOX_LAYOUT (ptr: gtk_widget_get_layout_manager (GTK_WIDGET (box))); |
150 | |
151 | switch (prop_id) |
152 | { |
153 | case PROP_ORIENTATION: |
154 | g_value_set_enum (value, v_enum: gtk_orientable_get_orientation (GTK_ORIENTABLE (box_layout))); |
155 | break; |
156 | case PROP_SPACING: |
157 | g_value_set_int (value, v_int: gtk_box_layout_get_spacing (box_layout)); |
158 | break; |
159 | case PROP_BASELINE_POSITION: |
160 | g_value_set_enum (value, v_enum: gtk_box_layout_get_baseline_position (box_layout)); |
161 | break; |
162 | case PROP_HOMOGENEOUS: |
163 | g_value_set_boolean (value, v_boolean: gtk_box_layout_get_homogeneous (box_layout)); |
164 | break; |
165 | default: |
166 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
167 | break; |
168 | } |
169 | } |
170 | |
171 | static void |
172 | gtk_box_compute_expand (GtkWidget *widget, |
173 | gboolean *hexpand_p, |
174 | gboolean *vexpand_p) |
175 | { |
176 | GtkWidget *w; |
177 | gboolean hexpand = FALSE; |
178 | gboolean vexpand = FALSE; |
179 | |
180 | for (w = gtk_widget_get_first_child (widget); |
181 | w != NULL; |
182 | w = gtk_widget_get_next_sibling (widget: w)) |
183 | { |
184 | hexpand = hexpand || gtk_widget_compute_expand (widget: w, orientation: GTK_ORIENTATION_HORIZONTAL); |
185 | vexpand = vexpand || gtk_widget_compute_expand (widget: w, orientation: GTK_ORIENTATION_VERTICAL); |
186 | } |
187 | |
188 | *hexpand_p = hexpand; |
189 | *vexpand_p = vexpand; |
190 | } |
191 | |
192 | static GtkSizeRequestMode |
193 | gtk_box_get_request_mode (GtkWidget *widget) |
194 | { |
195 | GtkWidget *w; |
196 | int wfh = 0, hfw = 0; |
197 | |
198 | for (w = gtk_widget_get_first_child (widget); |
199 | w != NULL; |
200 | w = gtk_widget_get_next_sibling (widget: w)) |
201 | { |
202 | GtkSizeRequestMode mode = gtk_widget_get_request_mode (widget: w); |
203 | |
204 | switch (mode) |
205 | { |
206 | case GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH: |
207 | hfw ++; |
208 | break; |
209 | case GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT: |
210 | wfh ++; |
211 | break; |
212 | case GTK_SIZE_REQUEST_CONSTANT_SIZE: |
213 | default: |
214 | break; |
215 | } |
216 | } |
217 | |
218 | if (hfw == 0 && wfh == 0) |
219 | return GTK_SIZE_REQUEST_CONSTANT_SIZE; |
220 | else |
221 | return wfh > hfw ? |
222 | GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT : |
223 | GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; |
224 | } |
225 | |
226 | static void |
227 | gtk_box_dispose (GObject *object) |
228 | { |
229 | GtkWidget *child; |
230 | |
231 | while ((child = gtk_widget_get_first_child (GTK_WIDGET (object)))) |
232 | gtk_widget_unparent (widget: child); |
233 | |
234 | G_OBJECT_CLASS (gtk_box_parent_class)->dispose (object); |
235 | } |
236 | |
237 | static void |
238 | gtk_box_class_init (GtkBoxClass *class) |
239 | { |
240 | GObjectClass *object_class = G_OBJECT_CLASS (class); |
241 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); |
242 | |
243 | object_class->set_property = gtk_box_set_property; |
244 | object_class->get_property = gtk_box_get_property; |
245 | object_class->dispose = gtk_box_dispose; |
246 | |
247 | widget_class->focus = gtk_widget_focus_child; |
248 | widget_class->compute_expand = gtk_box_compute_expand; |
249 | widget_class->get_request_mode = gtk_box_get_request_mode; |
250 | |
251 | g_object_class_override_property (oclass: object_class, |
252 | property_id: PROP_ORIENTATION, |
253 | name: "orientation" ); |
254 | |
255 | /** |
256 | * GtkBox:spacing: (attributes org.gtk.Property.get=gtk_box_get_spacing org.gtk.Property.set=gtk_box_set_spacing) |
257 | * |
258 | * The amount of space between children. |
259 | */ |
260 | props[PROP_SPACING] = |
261 | g_param_spec_int (name: "spacing" , |
262 | P_("Spacing" ), |
263 | P_("The amount of space between children" ), |
264 | minimum: 0, G_MAXINT, default_value: 0, |
265 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
266 | |
267 | /** |
268 | * GtkBox:homogeneous: (attributes org.gtk.Property.get=gtk_box_get_homogeneous org.gtk.Property.set=gtk_box_set_homogeneous) |
269 | * |
270 | * Whether the children should all be the same size. |
271 | */ |
272 | props[PROP_HOMOGENEOUS] = |
273 | g_param_spec_boolean (name: "homogeneous" , |
274 | P_("Homogeneous" ), |
275 | P_("Whether the children should all be the same size" ), |
276 | FALSE, |
277 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
278 | |
279 | /** |
280 | * GtkBox:baseline-position: (attributes org.gtk.Property.get=gtk_box_get_baseline_position org.gtk.Property.set=gtk_box_set_baseline_position) |
281 | * |
282 | * The position of the baseline aligned widgets if extra space is available. |
283 | */ |
284 | props[PROP_BASELINE_POSITION] = |
285 | g_param_spec_enum (name: "baseline-position" , |
286 | P_("Baseline position" ), |
287 | P_("The position of the baseline aligned widgets if extra space is available" ), |
288 | enum_type: GTK_TYPE_BASELINE_POSITION, |
289 | default_value: GTK_BASELINE_POSITION_CENTER, |
290 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
291 | |
292 | g_object_class_install_properties (oclass: object_class, n_pspecs: LAST_PROP, pspecs: props); |
293 | |
294 | gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT); |
295 | gtk_widget_class_set_css_name (widget_class, I_("box" )); |
296 | gtk_widget_class_set_accessible_role (widget_class, accessible_role: GTK_ACCESSIBLE_ROLE_GROUP); |
297 | } |
298 | static void |
299 | gtk_box_init (GtkBox *box) |
300 | { |
301 | gtk_widget_update_orientation (GTK_WIDGET (box), orientation: GTK_ORIENTATION_HORIZONTAL); |
302 | } |
303 | |
304 | static GtkBuildableIface *parent_buildable_iface; |
305 | |
306 | static void |
307 | gtk_box_buildable_add_child (GtkBuildable *buildable, |
308 | GtkBuilder *builder, |
309 | GObject *child, |
310 | const char *type) |
311 | { |
312 | if (GTK_IS_WIDGET (child)) |
313 | gtk_box_append (GTK_BOX (buildable), GTK_WIDGET (child)); |
314 | else |
315 | parent_buildable_iface->add_child (buildable, builder, child, type); |
316 | } |
317 | |
318 | static void |
319 | gtk_box_buildable_iface_init (GtkBuildableIface *iface) |
320 | { |
321 | parent_buildable_iface = g_type_interface_peek_parent (g_iface: iface); |
322 | |
323 | iface->add_child = gtk_box_buildable_add_child; |
324 | } |
325 | |
326 | /** |
327 | * gtk_box_new: |
328 | * @orientation: the box’s orientation |
329 | * @spacing: the number of pixels to place by default between children |
330 | * |
331 | * Creates a new `GtkBox`. |
332 | * |
333 | * Returns: a new `GtkBox`. |
334 | */ |
335 | GtkWidget* |
336 | gtk_box_new (GtkOrientation orientation, |
337 | int spacing) |
338 | { |
339 | return g_object_new (GTK_TYPE_BOX, |
340 | first_property_name: "orientation" , orientation, |
341 | "spacing" , spacing, |
342 | NULL); |
343 | } |
344 | |
345 | /** |
346 | * gtk_box_set_homogeneous: (attributes org.gtk.Method.set_property=homogeneous) |
347 | * @box: a `GtkBox` |
348 | * @homogeneous: a boolean value, %TRUE to create equal allotments, |
349 | * %FALSE for variable allotments |
350 | * |
351 | * Sets whether or not all children of @box are given equal space |
352 | * in the box. |
353 | */ |
354 | void |
355 | gtk_box_set_homogeneous (GtkBox *box, |
356 | gboolean homogeneous) |
357 | { |
358 | GtkBoxLayout *box_layout; |
359 | |
360 | g_return_if_fail (GTK_IS_BOX (box)); |
361 | |
362 | homogeneous = !!homogeneous; |
363 | |
364 | box_layout = GTK_BOX_LAYOUT (ptr: gtk_widget_get_layout_manager (GTK_WIDGET (box))); |
365 | if (homogeneous == gtk_box_layout_get_homogeneous (box_layout)) |
366 | return; |
367 | |
368 | gtk_box_layout_set_homogeneous (box_layout, homogeneous); |
369 | g_object_notify_by_pspec (G_OBJECT (box), pspec: props[PROP_HOMOGENEOUS]); |
370 | } |
371 | |
372 | /** |
373 | * gtk_box_get_homogeneous: (attributes org.gtk.Method.get_property=homogeneous) |
374 | * @box: a `GtkBox` |
375 | * |
376 | * Returns whether the box is homogeneous (all children are the |
377 | * same size). |
378 | * |
379 | * Returns: %TRUE if the box is homogeneous. |
380 | */ |
381 | gboolean |
382 | gtk_box_get_homogeneous (GtkBox *box) |
383 | { |
384 | GtkLayoutManager *box_layout; |
385 | |
386 | g_return_val_if_fail (GTK_IS_BOX (box), FALSE); |
387 | |
388 | box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box)); |
389 | |
390 | return gtk_box_layout_get_homogeneous (box_layout: GTK_BOX_LAYOUT (ptr: box_layout)); |
391 | } |
392 | |
393 | /** |
394 | * gtk_box_set_spacing: (attributes org.gtk.Method.set_property=spacing) |
395 | * @box: a `GtkBox` |
396 | * @spacing: the number of pixels to put between children |
397 | * |
398 | * Sets the number of pixels to place between children of @box. |
399 | */ |
400 | void |
401 | gtk_box_set_spacing (GtkBox *box, |
402 | int spacing) |
403 | { |
404 | GtkBoxLayout *box_layout; |
405 | |
406 | g_return_if_fail (GTK_IS_BOX (box)); |
407 | |
408 | box_layout = GTK_BOX_LAYOUT (ptr: gtk_widget_get_layout_manager (GTK_WIDGET (box))); |
409 | if (spacing == gtk_box_layout_get_spacing (box_layout)) |
410 | return; |
411 | |
412 | gtk_box_layout_set_spacing (box_layout, spacing); |
413 | g_object_notify_by_pspec (G_OBJECT (box), pspec: props[PROP_SPACING]); |
414 | } |
415 | |
416 | /** |
417 | * gtk_box_get_spacing: (attributes org.gtk.Method.get_property=spacing) |
418 | * @box: a `GtkBox` |
419 | * |
420 | * Gets the value set by gtk_box_set_spacing(). |
421 | * |
422 | * Returns: spacing between children |
423 | */ |
424 | int |
425 | gtk_box_get_spacing (GtkBox *box) |
426 | { |
427 | GtkLayoutManager *box_layout; |
428 | |
429 | g_return_val_if_fail (GTK_IS_BOX (box), 0); |
430 | |
431 | box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box)); |
432 | |
433 | return gtk_box_layout_get_spacing (box_layout: GTK_BOX_LAYOUT (ptr: box_layout)); |
434 | } |
435 | |
436 | /** |
437 | * gtk_box_set_baseline_position: (attributes org.gtk.Method.set_property=baseline-position) |
438 | * @box: a `GtkBox` |
439 | * @position: a `GtkBaselinePosition` |
440 | * |
441 | * Sets the baseline position of a box. |
442 | * |
443 | * This affects only horizontal boxes with at least one baseline |
444 | * aligned child. If there is more vertical space available than |
445 | * requested, and the baseline is not allocated by the parent then |
446 | * @position is used to allocate the baseline with respect to the |
447 | * extra space available. |
448 | */ |
449 | void |
450 | gtk_box_set_baseline_position (GtkBox *box, |
451 | GtkBaselinePosition position) |
452 | { |
453 | GtkBoxLayout *box_layout; |
454 | |
455 | g_return_if_fail (GTK_IS_BOX (box)); |
456 | |
457 | box_layout = GTK_BOX_LAYOUT (ptr: gtk_widget_get_layout_manager (GTK_WIDGET (box))); |
458 | if (position == gtk_box_layout_get_baseline_position (box_layout)) |
459 | return; |
460 | |
461 | gtk_box_layout_set_baseline_position (box_layout, position); |
462 | g_object_notify_by_pspec (G_OBJECT (box), pspec: props[PROP_BASELINE_POSITION]); |
463 | } |
464 | |
465 | /** |
466 | * gtk_box_get_baseline_position: (attributes org.gtk.Method.get_property=baseline-position) |
467 | * @box: a `GtkBox` |
468 | * |
469 | * Gets the value set by gtk_box_set_baseline_position(). |
470 | * |
471 | * Returns: the baseline position |
472 | */ |
473 | GtkBaselinePosition |
474 | gtk_box_get_baseline_position (GtkBox *box) |
475 | { |
476 | GtkLayoutManager *box_layout; |
477 | |
478 | g_return_val_if_fail (GTK_IS_BOX (box), GTK_BASELINE_POSITION_CENTER); |
479 | |
480 | box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box)); |
481 | |
482 | return gtk_box_layout_get_baseline_position (box_layout: GTK_BOX_LAYOUT (ptr: box_layout)); |
483 | } |
484 | |
485 | /** |
486 | * gtk_box_insert_child_after: |
487 | * @box: a `GtkBox` |
488 | * @child: the `GtkWidget` to insert |
489 | * @sibling: (nullable): the sibling after which to insert @child |
490 | * |
491 | * Inserts @child in the position after @sibling in the list |
492 | * of @box children. |
493 | * |
494 | * If @sibling is %NULL, insert @child at the first position. |
495 | */ |
496 | void |
497 | gtk_box_insert_child_after (GtkBox *box, |
498 | GtkWidget *child, |
499 | GtkWidget *sibling) |
500 | { |
501 | GtkWidget *widget; |
502 | |
503 | g_return_if_fail (GTK_IS_BOX (box)); |
504 | g_return_if_fail (GTK_IS_WIDGET (child)); |
505 | g_return_if_fail (gtk_widget_get_parent (child) == NULL); |
506 | |
507 | widget = GTK_WIDGET (box); |
508 | |
509 | if (sibling) |
510 | { |
511 | g_return_if_fail (GTK_IS_WIDGET (sibling)); |
512 | g_return_if_fail (gtk_widget_get_parent (sibling) == widget); |
513 | } |
514 | |
515 | if (child == sibling) |
516 | return; |
517 | |
518 | gtk_widget_insert_after (widget: child, parent: widget, previous_sibling: sibling); |
519 | } |
520 | |
521 | /** |
522 | * gtk_box_reorder_child_after: |
523 | * @box: a `GtkBox` |
524 | * @child: the `GtkWidget` to move, must be a child of @box |
525 | * @sibling: (nullable): the sibling to move @child after |
526 | * |
527 | * Moves @child to the position after @sibling in the list |
528 | * of @box children. |
529 | * |
530 | * If @sibling is %NULL, move @child to the first position. |
531 | */ |
532 | void |
533 | gtk_box_reorder_child_after (GtkBox *box, |
534 | GtkWidget *child, |
535 | GtkWidget *sibling) |
536 | { |
537 | GtkWidget *widget; |
538 | |
539 | g_return_if_fail (GTK_IS_BOX (box)); |
540 | g_return_if_fail (GTK_IS_WIDGET (child)); |
541 | g_return_if_fail (gtk_widget_get_parent (child) == (GtkWidget *)box); |
542 | |
543 | widget = GTK_WIDGET (box); |
544 | |
545 | if (sibling) |
546 | { |
547 | g_return_if_fail (GTK_IS_WIDGET (sibling)); |
548 | g_return_if_fail (gtk_widget_get_parent (sibling) == widget); |
549 | } |
550 | |
551 | if (child == sibling) |
552 | return; |
553 | |
554 | gtk_widget_insert_after (widget: child, parent: widget, previous_sibling: sibling); |
555 | } |
556 | |
557 | /** |
558 | * gtk_box_append: |
559 | * @box: a `GtkBox` |
560 | * @child: the `GtkWidget` to append |
561 | * |
562 | * Adds @child as the last child to @box. |
563 | */ |
564 | void |
565 | gtk_box_append (GtkBox *box, |
566 | GtkWidget *child) |
567 | { |
568 | g_return_if_fail (GTK_IS_BOX (box)); |
569 | g_return_if_fail (GTK_IS_WIDGET (child)); |
570 | g_return_if_fail (gtk_widget_get_parent (child) == NULL); |
571 | |
572 | gtk_widget_insert_before (widget: child, GTK_WIDGET (box), NULL); |
573 | } |
574 | |
575 | /** |
576 | * gtk_box_prepend: |
577 | * @box: a `GtkBox` |
578 | * @child: the `GtkWidget` to prepend |
579 | * |
580 | * Adds @child as the first child to @box. |
581 | */ |
582 | void |
583 | gtk_box_prepend (GtkBox *box, |
584 | GtkWidget *child) |
585 | { |
586 | g_return_if_fail (GTK_IS_BOX (box)); |
587 | g_return_if_fail (GTK_IS_WIDGET (child)); |
588 | g_return_if_fail (gtk_widget_get_parent (child) == NULL); |
589 | |
590 | gtk_widget_insert_after (widget: child, GTK_WIDGET (box), NULL); |
591 | } |
592 | |
593 | /** |
594 | * gtk_box_remove: |
595 | * @box: a `GtkBox` |
596 | * @child: the child to remove |
597 | * |
598 | * Removes a child widget from @box. |
599 | * |
600 | * The child must have been added before with |
601 | * [method@Gtk.Box.append], [method@Gtk.Box.prepend], or |
602 | * [method@Gtk.Box.insert_child_after]. |
603 | */ |
604 | void |
605 | gtk_box_remove (GtkBox *box, |
606 | GtkWidget *child) |
607 | { |
608 | g_return_if_fail (GTK_IS_BOX (box)); |
609 | g_return_if_fail (GTK_IS_WIDGET (child)); |
610 | g_return_if_fail (gtk_widget_get_parent (child) == (GtkWidget *)box); |
611 | |
612 | gtk_widget_unparent (widget: child); |
613 | } |
614 | |