]> Pileus Git - ~andy/gtk/blob - gtk/gtkbox.c
Fix stupid error introduced last night that was making things decidedly
[~andy/gtk] / gtk / gtkbox.c
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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gtkbox.h"
28 #include "gtkintl.h"
29
30 enum {
31   PROP_0,
32   PROP_SPACING,
33   PROP_HOMOGENEOUS
34 };
35
36 enum {
37   CHILD_PROP_0,
38   CHILD_PROP_EXPAND,
39   CHILD_PROP_FILL,
40   CHILD_PROP_PADDING,
41   CHILD_PROP_PACK_TYPE,
42   CHILD_PROP_POSITION
43 };
44
45 static void gtk_box_class_init (GtkBoxClass    *klass);
46 static void gtk_box_init       (GtkBox         *box);
47 static void gtk_box_set_property (GObject         *object,
48                                   guint            prop_id,
49                                   const GValue    *value,
50                                   GParamSpec      *pspec);
51 static void gtk_box_get_property (GObject         *object,
52                                   guint            prop_id,
53                                   GValue          *value,
54                                   GParamSpec      *pspec);
55 static void gtk_box_map        (GtkWidget      *widget);
56 static void gtk_box_unmap      (GtkWidget      *widget);
57 static void gtk_box_add        (GtkContainer   *container,
58                                 GtkWidget      *widget);
59 static void gtk_box_remove     (GtkContainer   *container,
60                                 GtkWidget      *widget);
61 static void gtk_box_forall     (GtkContainer   *container,
62                                 gboolean        include_internals,
63                                 GtkCallback     callback,
64                                 gpointer        callback_data);
65 static void gtk_box_set_child_property (GtkContainer    *container,
66                                         GtkWidget       *child,
67                                         guint            property_id,
68                                         const GValue    *value,
69                                         GParamSpec      *pspec);
70 static void gtk_box_get_child_property (GtkContainer    *container,
71                                         GtkWidget       *child,
72                                         guint            property_id,
73                                         GValue          *value,
74                                         GParamSpec      *pspec);
75 static GtkType gtk_box_child_type (GtkContainer   *container);
76      
77
78 static GtkContainerClass *parent_class = NULL;
79
80
81 GtkType
82 gtk_box_get_type (void)
83 {
84   static GtkType box_type = 0;
85
86   if (!box_type)
87     {
88       static const GtkTypeInfo box_info =
89       {
90         "GtkBox",
91         sizeof (GtkBox),
92         sizeof (GtkBoxClass),
93         (GtkClassInitFunc) gtk_box_class_init,
94         (GtkObjectInitFunc) gtk_box_init,
95         /* reserved_1 */ NULL,
96         /* reserved_2 */ NULL,
97         (GtkClassInitFunc) NULL,
98       };
99
100       box_type = gtk_type_unique (GTK_TYPE_CONTAINER, &box_info);
101     }
102
103   return box_type;
104 }
105
106 static void
107 gtk_box_class_init (GtkBoxClass *class)
108 {
109   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
110   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
111   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
112
113   parent_class = g_type_class_peek_parent (class);
114
115   gobject_class->set_property = gtk_box_set_property;
116   gobject_class->get_property = gtk_box_get_property;
117    
118   widget_class->map = gtk_box_map;
119   widget_class->unmap = gtk_box_unmap;
120
121   container_class->add = gtk_box_add;
122   container_class->remove = gtk_box_remove;
123   container_class->forall = gtk_box_forall;
124   container_class->child_type = gtk_box_child_type;
125   container_class->set_child_property = gtk_box_set_child_property;
126   container_class->get_child_property = gtk_box_get_child_property;
127
128   g_object_class_install_property (gobject_class,
129                                    PROP_SPACING,
130                                    g_param_spec_int ("spacing",
131                                                      _("Spacing"),
132                                                      _("The amount of space between children."),
133                                                      0,
134                                                      G_MAXINT,
135                                                      0,
136                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
137   
138   g_object_class_install_property (gobject_class,
139                                    PROP_HOMOGENEOUS,
140                                    g_param_spec_boolean ("homogeneous",
141                                                          _("Homogeneous"),
142                                                          _("Whether the children should all be the same size."),
143                                                          FALSE,
144                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
145
146   gtk_container_class_install_child_property (container_class,
147                                               CHILD_PROP_EXPAND,
148                                               g_param_spec_boolean ("expand", NULL, NULL,
149                                                                     TRUE,
150                                                                     G_PARAM_READWRITE));
151   gtk_container_class_install_child_property (container_class,
152                                               CHILD_PROP_FILL,
153                                               g_param_spec_boolean ("fill", NULL, NULL,
154                                                                     TRUE,
155                                                                     G_PARAM_READWRITE));
156   gtk_container_class_install_child_property (container_class,
157                                               CHILD_PROP_PADDING,
158                                               g_param_spec_uint ("padding", NULL, NULL,
159                                                                  0, G_MAXINT, 0,
160                                                                  G_PARAM_READWRITE));
161   gtk_container_class_install_child_property (container_class,
162                                               CHILD_PROP_PACK_TYPE,
163                                               g_param_spec_enum ("pack_type", NULL, NULL,
164                                                                  GTK_TYPE_PACK_TYPE, GTK_PACK_START,
165                                                                  G_PARAM_READWRITE));
166   gtk_container_class_install_child_property (container_class,
167                                               CHILD_PROP_POSITION,
168                                               g_param_spec_int ("position", NULL, NULL,
169                                                                 -1, G_MAXINT, 0,
170                                                                 G_PARAM_READWRITE));
171 }
172
173 static void
174 gtk_box_init (GtkBox *box)
175 {
176   GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW);
177
178   box->children = NULL;
179   box->spacing = 0;
180   box->homogeneous = FALSE;
181 }
182
183 static void 
184 gtk_box_set_property (GObject         *object,
185                       guint            prop_id,
186                       const GValue    *value,
187                       GParamSpec      *pspec)
188 {
189   GtkBox *box;
190
191   box = GTK_BOX (object);
192
193   switch (prop_id)
194     {
195     case PROP_SPACING:
196       gtk_box_set_spacing (box, g_value_get_int (value));
197       break;
198     case PROP_HOMOGENEOUS:
199       gtk_box_set_homogeneous (box, g_value_get_boolean (value));
200       break;
201     default:
202       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
203       break;
204     }
205 }
206
207 static void gtk_box_get_property (GObject         *object,
208                                   guint            prop_id,
209                                   GValue          *value,
210                                   GParamSpec      *pspec)
211 {
212   GtkBox *box;
213
214   box = GTK_BOX (object);
215
216   switch (prop_id)
217     {
218     case PROP_SPACING:
219       g_value_set_int (value, box->spacing);
220       break;
221     case PROP_HOMOGENEOUS:
222       g_value_set_boolean (value, box->homogeneous);
223       break;
224     default:
225       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
226       break;
227     }
228 }
229
230 static GtkType
231 gtk_box_child_type      (GtkContainer   *container)
232 {
233   return GTK_TYPE_WIDGET;
234 }
235
236 static void
237 gtk_box_set_child_property (GtkContainer    *container,
238                             GtkWidget       *child,
239                             guint            property_id,
240                             const GValue    *value,
241                             GParamSpec      *pspec)
242 {
243   gboolean expand = 0;
244   gboolean fill = 0;
245   guint padding = 0;
246   GtkPackType pack_type = 0;
247
248   if (property_id != CHILD_PROP_POSITION)
249     gtk_box_query_child_packing (GTK_BOX (container),
250                                  child,
251                                  &expand,
252                                  &fill,
253                                  &padding,
254                                  &pack_type);
255   switch (property_id)
256     {
257     case CHILD_PROP_EXPAND:
258       gtk_box_set_child_packing (GTK_BOX (container),
259                                  child,
260                                  g_value_get_boolean (value),
261                                  fill,
262                                  padding,
263                                  pack_type);
264       break;
265     case CHILD_PROP_FILL:
266       gtk_box_set_child_packing (GTK_BOX (container),
267                                  child,
268                                  expand,
269                                  g_value_get_boolean (value),
270                                  padding,
271                                  pack_type);
272       break;
273     case CHILD_PROP_PADDING:
274       gtk_box_set_child_packing (GTK_BOX (container),
275                                  child,
276                                  expand,
277                                  fill,
278                                  g_value_get_uint (value),
279                                  pack_type);
280       break;
281     case CHILD_PROP_PACK_TYPE:
282       gtk_box_set_child_packing (GTK_BOX (container),
283                                  child,
284                                  expand,
285                                  fill,
286                                  padding,
287                                  g_value_get_enum (value));
288       break;
289     case CHILD_PROP_POSITION:
290       gtk_box_reorder_child (GTK_BOX (container),
291                              child,
292                              g_value_get_int (value));
293       break;
294     default:
295       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
296       break;
297     }
298 }
299
300 static void
301 gtk_box_get_child_property (GtkContainer *container,
302                             GtkWidget    *child,
303                             guint         property_id,
304                             GValue       *value,
305                             GParamSpec   *pspec)
306 {
307   gboolean expand = 0;
308   gboolean fill = 0;
309   guint padding = 0;
310   GtkPackType pack_type = 0;
311   GList *list;
312
313   if (property_id != CHILD_PROP_POSITION)
314     gtk_box_query_child_packing (GTK_BOX (container),
315                                  child,
316                                  &expand,
317                                  &fill,
318                                  &padding,
319                                  &pack_type);
320   switch (property_id)
321     {
322       guint i;
323     case CHILD_PROP_EXPAND:
324       g_value_set_boolean (value, expand);
325       break;
326     case CHILD_PROP_FILL:
327       g_value_set_boolean (value, fill);
328       break;
329     case CHILD_PROP_PADDING:
330       g_value_set_uint (value, padding);
331       break;
332     case CHILD_PROP_PACK_TYPE:
333       g_value_set_enum (value, pack_type);
334       break;
335     case CHILD_PROP_POSITION:
336       i = 0;
337       for (list = GTK_BOX (container)->children; list; list = list->next)
338         {
339           GtkBoxChild *child_entry;
340
341           child_entry = list->data;
342           if (child_entry->widget == child)
343             break;
344           i++;
345         }
346       g_value_set_int (value, list ? i : -1);
347       break;
348     default:
349       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
350       break;
351     }
352 }
353
354 void
355 gtk_box_pack_start (GtkBox    *box,
356                     GtkWidget *child,
357                     gboolean   expand,
358                     gboolean   fill,
359                     guint      padding)
360 {
361   GtkBoxChild *child_info;
362
363   g_return_if_fail (box != NULL);
364   g_return_if_fail (GTK_IS_BOX (box));
365   g_return_if_fail (child != NULL);
366   g_return_if_fail (child->parent == NULL);
367
368   child_info = g_new (GtkBoxChild, 1);
369   child_info->widget = child;
370   child_info->padding = padding;
371   child_info->expand = expand ? TRUE : FALSE;
372   child_info->fill = fill ? TRUE : FALSE;
373   child_info->pack = GTK_PACK_START;
374
375   box->children = g_list_append (box->children, child_info);
376
377   gtk_widget_freeze_child_notify (child);
378
379   gtk_widget_set_parent (child, GTK_WIDGET (box));
380   
381   if (GTK_WIDGET_REALIZED (box))
382     gtk_widget_realize (child);
383
384   if (GTK_WIDGET_VISIBLE (box) && GTK_WIDGET_VISIBLE (child))
385     {
386       if (GTK_WIDGET_MAPPED (box))
387         gtk_widget_map (child);
388
389       gtk_widget_queue_resize (child);
390     }
391   gtk_widget_child_notify (child, "expand");
392   gtk_widget_child_notify (child, "fill");
393   gtk_widget_child_notify (child, "padding");
394   gtk_widget_child_notify (child, "pack_type");
395   gtk_widget_child_notify (child, "position");
396   gtk_widget_thaw_child_notify (child);
397 }
398
399 void
400 gtk_box_pack_end (GtkBox    *box,
401                   GtkWidget *child,
402                   gboolean   expand,
403                   gboolean   fill,
404                   guint      padding)
405 {
406   GtkBoxChild *child_info;
407
408   g_return_if_fail (box != NULL);
409   g_return_if_fail (GTK_IS_BOX (box));
410   g_return_if_fail (child != NULL);
411   g_return_if_fail (child->parent == NULL);
412
413   child_info = g_new (GtkBoxChild, 1);
414   child_info->widget = child;
415   child_info->padding = padding;
416   child_info->expand = expand ? TRUE : FALSE;
417   child_info->fill = fill ? TRUE : FALSE;
418   child_info->pack = GTK_PACK_END;
419
420   box->children = g_list_append (box->children, child_info);
421
422   gtk_widget_freeze_child_notify (child);
423
424   gtk_widget_set_parent (child, GTK_WIDGET (box));
425
426   if (GTK_WIDGET_REALIZED (box))
427     gtk_widget_realize (child);
428
429   if (GTK_WIDGET_VISIBLE (box) && GTK_WIDGET_VISIBLE (child))
430     {
431       if (GTK_WIDGET_MAPPED (box))
432         gtk_widget_map (child);
433
434       gtk_widget_queue_resize (child);
435     }
436   gtk_widget_child_notify (child, "expand");
437   gtk_widget_child_notify (child, "fill");
438   gtk_widget_child_notify (child, "padding");
439   gtk_widget_child_notify (child, "pack_type");
440   gtk_widget_child_notify (child, "position");
441   gtk_widget_thaw_child_notify (child);
442 }
443
444 void
445 gtk_box_pack_start_defaults (GtkBox    *box,
446                              GtkWidget *child)
447 {
448   g_return_if_fail (box != NULL);
449   g_return_if_fail (GTK_IS_BOX (box));
450   g_return_if_fail (child != NULL);
451
452   gtk_box_pack_start (box, child, TRUE, TRUE, 0);
453 }
454
455 void
456 gtk_box_pack_end_defaults (GtkBox    *box,
457                            GtkWidget *child)
458 {
459   g_return_if_fail (box != NULL);
460   g_return_if_fail (GTK_IS_BOX (box));
461   g_return_if_fail (child != NULL);
462
463   gtk_box_pack_end (box, child, TRUE, TRUE, 0);
464 }
465
466 void
467 gtk_box_set_homogeneous (GtkBox  *box,
468                          gboolean homogeneous)
469 {
470   g_return_if_fail (box != NULL);
471   g_return_if_fail (GTK_IS_BOX (box));
472
473   if ((homogeneous ? TRUE : FALSE) != box->homogeneous)
474     {
475       box->homogeneous = homogeneous ? TRUE : FALSE;
476       g_object_notify (G_OBJECT (box), "homogeneous");
477       gtk_widget_queue_resize (GTK_WIDGET (box));
478     }
479 }
480
481 /**
482  * gtk_box_get_homogeneous:
483  * @box: a #GtkBox
484  *
485  * Returns whether the box is homogeneous (all children are the
486  * same size). See gtk_box_set_homogeneous ().
487  *
488  * Return value: %TRUE if the box is homogeneous.
489  **/
490 gboolean
491 gtk_box_get_homogeneous (GtkBox *box)
492 {
493   g_return_val_if_fail (GTK_IS_BOX (box), FALSE);
494
495   return box->homogeneous;
496 }
497
498 void
499 gtk_box_set_spacing (GtkBox *box,
500                      gint    spacing)
501 {
502   g_return_if_fail (box != NULL);
503   g_return_if_fail (GTK_IS_BOX (box));
504
505   if (spacing != box->spacing)
506     {
507       box->spacing = spacing;
508       g_object_notify (G_OBJECT (box), "spacing");
509       gtk_widget_queue_resize (GTK_WIDGET (box));
510     }
511 }
512
513 /**
514  * gtk_box_get_spacing:
515  * @box: a #GtkBox
516  * 
517  * Gets the value set by gtk_box_set_spacing().
518  * 
519  * Return value: spacing between children
520  **/
521 gint
522 gtk_box_get_spacing (GtkBox *box)
523 {
524   g_return_val_if_fail (GTK_IS_BOX (box), 0);
525
526   return box->spacing;
527 }
528
529 void
530 gtk_box_reorder_child (GtkBox    *box,
531                        GtkWidget *child,
532                        gint       position)
533 {
534   GList *list;
535
536   g_return_if_fail (box != NULL);
537   g_return_if_fail (GTK_IS_BOX (box));
538   g_return_if_fail (child != NULL);
539
540   list = box->children;
541   while (list)
542     {
543       GtkBoxChild *child_info;
544
545       child_info = list->data;
546       if (child_info->widget == child)
547         break;
548
549       list = list->next;
550     }
551
552   if (list && box->children->next)
553     {
554       GList *tmp_list;
555
556       if (list->next)
557         list->next->prev = list->prev;
558       if (list->prev)
559         list->prev->next = list->next;
560       else
561         box->children = list->next;
562
563       tmp_list = box->children;
564       while (position && tmp_list->next)
565         {
566           position--;
567           tmp_list = tmp_list->next;
568         }
569
570       if (position)
571         {
572           tmp_list->next = list;
573           list->prev = tmp_list;
574           list->next = NULL;
575         }
576       else
577         {
578           if (tmp_list->prev)
579             tmp_list->prev->next = list;
580           else
581             box->children = list;
582           list->prev = tmp_list->prev;
583           tmp_list->prev = list;
584           list->next = tmp_list;
585         }
586
587       gtk_widget_child_notify (child, "position");
588       if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
589         gtk_widget_queue_resize (child);
590     }
591 }
592
593 void
594 gtk_box_query_child_packing (GtkBox             *box,
595                              GtkWidget          *child,
596                              gboolean           *expand,
597                              gboolean           *fill,
598                              guint              *padding,
599                              GtkPackType        *pack_type)
600 {
601   GList *list;
602   GtkBoxChild *child_info = NULL;
603
604   g_return_if_fail (box != NULL);
605   g_return_if_fail (GTK_IS_BOX (box));
606   g_return_if_fail (child != NULL);
607
608   list = box->children;
609   while (list)
610     {
611       child_info = list->data;
612       if (child_info->widget == child)
613         break;
614
615       list = list->next;
616     }
617
618   if (list)
619     {
620       if (expand)
621         *expand = child_info->expand;
622       if (fill)
623         *fill = child_info->fill;
624       if (padding)
625         *padding = child_info->padding;
626       if (pack_type)
627         *pack_type = child_info->pack;
628     }
629 }
630
631 void
632 gtk_box_set_child_packing (GtkBox               *box,
633                            GtkWidget            *child,
634                            gboolean              expand,
635                            gboolean              fill,
636                            guint                 padding,
637                            GtkPackType           pack_type)
638 {
639   GList *list;
640   GtkBoxChild *child_info = NULL;
641
642   g_return_if_fail (box != NULL);
643   g_return_if_fail (GTK_IS_BOX (box));
644   g_return_if_fail (child != NULL);
645
646   list = box->children;
647   while (list)
648     {
649       child_info = list->data;
650       if (child_info->widget == child)
651         break;
652
653       list = list->next;
654     }
655
656   gtk_widget_freeze_child_notify (child);
657   if (list)
658     {
659       child_info->expand = expand != FALSE;
660       gtk_widget_child_notify (child, "expand");
661       child_info->fill = fill != FALSE;
662       gtk_widget_child_notify (child, "fill");
663       child_info->padding = padding;
664       gtk_widget_child_notify (child, "padding");
665       if (pack_type == GTK_PACK_END)
666         child_info->pack = GTK_PACK_END;
667       else
668         child_info->pack = GTK_PACK_START;
669       gtk_widget_child_notify (child, "pack_type");
670
671       if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
672         gtk_widget_queue_resize (child);
673     }
674   gtk_widget_thaw_child_notify (child);
675 }
676
677 static void
678 gtk_box_map (GtkWidget *widget)
679 {
680   GtkBox *box;
681   GtkBoxChild *child;
682   GList *children;
683
684   g_return_if_fail (widget != NULL);
685   g_return_if_fail (GTK_IS_BOX (widget));
686
687   box = GTK_BOX (widget);
688   GTK_WIDGET_SET_FLAGS (box, GTK_MAPPED);
689
690   children = box->children;
691   while (children)
692     {
693       child = children->data;
694       children = children->next;
695
696       if (GTK_WIDGET_VISIBLE (child->widget) &&
697           !GTK_WIDGET_MAPPED (child->widget))
698         gtk_widget_map (child->widget);
699     }
700 }
701
702 static void
703 gtk_box_unmap (GtkWidget *widget)
704 {
705   GtkBox *box;
706   GtkBoxChild *child;
707   GList *children;
708
709   g_return_if_fail (widget != NULL);
710   g_return_if_fail (GTK_IS_BOX (widget));
711
712   box = GTK_BOX (widget);
713   GTK_WIDGET_UNSET_FLAGS (box, GTK_MAPPED);
714
715   children = box->children;
716   while (children)
717     {
718       child = children->data;
719       children = children->next;
720
721       if (GTK_WIDGET_VISIBLE (child->widget) &&
722           GTK_WIDGET_MAPPED (child->widget))
723         gtk_widget_unmap (child->widget);
724     }
725 }
726
727 static void
728 gtk_box_add (GtkContainer *container,
729              GtkWidget    *widget)
730 {
731   g_return_if_fail (container != NULL);
732   g_return_if_fail (GTK_IS_BOX (container));
733   g_return_if_fail (widget != NULL);
734
735   gtk_box_pack_start_defaults (GTK_BOX (container), widget);
736 }
737
738 static void
739 gtk_box_remove (GtkContainer *container,
740                 GtkWidget    *widget)
741 {
742   GtkBox *box;
743   GtkBoxChild *child;
744   GList *children;
745
746   g_return_if_fail (container != NULL);
747   g_return_if_fail (GTK_IS_BOX (container));
748   g_return_if_fail (widget != NULL);
749
750   box = GTK_BOX (container);
751
752   children = box->children;
753   while (children)
754     {
755       child = children->data;
756
757       if (child->widget == widget)
758         {
759           gboolean was_visible;
760
761           was_visible = GTK_WIDGET_VISIBLE (widget);
762           gtk_widget_unparent (widget);
763
764           box->children = g_list_remove_link (box->children, children);
765           g_list_free (children);
766           g_free (child);
767
768           /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
769            * since that's what is needed by toplevels.
770            */
771           if (was_visible)
772             gtk_widget_queue_resize (GTK_WIDGET (container));
773
774           break;
775         }
776
777       children = children->next;
778     }
779 }
780
781 static void
782 gtk_box_forall (GtkContainer *container,
783                 gboolean      include_internals,
784                 GtkCallback   callback,
785                 gpointer      callback_data)
786 {
787   GtkBox *box;
788   GtkBoxChild *child;
789   GList *children;
790
791   g_return_if_fail (container != NULL);
792   g_return_if_fail (GTK_IS_BOX (container));
793   g_return_if_fail (callback != NULL);
794
795   box = GTK_BOX (container);
796
797   children = box->children;
798   while (children)
799     {
800       child = children->data;
801       children = children->next;
802
803       if (child->pack == GTK_PACK_START)
804         (* callback) (child->widget, callback_data);
805     }
806
807   children = g_list_last (box->children);
808   while (children)
809     {
810       child = children->data;
811       children = children->prev;
812
813       if (child->pack == GTK_PACK_END)
814         (* callback) (child->widget, callback_data);
815     }
816 }