]> Pileus Git - ~andy/gtk/blob - gtk/gtklayout.c
Patch from Matthias Clasen to remove remove all instances of
[~andy/gtk] / gtk / gtklayout.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  * GtkLayout: Widget for scrolling of arbitrary-sized areas.
20  *
21  * Copyright Owen Taylor, 1998
22  */
23
24 /*
25  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
26  * file for a list of people on the GTK+ Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
29  */
30
31 #include "gdkconfig.h"
32
33 #include "gtklayout.h"
34 #include "gtksignal.h"
35 #include "gtkprivate.h"
36 #include "gtkintl.h"
37
38 typedef struct _GtkLayoutChild   GtkLayoutChild;
39
40 struct _GtkLayoutChild {
41   GtkWidget *widget;
42   gint x;
43   gint y;
44 };
45
46 enum {
47    PROP_0,
48    PROP_HADJUSTMENT,
49    PROP_VADJUSTMENT,
50    PROP_WIDTH,
51    PROP_HEIGHT
52 };
53
54 static void     gtk_layout_class_init         (GtkLayoutClass *class);
55 static void     gtk_layout_get_property       (GObject        *object,
56                                                guint          prop_id,
57                                                GValue         *value,
58                                                GParamSpec     *pspec);
59 static void     gtk_layout_set_property       (GObject        *object,
60                                                guint          prop_id,
61                                                const GValue   *value,
62                                                GParamSpec     *pspec);
63 static void     gtk_layout_init               (GtkLayout      *layout);
64
65 static void     gtk_layout_finalize           (GObject        *object);
66 static void     gtk_layout_realize            (GtkWidget      *widget);
67 static void     gtk_layout_unrealize          (GtkWidget      *widget);
68 static void     gtk_layout_map                (GtkWidget      *widget);
69 static void     gtk_layout_size_request       (GtkWidget      *widget,
70                                                GtkRequisition *requisition);
71 static void     gtk_layout_size_allocate      (GtkWidget      *widget,
72                                                GtkAllocation  *allocation);
73 static gint     gtk_layout_expose             (GtkWidget      *widget, 
74                                                GdkEventExpose *event);
75
76 static void     gtk_layout_remove             (GtkContainer *container, 
77                                                GtkWidget    *widget);
78 static void     gtk_layout_forall             (GtkContainer *container,
79                                                gboolean      include_internals,
80                                                GtkCallback   callback,
81                                                gpointer      callback_data);
82 static void     gtk_layout_set_adjustments    (GtkLayout     *layout,
83                                                GtkAdjustment *hadj,
84                                                GtkAdjustment *vadj);
85
86 static void     gtk_layout_allocate_child     (GtkLayout      *layout,
87                                                GtkLayoutChild *child);
88
89
90 static void     gtk_layout_adjustment_changed (GtkAdjustment  *adjustment,
91                                                GtkLayout      *layout);
92
93 static GtkWidgetClass *parent_class = NULL;
94
95 /* Public interface
96  */
97   
98 GtkWidget*    
99 gtk_layout_new (GtkAdjustment *hadjustment,
100                 GtkAdjustment *vadjustment)
101 {
102   GtkLayout *layout;
103
104   layout = gtk_type_new (GTK_TYPE_LAYOUT);
105
106   gtk_layout_set_adjustments (layout, hadjustment, vadjustment);
107
108   return GTK_WIDGET (layout);
109 }
110
111 GtkAdjustment* 
112 gtk_layout_get_hadjustment (GtkLayout     *layout)
113 {
114   g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL);
115
116   return layout->hadjustment;
117 }
118 GtkAdjustment* 
119 gtk_layout_get_vadjustment (GtkLayout     *layout)
120 {
121   g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL);
122
123   return layout->vadjustment;
124 }
125
126 static void           
127 gtk_layout_set_adjustments (GtkLayout     *layout,
128                             GtkAdjustment *hadj,
129                             GtkAdjustment *vadj)
130 {
131   gboolean need_adjust = FALSE;
132
133   g_return_if_fail (GTK_IS_LAYOUT (layout));
134
135   if (hadj)
136     g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
137   else
138     hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
139   if (vadj)
140     g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
141   else
142     vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
143   
144   if (layout->hadjustment && (layout->hadjustment != hadj))
145     {
146       gtk_signal_disconnect_by_data (GTK_OBJECT (layout->hadjustment), layout);
147       gtk_object_unref (GTK_OBJECT (layout->hadjustment));
148     }
149   
150   if (layout->vadjustment && (layout->vadjustment != vadj))
151     {
152       gtk_signal_disconnect_by_data (GTK_OBJECT (layout->vadjustment), layout);
153       gtk_object_unref (GTK_OBJECT (layout->vadjustment));
154     }
155   
156   if (layout->hadjustment != hadj)
157     {
158       layout->hadjustment = hadj;
159       gtk_object_ref (GTK_OBJECT (layout->hadjustment));
160       gtk_object_sink (GTK_OBJECT (layout->hadjustment));
161       
162       gtk_signal_connect (GTK_OBJECT (layout->hadjustment), "value_changed",
163                           (GtkSignalFunc) gtk_layout_adjustment_changed,
164                           layout);
165       need_adjust = TRUE;
166     }
167   
168   if (layout->vadjustment != vadj)
169     {
170       layout->vadjustment = vadj;
171       gtk_object_ref (GTK_OBJECT (layout->vadjustment));
172       gtk_object_sink (GTK_OBJECT (layout->vadjustment));
173       
174       gtk_signal_connect (GTK_OBJECT (layout->vadjustment), "value_changed",
175                           (GtkSignalFunc) gtk_layout_adjustment_changed,
176                           layout);
177       need_adjust = TRUE;
178     }
179
180   if (need_adjust)
181     gtk_layout_adjustment_changed (NULL, layout);
182 }
183
184 static void
185 gtk_layout_finalize (GObject *object)
186 {
187   GtkLayout *layout = GTK_LAYOUT (object);
188
189   gtk_object_unref (GTK_OBJECT (layout->hadjustment));
190   gtk_object_unref (GTK_OBJECT (layout->vadjustment));
191
192   G_OBJECT_CLASS (parent_class)->finalize (object);
193 }
194
195 void           
196 gtk_layout_set_hadjustment (GtkLayout     *layout,
197                             GtkAdjustment *adjustment)
198 {
199   g_return_if_fail (GTK_IS_LAYOUT (layout));
200
201   gtk_layout_set_adjustments (layout, adjustment, layout->vadjustment);
202   g_object_notify (G_OBJECT (layout), "hadjustment");
203 }
204  
205
206 void           
207 gtk_layout_set_vadjustment (GtkLayout     *layout,
208                             GtkAdjustment *adjustment)
209 {
210   g_return_if_fail (GTK_IS_LAYOUT (layout));
211   
212   gtk_layout_set_adjustments (layout, layout->hadjustment, adjustment);
213   g_object_notify (G_OBJECT (layout), "vadjustment");
214 }
215
216
217 void           
218 gtk_layout_put (GtkLayout     *layout, 
219                 GtkWidget     *child_widget, 
220                 gint           x, 
221                 gint           y)
222 {
223   GtkLayoutChild *child;
224
225   g_return_if_fail (GTK_IS_LAYOUT (layout));
226   g_return_if_fail (GTK_IS_WIDGET (child_widget));
227   
228   child = g_new (GtkLayoutChild, 1);
229
230   child->widget = child_widget;
231   child->x = x;
232   child->y = y;
233
234   layout->children = g_list_append (layout->children, child);
235   
236   gtk_widget_set_parent (child_widget, GTK_WIDGET (layout));
237   if (GTK_WIDGET_REALIZED (layout))
238     gtk_widget_set_parent_window (child->widget, layout->bin_window);
239
240   if (GTK_WIDGET_REALIZED (layout))
241     gtk_widget_realize (child_widget);
242     
243   if (GTK_WIDGET_VISIBLE (layout) && GTK_WIDGET_VISIBLE (child_widget))
244     {
245       if (GTK_WIDGET_MAPPED (layout))
246         gtk_widget_map (child_widget);
247
248       gtk_widget_queue_resize (child_widget);
249     }
250 }
251
252 void           
253 gtk_layout_move (GtkLayout     *layout, 
254                  GtkWidget     *child_widget, 
255                  gint           x, 
256                  gint           y)
257 {
258   GList *tmp_list;
259   GtkLayoutChild *child;
260   
261   g_return_if_fail (GTK_IS_LAYOUT (layout));
262
263   tmp_list = layout->children;
264   while (tmp_list)
265     {
266       child = tmp_list->data;
267       tmp_list = tmp_list->next;
268
269       if (child->widget == child_widget)
270         {
271           child->x = x;
272           child->y = y;
273
274           if (GTK_WIDGET_VISIBLE (child_widget) && GTK_WIDGET_VISIBLE (layout))
275             gtk_widget_queue_resize (child_widget);
276
277           return;
278         }
279     }
280 }
281
282 static void
283 gtk_layout_set_adjustment_upper (GtkAdjustment *adj,
284                                  gdouble        upper)
285 {
286   if (upper != adj->upper)
287     {
288       gdouble min = MAX (0., upper - adj->page_size);
289       gboolean value_changed = FALSE;
290       
291       adj->upper = upper;
292       
293       if (adj->value > min)
294         {
295           adj->value = min;
296           value_changed = TRUE;
297         }
298       
299       gtk_signal_emit_by_name (GTK_OBJECT (adj), "changed");
300       if (value_changed)
301         gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
302     }
303 }
304
305 void
306 gtk_layout_set_size (GtkLayout     *layout, 
307                      guint          width,
308                      guint          height)
309 {
310   GtkWidget *widget;
311   
312   g_return_if_fail (GTK_IS_LAYOUT (layout));
313
314   widget = GTK_WIDGET (layout);
315   
316   if (width != layout->width)
317      {
318         layout->width = width;
319         g_object_notify (G_OBJECT (layout), "width");
320      }
321   if (height != layout->height)
322      {
323         layout->height = height;
324         g_object_notify (G_OBJECT (layout), "height");
325      }
326
327   gtk_layout_set_adjustment_upper (layout->hadjustment, layout->width);
328   gtk_layout_set_adjustment_upper (layout->vadjustment, layout->height);
329
330   if (GTK_WIDGET_REALIZED (layout))
331     {
332       width = MAX (width, widget->allocation.width);
333       height = MAX (height, widget->allocation.height);
334       gdk_window_resize (layout->bin_window, width, height);
335     }
336 }
337
338 /**
339  * gtk_layout_get_size:
340  * @layout: a #GtkLayout
341  * @width: location to store the width set on @layout, or %NULL
342  * @height: location to store the height set on @layout, or %NULL
343  *
344  * Gets the size that has been set on the layout, and that determines
345  * the total extents of the layout's scrollbar area. See
346  * gtk_layout_set_size ().
347  **/
348 void
349 gtk_layout_get_size (GtkLayout *layout,
350                      guint     *width,
351                      guint     *height)
352 {
353   g_return_if_fail (GTK_IS_LAYOUT (layout));
354
355   if (width)
356     *width = layout->width;
357   if (height)
358     *height = layout->height;
359 }
360
361 void
362 gtk_layout_freeze (GtkLayout *layout)
363 {
364   g_return_if_fail (GTK_IS_LAYOUT (layout));
365
366   layout->freeze_count++;
367 }
368
369 void
370 gtk_layout_thaw (GtkLayout *layout)
371 {
372   g_return_if_fail (GTK_IS_LAYOUT (layout));
373
374   if (layout->freeze_count)
375     if (!(--layout->freeze_count))
376       gtk_widget_draw (GTK_WIDGET (layout), NULL);
377 }
378
379 /* Basic Object handling procedures
380  */
381 GtkType
382 gtk_layout_get_type (void)
383 {
384   static GtkType layout_type = 0;
385
386   if (!layout_type)
387     {
388       static const GTypeInfo layout_info =
389       {
390         sizeof (GtkLayoutClass),
391         NULL,           /* base_init */
392         NULL,           /* base_finalize */
393         (GClassInitFunc) gtk_layout_class_init,
394         NULL,           /* class_finalize */
395         NULL,           /* class_data */
396         sizeof (GtkLayout),
397         16,             /* n_preallocs */
398         (GInstanceInitFunc) gtk_layout_init,
399       };
400
401       layout_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkLayout", &layout_info, 0);
402     }
403
404   return layout_type;
405 }
406
407 static void
408 gtk_layout_class_init (GtkLayoutClass *class)
409 {
410   GObjectClass *gobject_class;
411   GtkObjectClass *object_class;
412   GtkWidgetClass *widget_class;
413   GtkContainerClass *container_class;
414
415   gobject_class = (GObjectClass*) class;
416   object_class = (GtkObjectClass*) class;
417   widget_class = (GtkWidgetClass*) class;
418   container_class = (GtkContainerClass*) class;
419
420   parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
421
422   gobject_class->set_property = gtk_layout_set_property;
423   gobject_class->get_property = gtk_layout_get_property;
424   gobject_class->finalize = gtk_layout_finalize;
425
426   g_object_class_install_property (gobject_class,
427                                    PROP_HADJUSTMENT,
428                                    g_param_spec_object ("hadjustment",
429                                                         _("Horizontal adjustment"),
430                                                         _("The GtkAdjustment for the horizontal position."),
431                                                         GTK_TYPE_ADJUSTMENT,
432                                                         G_PARAM_READWRITE));
433   
434   g_object_class_install_property (gobject_class,
435                                    PROP_VADJUSTMENT,
436                                    g_param_spec_object ("vadjustment",
437                                                         _("Vertical adjustment"),
438                                                         _("The GtkAdjustment for the vertical position."),
439                                                         GTK_TYPE_ADJUSTMENT,
440                                                         G_PARAM_READWRITE));
441
442   g_object_class_install_property (gobject_class,
443                                    PROP_WIDTH,
444                                    g_param_spec_uint ("width",
445                                                      _("Width"),
446                                                      _("The width of the layout."),
447                                                      0,
448                                                      G_MAXINT,
449                                                      100,
450                                                      G_PARAM_READWRITE));
451   g_object_class_install_property (gobject_class,
452                                    PROP_HEIGHT,
453                                    g_param_spec_uint ("height",
454                                                      _("Height"),
455                                                      _("The height of the layout."),
456                                                      0,
457                                                      G_MAXINT,
458                                                      100,
459                                                      G_PARAM_READWRITE));
460   widget_class->realize = gtk_layout_realize;
461   widget_class->unrealize = gtk_layout_unrealize;
462   widget_class->map = gtk_layout_map;
463   widget_class->size_request = gtk_layout_size_request;
464   widget_class->size_allocate = gtk_layout_size_allocate;
465   widget_class->expose_event = gtk_layout_expose;
466
467   container_class->remove = gtk_layout_remove;
468   container_class->forall = gtk_layout_forall;
469
470   class->set_scroll_adjustments = gtk_layout_set_adjustments;
471
472   widget_class->set_scroll_adjustments_signal =
473     gtk_signal_new ("set_scroll_adjustments",
474                     GTK_RUN_LAST,
475                     GTK_CLASS_TYPE (object_class),
476                     GTK_SIGNAL_OFFSET (GtkLayoutClass, set_scroll_adjustments),
477                     gtk_marshal_VOID__OBJECT_OBJECT,
478                     GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
479 }
480
481 static void
482 gtk_layout_get_property (GObject     *object,
483                          guint        prop_id,
484                          GValue      *value,
485                          GParamSpec  *pspec)
486 {
487   GtkLayout *layout = GTK_LAYOUT (object);
488   
489   switch (prop_id)
490     {
491     case PROP_HADJUSTMENT:
492       g_value_set_object (value, G_OBJECT (layout->hadjustment));
493       break;
494     case PROP_VADJUSTMENT:
495       g_value_set_object (value, G_OBJECT (layout->vadjustment));
496       break;
497     case PROP_WIDTH:
498       g_value_set_uint (value, layout->width);
499       break;
500     case PROP_HEIGHT:
501       g_value_set_uint (value, layout->height);
502       break;
503     default:
504       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
505       break;
506     }
507 }
508
509 static void
510 gtk_layout_set_property (GObject      *object,
511                          guint         prop_id,
512                          const GValue *value,
513                          GParamSpec   *pspec)
514 {
515   GtkLayout *layout = GTK_LAYOUT (object);
516   
517   switch (prop_id)
518     {
519     case PROP_HADJUSTMENT:
520       gtk_layout_set_hadjustment (layout, 
521                                   (GtkAdjustment*) g_value_get_object (value));
522       break;
523     case PROP_VADJUSTMENT:
524       gtk_layout_set_vadjustment (layout, 
525                                   (GtkAdjustment*) g_value_get_object (value));
526       break;
527     case PROP_WIDTH:
528       gtk_layout_set_size (layout, g_value_get_uint (value),
529                            layout->height);
530       break;
531     case PROP_HEIGHT:
532       gtk_layout_set_size (layout, layout->width,
533                            g_value_get_uint (value));
534       break;
535     default:
536       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
537       break;
538     }
539 }
540
541
542 static void
543 gtk_layout_init (GtkLayout *layout)
544 {
545   layout->children = NULL;
546
547   layout->width = 100;
548   layout->height = 100;
549
550   layout->hadjustment = NULL;
551   layout->vadjustment = NULL;
552
553   layout->bin_window = NULL;
554
555   layout->scroll_x = 0;
556   layout->scroll_y = 0;
557   layout->visibility = GDK_VISIBILITY_PARTIAL;
558
559   layout->freeze_count = 0;
560 }
561
562 /* Widget methods
563  */
564
565 static void 
566 gtk_layout_realize (GtkWidget *widget)
567 {
568   GList *tmp_list;
569   GtkLayout *layout;
570   GdkWindowAttr attributes;
571   gint attributes_mask;
572
573   g_return_if_fail (GTK_IS_LAYOUT (widget));
574
575   layout = GTK_LAYOUT (widget);
576   GTK_WIDGET_SET_FLAGS (layout, GTK_REALIZED);
577
578   attributes.window_type = GDK_WINDOW_CHILD;
579   attributes.x = widget->allocation.x;
580   attributes.y = widget->allocation.y;
581   attributes.width = widget->allocation.width;
582   attributes.height = widget->allocation.height;
583   attributes.wclass = GDK_INPUT_OUTPUT;
584   attributes.visual = gtk_widget_get_visual (widget);
585   attributes.colormap = gtk_widget_get_colormap (widget);
586   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
587
588   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
589
590   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
591                                    &attributes, attributes_mask);
592   gdk_window_set_user_data (widget->window, widget);
593
594   attributes.x = 0;
595   attributes.y = 0;
596   attributes.width = MAX (layout->width, widget->allocation.width);
597   attributes.height = MAX (layout->height, widget->allocation.height);
598   attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | 
599                           gtk_widget_get_events (widget);
600
601   layout->bin_window = gdk_window_new (widget->window,
602                                         &attributes, attributes_mask);
603   gdk_window_set_user_data (layout->bin_window, widget);
604
605   widget->style = gtk_style_attach (widget->style, widget->window);
606   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
607   gtk_style_set_background (widget->style, layout->bin_window, GTK_STATE_NORMAL);
608
609   tmp_list = layout->children;
610   while (tmp_list)
611     {
612       GtkLayoutChild *child = tmp_list->data;
613       tmp_list = tmp_list->next;
614
615       gtk_widget_set_parent_window (child->widget, layout->bin_window);
616     }
617 }
618
619 static void 
620 gtk_layout_map (GtkWidget *widget)
621 {
622   GList *tmp_list;
623   GtkLayout *layout;
624
625   g_return_if_fail (GTK_IS_LAYOUT (widget));
626
627   layout = GTK_LAYOUT (widget);
628
629   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
630
631   tmp_list = layout->children;
632   while (tmp_list)
633     {
634       GtkLayoutChild *child = tmp_list->data;
635       tmp_list = tmp_list->next;
636
637       if (GTK_WIDGET_VISIBLE (child->widget))
638         {
639           if (!GTK_WIDGET_MAPPED (child->widget))
640             gtk_widget_map (child->widget);
641         }
642     }
643
644   gdk_window_show (layout->bin_window);
645   gdk_window_show (widget->window);
646 }
647
648 static void 
649 gtk_layout_unrealize (GtkWidget *widget)
650 {
651   GtkLayout *layout;
652
653   g_return_if_fail (GTK_IS_LAYOUT (widget));
654
655   layout = GTK_LAYOUT (widget);
656
657   gdk_window_set_user_data (layout->bin_window, NULL);
658   gdk_window_destroy (layout->bin_window);
659   layout->bin_window = NULL;
660
661   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
662     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
663 }
664
665 static void     
666 gtk_layout_size_request (GtkWidget     *widget,
667                          GtkRequisition *requisition)
668 {
669   GList *tmp_list;
670   GtkLayout *layout;
671
672   g_return_if_fail (GTK_IS_LAYOUT (widget));
673
674   layout = GTK_LAYOUT (widget);
675
676   requisition->width = 0;
677   requisition->height = 0;
678
679   tmp_list = layout->children;
680
681   while (tmp_list)
682     {
683       GtkLayoutChild *child = tmp_list->data;
684       GtkRequisition child_requisition;
685       
686       tmp_list = tmp_list->next;
687
688       gtk_widget_size_request (child->widget, &child_requisition);
689     }
690 }
691
692 static void     
693 gtk_layout_size_allocate (GtkWidget     *widget,
694                           GtkAllocation *allocation)
695 {
696   GList *tmp_list;
697   GtkLayout *layout;
698
699   g_return_if_fail (GTK_IS_LAYOUT (widget));
700
701   widget->allocation = *allocation;
702   
703   layout = GTK_LAYOUT (widget);
704
705   tmp_list = layout->children;
706
707   while (tmp_list)
708     {
709       GtkLayoutChild *child = tmp_list->data;
710       tmp_list = tmp_list->next;
711
712       gtk_layout_allocate_child (layout, child);
713     }
714
715   if (GTK_WIDGET_REALIZED (widget))
716     {
717       gdk_window_move_resize (widget->window,
718                               allocation->x, allocation->y,
719                               allocation->width, allocation->height);
720
721       gdk_window_resize (layout->bin_window,
722                          MAX (layout->width, allocation->width),
723                          MAX (layout->height, allocation->height));
724     }
725
726   layout->hadjustment->page_size = allocation->width;
727   layout->hadjustment->page_increment = allocation->width / 2;
728   layout->hadjustment->lower = 0;
729   layout->hadjustment->upper = MAX (allocation->width, layout->width);
730   gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed");
731
732   layout->vadjustment->page_size = allocation->height;
733   layout->vadjustment->page_increment = allocation->height / 2;
734   layout->vadjustment->lower = 0;
735   layout->vadjustment->upper = MAX (allocation->height, layout->height);
736   gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed");
737 }
738
739 static gint 
740 gtk_layout_expose (GtkWidget *widget, GdkEventExpose *event)
741 {
742   GtkLayout *layout;
743
744   g_return_val_if_fail (GTK_IS_LAYOUT (widget), FALSE);
745
746   layout = GTK_LAYOUT (widget);
747
748   if (event->window != layout->bin_window)
749     return FALSE;
750   
751   (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
752
753   return FALSE;
754 }
755
756 /* Container method
757  */
758 static void
759 gtk_layout_remove (GtkContainer *container, 
760                    GtkWidget    *widget)
761 {
762   GList *tmp_list;
763   GtkLayout *layout;
764   GtkLayoutChild *child = NULL;
765   
766   g_return_if_fail (GTK_IS_LAYOUT (container));
767   
768   layout = GTK_LAYOUT (container);
769
770   tmp_list = layout->children;
771   while (tmp_list)
772     {
773       child = tmp_list->data;
774       if (child->widget == widget)
775         break;
776       tmp_list = tmp_list->next;
777     }
778
779   if (tmp_list)
780     {
781       gtk_widget_unparent (widget);
782
783       layout->children = g_list_remove_link (layout->children, tmp_list);
784       g_list_free_1 (tmp_list);
785       g_free (child);
786     }
787 }
788
789 static void
790 gtk_layout_forall (GtkContainer *container,
791                    gboolean      include_internals,
792                    GtkCallback   callback,
793                    gpointer      callback_data)
794 {
795   GtkLayout *layout;
796   GtkLayoutChild *child;
797   GList *tmp_list;
798
799   g_return_if_fail (GTK_IS_LAYOUT (container));
800   g_return_if_fail (callback != NULL);
801
802   layout = GTK_LAYOUT (container);
803
804   tmp_list = layout->children;
805   while (tmp_list)
806     {
807       child = tmp_list->data;
808       tmp_list = tmp_list->next;
809
810       (* callback) (child->widget, callback_data);
811     }
812 }
813
814 /* Operations on children
815  */
816
817 static void
818 gtk_layout_allocate_child (GtkLayout      *layout,
819                            GtkLayoutChild *child)
820 {
821   GtkAllocation allocation;
822   GtkRequisition requisition;
823
824   allocation.x = child->x;
825   allocation.y = child->y;
826   gtk_widget_get_child_requisition (child->widget, &requisition);
827   allocation.width = requisition.width;
828   allocation.height = requisition.height;
829   
830   gtk_widget_size_allocate (child->widget, &allocation);
831 }
832
833 /* Callbacks */
834
835 static void
836 gtk_layout_adjustment_changed (GtkAdjustment *adjustment,
837                                GtkLayout     *layout)
838 {
839   GtkWidget *widget;
840
841   widget = GTK_WIDGET (layout);
842
843   if (layout->freeze_count)
844     return;
845
846   if (GTK_WIDGET_REALIZED (layout))
847     {
848       gdk_window_move (layout->bin_window,
849                        - layout->hadjustment->value,
850                        - layout->vadjustment->value);
851       
852       gdk_window_process_updates (layout->bin_window, TRUE);
853     }
854 }