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