]> Pileus Git - ~andy/gtk/blob - gtk/gtkcontainer.c
main part for GtkArgSetFunc/GtkArgGetFunc implementation.
[~andy/gtk] / gtk / gtkcontainer.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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <string.h>
19 #include "gtkcontainer.h"
20 #include "gtksignal.h"
21
22
23 enum {
24   ADD,
25   REMOVE,
26   NEED_RESIZE,
27   FOREACH,
28   FOCUS,
29   LAST_SIGNAL
30 };
31 enum {
32   ARG_0,
33   ARG_BORDER_WIDTH,
34   ARG_AUTO_RESIZE,
35   ARG_BLOCK_RESIZE,
36   ARG_CHILD
37 };
38
39
40 typedef void (*GtkContainerSignal1) (GtkObject *object,
41                                      gpointer   arg1,
42                                      gpointer   data);
43 typedef void (*GtkContainerSignal2) (GtkObject *object,
44                                      gpointer   arg1,
45                                      gpointer   arg2,
46                                      gpointer   data);
47 typedef gint (*GtkContainerSignal3) (GtkObject *object,
48                                      gint       arg1,
49                                      gpointer   data);
50 typedef gint (*GtkContainerSignal4) (GtkObject *object,
51                                      gpointer   data);
52
53
54 static void gtk_container_marshal_signal_1 (GtkObject      *object,
55                                             GtkSignalFunc   func,
56                                             gpointer        func_data,
57                                             GtkArg         *args);
58 static void gtk_container_marshal_signal_2 (GtkObject      *object,
59                                             GtkSignalFunc   func,
60                                             gpointer        func_data,
61                                             GtkArg         *args);
62 static void gtk_container_marshal_signal_3 (GtkObject      *object,
63                                             GtkSignalFunc   func,
64                                             gpointer        func_data,
65                                             GtkArg         *args);
66 static void gtk_container_marshal_signal_4 (GtkObject      *object,
67                                             GtkSignalFunc   func,
68                                             gpointer        func_data,
69                                             GtkArg         *args);
70
71
72 static void gtk_container_class_init        (GtkContainerClass *klass);
73 static void gtk_container_init              (GtkContainer      *container);
74 static void gtk_container_set_arg           (GtkContainer      *container,
75                                              GtkArg            *arg,
76                                              guint              arg_id);
77 static gint gtk_real_container_need_resize  (GtkContainer      *container);
78 static gint gtk_real_container_focus        (GtkContainer      *container,
79                                              GtkDirectionType   direction);
80 static gint gtk_container_focus_tab         (GtkContainer      *container,
81                                              GList             *children,
82                                              GtkDirectionType   direction);
83 static gint gtk_container_focus_up_down     (GtkContainer      *container,
84                                              GList             *children,
85                                              GtkDirectionType   direction);
86 static gint gtk_container_focus_left_right  (GtkContainer      *container,
87                                              GList             *children,
88                                              GtkDirectionType   direction);
89 static gint gtk_container_focus_move        (GtkContainer      *container,
90                                              GList             *children,
91                                              GtkDirectionType   direction);
92 static void gtk_container_children_callback (GtkWidget         *widget,
93                                              gpointer           client_data);
94 static void gtk_container_show_all          (GtkWidget         *widget);
95 static void gtk_container_hide_all          (GtkWidget         *widget);
96
97
98
99 static gint container_signals[LAST_SIGNAL] = { 0 };
100
101
102 guint
103 gtk_container_get_type ()
104 {
105   static guint container_type = 0;
106
107   if (!container_type)
108     {
109       GtkTypeInfo container_info =
110       {
111         "GtkContainer",
112         sizeof (GtkContainer),
113         sizeof (GtkContainerClass),
114         (GtkClassInitFunc) gtk_container_class_init,
115         (GtkObjectInitFunc) gtk_container_init,
116         (GtkArgSetFunc) gtk_container_set_arg,
117         (GtkArgGetFunc) NULL,
118       };
119
120       container_type = gtk_type_unique (gtk_widget_get_type (), &container_info);
121     }
122
123   return container_type;
124 }
125
126 static void
127 gtk_container_class_init (GtkContainerClass *class)
128 {
129   GtkObjectClass *object_class;
130   GtkWidgetClass *widget_class;
131
132   object_class = (GtkObjectClass*) class;
133   widget_class = (GtkWidgetClass*) class;
134
135   gtk_object_add_arg_type ("GtkContainer::border_width", GTK_TYPE_LONG, ARG_BORDER_WIDTH);
136   gtk_object_add_arg_type ("GtkContainer::auto_resize", GTK_TYPE_BOOL, ARG_AUTO_RESIZE);
137   gtk_object_add_arg_type ("GtkContainer::block_resize", GTK_TYPE_BOOL, ARG_BLOCK_RESIZE);
138   gtk_object_add_arg_type ("GtkContainer::child", GTK_TYPE_WIDGET, ARG_CHILD);
139
140   container_signals[ADD] =
141     gtk_signal_new ("add",
142                     GTK_RUN_FIRST,
143                     object_class->type,
144                     GTK_SIGNAL_OFFSET (GtkContainerClass, add),
145                     gtk_container_marshal_signal_1,
146                     GTK_TYPE_NONE, 1,
147                     GTK_TYPE_WIDGET);
148   container_signals[REMOVE] =
149     gtk_signal_new ("remove",
150                     GTK_RUN_FIRST,
151                     object_class->type,
152                     GTK_SIGNAL_OFFSET (GtkContainerClass, remove),
153                     gtk_container_marshal_signal_1,
154                     GTK_TYPE_NONE, 1,
155                     GTK_TYPE_WIDGET);
156   container_signals[NEED_RESIZE] =
157     gtk_signal_new ("need_resize",
158                     GTK_RUN_FIRST,
159                     object_class->type,
160                     GTK_SIGNAL_OFFSET (GtkContainerClass, need_resize),
161                     gtk_container_marshal_signal_4,
162                     GTK_TYPE_BOOL, 0,
163                     GTK_TYPE_WIDGET);
164   container_signals[FOREACH] =
165     gtk_signal_new ("foreach",
166                     GTK_RUN_FIRST,
167                     object_class->type,
168                     GTK_SIGNAL_OFFSET (GtkContainerClass, foreach),
169                     gtk_container_marshal_signal_2,
170                     GTK_TYPE_NONE, 1,
171                     GTK_TYPE_C_CALLBACK);
172   container_signals[FOCUS] =
173     gtk_signal_new ("focus",
174                     GTK_RUN_FIRST,
175                     object_class->type,
176                     GTK_SIGNAL_OFFSET (GtkContainerClass, focus),
177                     gtk_container_marshal_signal_3,
178                     GTK_TYPE_DIRECTION_TYPE, 1,
179                     GTK_TYPE_DIRECTION_TYPE);
180
181   gtk_object_class_add_signals (object_class, container_signals, LAST_SIGNAL);
182
183   /* Other container classes should overwrite show_all and hide_all,
184      unless they make all their children accessable
185      through gtk_container_foreach.
186   */
187   widget_class->show_all = gtk_container_show_all;
188   widget_class->hide_all = gtk_container_hide_all;  
189   
190   class->need_resize = gtk_real_container_need_resize;
191   class->focus = gtk_real_container_focus;
192 }
193
194 static void
195 gtk_container_init (GtkContainer *container)
196 {
197   container->focus_child = NULL;
198   container->border_width = 0;
199   container->auto_resize = TRUE;
200   container->need_resize = FALSE;
201   container->block_resize = FALSE;
202 }
203
204 static void
205 gtk_container_set_arg (GtkContainer *container,
206                        GtkArg       *arg,
207                        guint         arg_id)
208 {
209   switch (arg_id)
210     {
211     case ARG_BORDER_WIDTH:
212       gtk_container_border_width (container, GTK_VALUE_LONG (*arg));
213       break;
214     case ARG_AUTO_RESIZE:
215       if (GTK_VALUE_BOOL (*arg))
216         gtk_container_enable_resize (container);
217       else
218         gtk_container_disable_resize (container);
219       break;
220     case ARG_BLOCK_RESIZE:
221       if (GTK_VALUE_BOOL (*arg))
222         gtk_container_block_resize (container);
223       else
224         gtk_container_unblock_resize (container);
225       break;
226     case ARG_CHILD:
227       gtk_container_add (container, GTK_WIDGET (GTK_VALUE_OBJECT (*arg)));
228       break;
229     default:
230       g_assert_not_reached ();
231     }
232 }
233
234 void
235 gtk_container_border_width (GtkContainer *container,
236                             gint          border_width)
237 {
238   g_return_if_fail (container != NULL);
239   g_return_if_fail (GTK_IS_CONTAINER (container));
240
241   if (container->border_width != border_width)
242     {
243       container->border_width = border_width;
244
245       if (container->widget.parent && GTK_WIDGET_VISIBLE (container))
246         gtk_container_need_resize (GTK_CONTAINER (container->widget.parent));
247     }
248 }
249
250 void
251 gtk_container_add (GtkContainer *container,
252                    GtkWidget    *widget)
253 {
254   gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget);
255 }
256
257 void
258 gtk_container_remove (GtkContainer *container,
259                       GtkWidget    *widget)
260 {
261   g_return_if_fail (container != NULL);
262   g_return_if_fail (GTK_IS_CONTAINER (container));
263
264   if (container->focus_child == widget)
265     container->focus_child = NULL;
266
267   gtk_signal_emit (GTK_OBJECT (container), container_signals[REMOVE], widget);
268 }
269
270 void
271 gtk_container_disable_resize (GtkContainer *container)
272 {
273   g_return_if_fail (container != NULL);
274   g_return_if_fail (GTK_IS_CONTAINER (container));
275
276   container->auto_resize = FALSE;
277 }
278
279 void
280 gtk_container_enable_resize (GtkContainer *container)
281 {
282   g_return_if_fail (container != NULL);
283   g_return_if_fail (GTK_IS_CONTAINER (container));
284
285   container->auto_resize = TRUE;
286   if (container->need_resize)
287     {
288       container->need_resize = FALSE;
289       gtk_widget_queue_resize (GTK_WIDGET (container));
290     }
291 }
292
293 void
294 gtk_container_block_resize (GtkContainer *container)
295 {
296   g_return_if_fail (container != NULL);
297   g_return_if_fail (GTK_IS_CONTAINER (container));
298
299   container->block_resize = TRUE;
300 }
301
302 void
303 gtk_container_unblock_resize (GtkContainer *container)
304 {
305   g_return_if_fail (container != NULL);
306   g_return_if_fail (GTK_IS_CONTAINER (container));
307
308   container->block_resize = FALSE;
309 }
310
311 gint
312 gtk_container_need_resize (GtkContainer *container)
313 {
314   gint return_val;
315
316   g_return_val_if_fail (container != NULL, FALSE);
317   g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
318
319   return_val = FALSE;
320
321   if (!container->block_resize)
322     {
323       if (container->auto_resize)
324         gtk_signal_emit (GTK_OBJECT (container),
325                          container_signals[NEED_RESIZE],
326                          &return_val);
327       else
328         container->need_resize = TRUE;
329     }
330
331   return return_val;
332 }
333
334 void
335 gtk_container_foreach (GtkContainer *container,
336                        GtkCallback   callback,
337                        gpointer      callback_data)
338 {
339   gtk_signal_emit (GTK_OBJECT (container),
340                    container_signals[FOREACH],
341                    callback, callback_data);
342 }
343
344 gint
345 gtk_container_focus (GtkContainer     *container,
346                      GtkDirectionType  direction)
347 {
348   gint return_val;
349
350   gtk_signal_emit (GTK_OBJECT (container),
351                    container_signals[FOCUS],
352                    direction, &return_val);
353
354   return return_val;
355 }
356
357 GList*
358 gtk_container_children (GtkContainer *container)
359 {
360   GList *children;
361
362   children = NULL;
363
364   gtk_container_foreach (container,
365                          gtk_container_children_callback,
366                          &children);
367
368   return g_list_reverse (children);
369 }
370
371
372 static void
373 gtk_container_marshal_signal_1 (GtkObject      *object,
374                                 GtkSignalFunc   func,
375                                 gpointer        func_data,
376                                 GtkArg         *args)
377 {
378   GtkContainerSignal1 rfunc;
379
380   rfunc = (GtkContainerSignal1) func;
381
382   (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
383 }
384
385 static void
386 gtk_container_marshal_signal_2 (GtkObject      *object,
387                                 GtkSignalFunc   func,
388                                 gpointer        func_data,
389                                 GtkArg         *args)
390 {
391   GtkContainerSignal2 rfunc;
392
393   rfunc = (GtkContainerSignal2) func;
394
395   (* rfunc) (object,
396              GTK_VALUE_C_CALLBACK(args[0]).func,
397              GTK_VALUE_C_CALLBACK(args[0]).func_data,
398              func_data);
399 }
400
401 static void
402 gtk_container_marshal_signal_3 (GtkObject      *object,
403                                 GtkSignalFunc   func,
404                                 gpointer        func_data,
405                                 GtkArg         *args)
406 {
407   GtkContainerSignal3 rfunc;
408   gint *return_val;
409
410   rfunc = (GtkContainerSignal3) func;
411   return_val = GTK_RETLOC_ENUM (args[1]);
412
413   *return_val = (* rfunc) (object, GTK_VALUE_ENUM(args[0]), func_data);
414 }
415
416 static void
417 gtk_container_marshal_signal_4 (GtkObject      *object,
418                                 GtkSignalFunc   func,
419                                 gpointer        func_data,
420                                 GtkArg         *args)
421 {
422   GtkContainerSignal4 rfunc;
423   gint *return_val;
424
425   rfunc = (GtkContainerSignal4) func;
426   return_val = GTK_RETLOC_BOOL (args[0]);
427
428   *return_val = (* rfunc) (object, func_data);
429 }
430
431 static gint
432 gtk_real_container_need_resize (GtkContainer *container)
433 {
434   g_return_val_if_fail (container != NULL, FALSE);
435   g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
436
437   if (GTK_WIDGET_VISIBLE (container) && container->widget.parent)
438     return gtk_container_need_resize (GTK_CONTAINER (container->widget.parent));
439
440   return FALSE;
441 }
442
443 static gint
444 gtk_real_container_focus (GtkContainer     *container,
445                           GtkDirectionType  direction)
446 {
447   GList *children;
448   GList *tmp_list;
449   GList *tmp_list2;
450   gint return_val;
451
452   g_return_val_if_fail (container != NULL, FALSE);
453   g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
454
455   /* Fail if the container is insensitive
456    */
457   if (!GTK_WIDGET_SENSITIVE (container))
458     return FALSE;
459
460   return_val = FALSE;
461
462   if (GTK_WIDGET_CAN_FOCUS (container))
463     {
464       gtk_widget_grab_focus (GTK_WIDGET (container));
465       return_val = TRUE;
466     }
467   else
468     {
469       /* Get a list of the containers children
470        */
471       children = gtk_container_children (container);
472
473       if (children)
474         {
475           /* Remove any children which are insensitive
476            */
477           tmp_list = children;
478           while (tmp_list)
479             {
480               if (!GTK_WIDGET_SENSITIVE (tmp_list->data))
481                 {
482                   tmp_list2 = tmp_list;
483                   tmp_list = tmp_list->next;
484
485                   children = g_list_remove_link (children, tmp_list2);
486                   g_list_free_1 (tmp_list2);
487                 }
488               else
489                 tmp_list = tmp_list->next;
490             }
491
492           switch (direction)
493             {
494             case GTK_DIR_TAB_FORWARD:
495             case GTK_DIR_TAB_BACKWARD:
496               return_val = gtk_container_focus_tab (container, children, direction);
497               break;
498             case GTK_DIR_UP:
499             case GTK_DIR_DOWN:
500               return_val = gtk_container_focus_up_down (container, children, direction);
501               break;
502             case GTK_DIR_LEFT:
503             case GTK_DIR_RIGHT:
504               return_val = gtk_container_focus_left_right (container, children, direction);
505               break;
506             }
507
508           g_list_free (children);
509         }
510     }
511
512   return return_val;
513 }
514
515 static gint
516 gtk_container_focus_tab (GtkContainer     *container,
517                          GList            *children,
518                          GtkDirectionType  direction)
519 {
520   GtkWidget *child;
521   GtkWidget *child2;
522   GList *tmp_list;
523   gint length;
524   gint i, j;
525
526   length = g_list_length (children);
527
528   /* sort the children in the y direction */
529   for (i = 1; i < length; i++)
530     {
531       j = i;
532       tmp_list = g_list_nth (children, j);
533       child = tmp_list->data;
534
535       while (j > 0)
536         {
537           child2 = tmp_list->prev->data;
538           if (child->allocation.y < child2->allocation.y)
539             {
540               tmp_list->data = tmp_list->prev->data;
541               tmp_list = tmp_list->prev;
542               j--;
543             }
544           else
545             break;
546         }
547
548       tmp_list->data = child;
549     }
550
551   /* sort the children in the x direction while
552    *  maintaining the y direction sort.
553    */
554   for (i = 1; i < length; i++)
555     {
556       j = i;
557       tmp_list = g_list_nth (children, j);
558       child = tmp_list->data;
559
560       while (j > 0)
561         {
562           child2 = tmp_list->prev->data;
563           if ((child->allocation.x < child2->allocation.x) &&
564               (child->allocation.y >= child2->allocation.y))
565             {
566               tmp_list->data = tmp_list->prev->data;
567               tmp_list = tmp_list->prev;
568               j--;
569             }
570           else
571             break;
572         }
573
574       tmp_list->data = child;
575     }
576
577   /* if we are going backwards then reverse the order
578    *  of the children.
579    */
580   if (direction == GTK_DIR_TAB_BACKWARD)
581     children = g_list_reverse (children);
582
583   return gtk_container_focus_move (container, children, direction);
584 }
585
586 static gint
587 gtk_container_focus_up_down (GtkContainer     *container,
588                              GList            *children,
589                              GtkDirectionType  direction)
590 {
591   GtkWidget *child;
592   GtkWidget *child2;
593   GList *tmp_list;
594   gint dist1, dist2;
595   gint focus_x;
596   gint focus_width;
597   gint length;
598   gint i, j;
599
600   /* return failure if there isn't a focus child */
601   if (container->focus_child)
602     {
603       focus_width = container->focus_child->allocation.width / 2;
604       focus_x = container->focus_child->allocation.x + focus_width;
605     }
606   else
607     {
608       focus_width = GTK_WIDGET (container)->allocation.width;
609       if (GTK_WIDGET_NO_WINDOW (container))
610         focus_x = GTK_WIDGET (container)->allocation.x;
611       else
612         focus_x = 0;
613     }
614
615   length = g_list_length (children);
616
617   /* sort the children in the y direction */
618   for (i = 1; i < length; i++)
619     {
620       j = i;
621       tmp_list = g_list_nth (children, j);
622       child = tmp_list->data;
623
624       while (j > 0)
625         {
626           child2 = tmp_list->prev->data;
627           if (child->allocation.y < child2->allocation.y)
628             {
629               tmp_list->data = tmp_list->prev->data;
630               tmp_list = tmp_list->prev;
631               j--;
632             }
633           else
634             break;
635         }
636
637       tmp_list->data = child;
638     }
639
640   /* sort the children in distance in the x direction
641    *  in distance from the current focus child while maintaining the
642    *  sort in the y direction
643    */
644   for (i = 1; i < length; i++)
645     {
646       j = i;
647       tmp_list = g_list_nth (children, j);
648       child = tmp_list->data;
649       dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x;
650
651       while (j > 0)
652         {
653           child2 = tmp_list->prev->data;
654           dist2 = (child2->allocation.x + child2->allocation.width / 2) - focus_x;
655
656           if ((dist1 < dist2) &&
657               (child->allocation.y >= child2->allocation.y))
658             {
659               tmp_list->data = tmp_list->prev->data;
660               tmp_list = tmp_list->prev;
661               j--;
662             }
663           else
664             break;
665         }
666
667       tmp_list->data = child;
668     }
669
670   /* go and invalidate any widget which is too
671    *  far from the focus widget.
672    */
673   if (!container->focus_child &&
674       (direction == GTK_DIR_UP))
675     focus_x += focus_width;
676
677   tmp_list = children;
678   while (tmp_list)
679     {
680       child = tmp_list->data;
681
682       dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x;
683       if (((direction == GTK_DIR_DOWN) && (dist1 < 0)) ||
684           ((direction == GTK_DIR_UP) && (dist1 > 0)))
685         tmp_list->data = NULL;
686
687       tmp_list = tmp_list->next;
688     }
689
690   if (direction == GTK_DIR_UP)
691     children = g_list_reverse (children);
692
693   return gtk_container_focus_move (container, children, direction);
694 }
695
696 static gint
697 gtk_container_focus_left_right (GtkContainer     *container,
698                                 GList            *children,
699                                 GtkDirectionType  direction)
700 {
701   GtkWidget *child;
702   GtkWidget *child2;
703   GList *tmp_list;
704   gint dist1, dist2;
705   gint focus_y;
706   gint focus_height;
707   gint length;
708   gint i, j;
709
710   /* return failure if there isn't a focus child */
711   if (container->focus_child)
712     {
713       focus_height = container->focus_child->allocation.height / 2;
714       focus_y = container->focus_child->allocation.y + focus_height;
715     }
716   else
717     {
718       focus_height = GTK_WIDGET (container)->allocation.height;
719       if (GTK_WIDGET_NO_WINDOW (container))
720         focus_y = GTK_WIDGET (container)->allocation.y;
721       else
722         focus_y = 0;
723     }
724
725   length = g_list_length (children);
726
727   /* sort the children in the x direction */
728   for (i = 1; i < length; i++)
729     {
730       j = i;
731       tmp_list = g_list_nth (children, j);
732       child = tmp_list->data;
733
734       while (j > 0)
735         {
736           child2 = tmp_list->prev->data;
737           if (child->allocation.x < child2->allocation.x)
738             {
739               tmp_list->data = tmp_list->prev->data;
740               tmp_list = tmp_list->prev;
741               j--;
742             }
743           else
744             break;
745         }
746
747       tmp_list->data = child;
748     }
749
750   /* sort the children in distance in the y direction
751    *  in distance from the current focus child while maintaining the
752    *  sort in the x direction
753    */
754   for (i = 1; i < length; i++)
755     {
756       j = i;
757       tmp_list = g_list_nth (children, j);
758       child = tmp_list->data;
759       dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y;
760
761       while (j > 0)
762         {
763           child2 = tmp_list->prev->data;
764           dist2 = (child2->allocation.y + child2->allocation.height / 2) - focus_y;
765
766           if ((dist1 < dist2) &&
767               (child->allocation.x >= child2->allocation.x))
768             {
769               tmp_list->data = tmp_list->prev->data;
770               tmp_list = tmp_list->prev;
771               j--;
772             }
773           else
774             break;
775         }
776
777       tmp_list->data = child;
778     }
779
780   /* go and invalidate any widget which is too
781    *  far from the focus widget.
782    */
783   if (!container->focus_child &&
784       (direction == GTK_DIR_LEFT))
785     focus_y += focus_height;
786
787   tmp_list = children;
788   while (tmp_list)
789     {
790       child = tmp_list->data;
791
792       dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y;
793       if (((direction == GTK_DIR_RIGHT) && (dist1 < 0)) ||
794           ((direction == GTK_DIR_LEFT) && (dist1 > 0)))
795         tmp_list->data = NULL;
796
797       tmp_list = tmp_list->next;
798     }
799
800   if (direction == GTK_DIR_LEFT)
801     children = g_list_reverse (children);
802
803   return gtk_container_focus_move (container, children, direction);
804 }
805
806 static gint
807 gtk_container_focus_move (GtkContainer     *container,
808                           GList            *children,
809                           GtkDirectionType  direction)
810 {
811   GtkWidget *focus_child;
812   GtkWidget *child;
813
814   focus_child = container->focus_child;
815   container->focus_child = NULL;
816
817   while (children)
818     {
819       child = children->data;
820       children = children->next;
821
822       if (!child)
823         continue;
824
825       if (focus_child)
826         {
827           if (focus_child == child)
828             {
829               focus_child = NULL;
830
831               if (GTK_WIDGET_VISIBLE (child) &&
832                   GTK_IS_CONTAINER (child) &&
833                   !GTK_WIDGET_HAS_FOCUS (child))
834                 if (gtk_container_focus (GTK_CONTAINER (child), direction))
835                   return TRUE;
836             }
837         }
838       else if (GTK_WIDGET_VISIBLE (child))
839         {
840           if (GTK_WIDGET_CAN_FOCUS (child))
841             {
842               gtk_widget_grab_focus (child);
843               return TRUE;
844             }
845           else if (GTK_IS_CONTAINER (child))
846             {
847               if (gtk_container_focus (GTK_CONTAINER (child), direction))
848                 return TRUE;
849             }
850         }
851     }
852
853   return FALSE;
854 }
855
856
857 static void
858 gtk_container_children_callback (GtkWidget *widget,
859                                  gpointer   client_data)
860 {
861   GList **children;
862
863   children = (GList**) client_data;
864   *children = g_list_prepend (*children, widget);
865 }
866
867 static void
868 gtk_container_show_all (GtkWidget *widget)
869 {
870   GtkContainer *container;
871
872   g_return_if_fail (widget != NULL);
873   g_return_if_fail (GTK_IS_CONTAINER (widget));
874   container = GTK_CONTAINER (widget);
875
876   /* First show children, then self.
877      This makes sure that toplevel windows get shown as last widget.
878      Otherwise the user would see the widgets get
879      visible one after another.
880   */
881   gtk_container_foreach (container, (GtkCallback) gtk_widget_show_all, NULL);
882   gtk_widget_show (widget);
883 }
884
885
886 static void
887 gtk_container_hide_all (GtkWidget *widget)
888 {
889   GtkContainer *container;
890
891   g_return_if_fail (widget != NULL);
892   g_return_if_fail (GTK_IS_CONTAINER (widget));
893   container = GTK_CONTAINER (widget);
894
895   /* First hide self, then children.
896      This is the reverse order of gtk_container_show_all.
897   */
898   gtk_widget_hide (widget);  
899   gtk_container_foreach (container, (GtkCallback) gtk_widget_hide_all, NULL);
900 }
901