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