]> Pileus Git - ~andy/gtk/blob - gtk/gtkbox.c
979bf02ee96b6eee12cde7a4313cf6a56d1e2573
[~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   child_info->is_secondary = FALSE;
375
376   box->children = g_list_append (box->children, child_info);
377
378   gtk_widget_freeze_child_notify (child);
379
380   gtk_widget_set_parent (child, GTK_WIDGET (box));
381   
382   if (GTK_WIDGET_REALIZED (box))
383     gtk_widget_realize (child);
384
385   if (GTK_WIDGET_VISIBLE (box) && GTK_WIDGET_VISIBLE (child))
386     {
387       if (GTK_WIDGET_MAPPED (box))
388         gtk_widget_map (child);
389
390       gtk_widget_queue_resize (child);
391     }
392   gtk_widget_child_notify (child, "expand");
393   gtk_widget_child_notify (child, "fill");
394   gtk_widget_child_notify (child, "padding");
395   gtk_widget_child_notify (child, "pack_type");
396   gtk_widget_child_notify (child, "position");
397   gtk_widget_thaw_child_notify (child);
398 }
399
400 void
401 gtk_box_pack_end (GtkBox    *box,
402                   GtkWidget *child,
403                   gboolean   expand,
404                   gboolean   fill,
405                   guint      padding)
406 {
407   GtkBoxChild *child_info;
408
409   g_return_if_fail (box != NULL);
410   g_return_if_fail (GTK_IS_BOX (box));
411   g_return_if_fail (child != NULL);
412   g_return_if_fail (child->parent == NULL);
413
414   child_info = g_new (GtkBoxChild, 1);
415   child_info->widget = child;
416   child_info->padding = padding;
417   child_info->expand = expand ? TRUE : FALSE;
418   child_info->fill = fill ? TRUE : FALSE;
419   child_info->pack = GTK_PACK_END;
420   child_info->is_secondary = FALSE;
421
422   box->children = g_list_append (box->children, child_info);
423
424   gtk_widget_freeze_child_notify (child);
425
426   gtk_widget_set_parent (child, GTK_WIDGET (box));
427
428   if (GTK_WIDGET_REALIZED (box))
429     gtk_widget_realize (child);
430
431   if (GTK_WIDGET_VISIBLE (box) && GTK_WIDGET_VISIBLE (child))
432     {
433       if (GTK_WIDGET_MAPPED (box))
434         gtk_widget_map (child);
435
436       gtk_widget_queue_resize (child);
437     }
438   gtk_widget_child_notify (child, "expand");
439   gtk_widget_child_notify (child, "fill");
440   gtk_widget_child_notify (child, "padding");
441   gtk_widget_child_notify (child, "pack_type");
442   gtk_widget_child_notify (child, "position");
443   gtk_widget_thaw_child_notify (child);
444 }
445
446 void
447 gtk_box_pack_start_defaults (GtkBox    *box,
448                              GtkWidget *child)
449 {
450   g_return_if_fail (box != NULL);
451   g_return_if_fail (GTK_IS_BOX (box));
452   g_return_if_fail (child != NULL);
453
454   gtk_box_pack_start (box, child, TRUE, TRUE, 0);
455 }
456
457 void
458 gtk_box_pack_end_defaults (GtkBox    *box,
459                            GtkWidget *child)
460 {
461   g_return_if_fail (box != NULL);
462   g_return_if_fail (GTK_IS_BOX (box));
463   g_return_if_fail (child != NULL);
464
465   gtk_box_pack_end (box, child, TRUE, TRUE, 0);
466 }
467
468 void
469 gtk_box_set_homogeneous (GtkBox  *box,
470                          gboolean homogeneous)
471 {
472   g_return_if_fail (box != NULL);
473   g_return_if_fail (GTK_IS_BOX (box));
474
475   if ((homogeneous ? TRUE : FALSE) != box->homogeneous)
476     {
477       box->homogeneous = homogeneous ? TRUE : FALSE;
478       g_object_notify (G_OBJECT (box), "homogeneous");
479       gtk_widget_queue_resize (GTK_WIDGET (box));
480     }
481 }
482
483 /**
484  * gtk_box_get_homogeneous:
485  * @box: a #GtkBox
486  *
487  * Returns whether the box is homogeneous (all children are the
488  * same size). See gtk_box_set_homogeneous ().
489  *
490  * Return value: %TRUE if the box is homogeneous.
491  **/
492 gboolean
493 gtk_box_get_homogeneous (GtkBox *box)
494 {
495   g_return_val_if_fail (GTK_IS_BOX (box), FALSE);
496
497   return box->homogeneous;
498 }
499
500 void
501 gtk_box_set_spacing (GtkBox *box,
502                      gint    spacing)
503 {
504   g_return_if_fail (box != NULL);
505   g_return_if_fail (GTK_IS_BOX (box));
506
507   if (spacing != box->spacing)
508     {
509       box->spacing = spacing;
510       g_object_notify (G_OBJECT (box), "spacing");
511       gtk_widget_queue_resize (GTK_WIDGET (box));
512     }
513 }
514
515 /**
516  * gtk_box_get_spacing:
517  * @box: a #GtkBox
518  * 
519  * Gets the value set by gtk_box_set_spacing().
520  * 
521  * Return value: spacing between children
522  **/
523 gint
524 gtk_box_get_spacing (GtkBox *box)
525 {
526   g_return_val_if_fail (GTK_IS_BOX (box), 0);
527
528   return box->spacing;
529 }
530
531 void
532 gtk_box_reorder_child (GtkBox    *box,
533                        GtkWidget *child,
534                        gint       position)
535 {
536   GList *list;
537
538   g_return_if_fail (box != NULL);
539   g_return_if_fail (GTK_IS_BOX (box));
540   g_return_if_fail (child != NULL);
541
542   list = box->children;
543   while (list)
544     {
545       GtkBoxChild *child_info;
546
547       child_info = list->data;
548       if (child_info->widget == child)
549         break;
550
551       list = list->next;
552     }
553
554   if (list && box->children->next)
555     {
556       GList *tmp_list;
557
558       if (list->next)
559         list->next->prev = list->prev;
560       if (list->prev)
561         list->prev->next = list->next;
562       else
563         box->children = list->next;
564
565       tmp_list = box->children;
566       while (position && tmp_list->next)
567         {
568           position--;
569           tmp_list = tmp_list->next;
570         }
571
572       if (position)
573         {
574           tmp_list->next = list;
575           list->prev = tmp_list;
576           list->next = NULL;
577         }
578       else
579         {
580           if (tmp_list->prev)
581             tmp_list->prev->next = list;
582           else
583             box->children = list;
584           list->prev = tmp_list->prev;
585           tmp_list->prev = list;
586           list->next = tmp_list;
587         }
588
589       gtk_widget_child_notify (child, "position");
590       if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
591         gtk_widget_queue_resize (child);
592     }
593 }
594
595 void
596 gtk_box_query_child_packing (GtkBox             *box,
597                              GtkWidget          *child,
598                              gboolean           *expand,
599                              gboolean           *fill,
600                              guint              *padding,
601                              GtkPackType        *pack_type)
602 {
603   GList *list;
604   GtkBoxChild *child_info = NULL;
605
606   g_return_if_fail (box != NULL);
607   g_return_if_fail (GTK_IS_BOX (box));
608   g_return_if_fail (child != NULL);
609
610   list = box->children;
611   while (list)
612     {
613       child_info = list->data;
614       if (child_info->widget == child)
615         break;
616
617       list = list->next;
618     }
619
620   if (list)
621     {
622       if (expand)
623         *expand = child_info->expand;
624       if (fill)
625         *fill = child_info->fill;
626       if (padding)
627         *padding = child_info->padding;
628       if (pack_type)
629         *pack_type = child_info->pack;
630     }
631 }
632
633 void
634 gtk_box_set_child_packing (GtkBox               *box,
635                            GtkWidget            *child,
636                            gboolean              expand,
637                            gboolean              fill,
638                            guint                 padding,
639                            GtkPackType           pack_type)
640 {
641   GList *list;
642   GtkBoxChild *child_info = NULL;
643
644   g_return_if_fail (box != NULL);
645   g_return_if_fail (GTK_IS_BOX (box));
646   g_return_if_fail (child != NULL);
647
648   list = box->children;
649   while (list)
650     {
651       child_info = list->data;
652       if (child_info->widget == child)
653         break;
654
655       list = list->next;
656     }
657
658   gtk_widget_freeze_child_notify (child);
659   if (list)
660     {
661       child_info->expand = expand != FALSE;
662       gtk_widget_child_notify (child, "expand");
663       child_info->fill = fill != FALSE;
664       gtk_widget_child_notify (child, "fill");
665       child_info->padding = padding;
666       gtk_widget_child_notify (child, "padding");
667       if (pack_type == GTK_PACK_END)
668         child_info->pack = GTK_PACK_END;
669       else
670         child_info->pack = GTK_PACK_START;
671       gtk_widget_child_notify (child, "pack_type");
672
673       if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
674         gtk_widget_queue_resize (child);
675     }
676   gtk_widget_thaw_child_notify (child);
677 }
678
679 static void
680 gtk_box_map (GtkWidget *widget)
681 {
682   GtkBox *box;
683   GtkBoxChild *child;
684   GList *children;
685
686   g_return_if_fail (widget != NULL);
687   g_return_if_fail (GTK_IS_BOX (widget));
688
689   box = GTK_BOX (widget);
690   GTK_WIDGET_SET_FLAGS (box, GTK_MAPPED);
691
692   children = box->children;
693   while (children)
694     {
695       child = children->data;
696       children = children->next;
697
698       if (GTK_WIDGET_VISIBLE (child->widget) &&
699           !GTK_WIDGET_MAPPED (child->widget))
700         gtk_widget_map (child->widget);
701     }
702 }
703
704 static void
705 gtk_box_unmap (GtkWidget *widget)
706 {
707   GtkBox *box;
708   GtkBoxChild *child;
709   GList *children;
710
711   g_return_if_fail (widget != NULL);
712   g_return_if_fail (GTK_IS_BOX (widget));
713
714   box = GTK_BOX (widget);
715   GTK_WIDGET_UNSET_FLAGS (box, GTK_MAPPED);
716
717   children = box->children;
718   while (children)
719     {
720       child = children->data;
721       children = children->next;
722
723       if (GTK_WIDGET_VISIBLE (child->widget) &&
724           GTK_WIDGET_MAPPED (child->widget))
725         gtk_widget_unmap (child->widget);
726     }
727 }
728
729 static void
730 gtk_box_add (GtkContainer *container,
731              GtkWidget    *widget)
732 {
733   g_return_if_fail (container != NULL);
734   g_return_if_fail (GTK_IS_BOX (container));
735   g_return_if_fail (widget != NULL);
736
737   gtk_box_pack_start_defaults (GTK_BOX (container), widget);
738 }
739
740 static void
741 gtk_box_remove (GtkContainer *container,
742                 GtkWidget    *widget)
743 {
744   GtkBox *box;
745   GtkBoxChild *child;
746   GList *children;
747
748   g_return_if_fail (container != NULL);
749   g_return_if_fail (GTK_IS_BOX (container));
750   g_return_if_fail (widget != NULL);
751
752   box = GTK_BOX (container);
753
754   children = box->children;
755   while (children)
756     {
757       child = children->data;
758
759       if (child->widget == widget)
760         {
761           gboolean was_visible;
762
763           was_visible = GTK_WIDGET_VISIBLE (widget);
764           gtk_widget_unparent (widget);
765
766           box->children = g_list_remove_link (box->children, children);
767           g_list_free (children);
768           g_free (child);
769
770           /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
771            * since that's what is needed by toplevels.
772            */
773           if (was_visible)
774             gtk_widget_queue_resize (GTK_WIDGET (container));
775
776           break;
777         }
778
779       children = children->next;
780     }
781 }
782
783 static void
784 gtk_box_forall (GtkContainer *container,
785                 gboolean      include_internals,
786                 GtkCallback   callback,
787                 gpointer      callback_data)
788 {
789   GtkBox *box;
790   GtkBoxChild *child;
791   GList *children;
792
793   g_return_if_fail (container != NULL);
794   g_return_if_fail (GTK_IS_BOX (container));
795   g_return_if_fail (callback != NULL);
796
797   box = GTK_BOX (container);
798
799   children = box->children;
800   while (children)
801     {
802       child = children->data;
803       children = children->next;
804
805       if (child->pack == GTK_PACK_START)
806         (* callback) (child->widget, callback_data);
807     }
808
809   children = g_list_last (box->children);
810   while (children)
811     {
812       child = children->data;
813       children = children->prev;
814
815       if (child->pack == GTK_PACK_END)
816         (* callback) (child->widget, callback_data);
817     }
818 }