]> Pileus Git - ~andy/gtk/blob - gtk/gtkviewport.c
added args ::show_text, ::text_xalign, ::text_yalign, ::activity_mode.
[~andy/gtk] / gtk / gtkviewport.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
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include "gtksignal.h"
20 #include "gtkviewport.h"
21
22 enum {
23   ARG_0,
24   ARG_HADJUSTMENT,
25   ARG_VADJUSTMENT,
26   ARG_SHADOW_TYPE
27 };
28
29
30 static void gtk_viewport_class_init               (GtkViewportClass *klass);
31 static void gtk_viewport_init                     (GtkViewport      *viewport);
32 static void gtk_viewport_destroy                  (GtkObject        *object);
33 static void gtk_viewport_finalize                 (GtkObject        *object);
34 static void gtk_viewport_set_arg                  (GtkObject        *object,
35                                                    GtkArg           *arg,
36                                                    guint             arg_id);
37 static void gtk_viewport_get_arg                  (GtkObject        *object,
38                                                    GtkArg           *arg,
39                                                    guint             arg_id);
40 static void gtk_viewport_scroll_adjustments       (GtkViewport      *viewport,
41                                                    GtkAdjustment    *hadjustment,
42                                                    GtkAdjustment    *vadjustment);
43 static void gtk_viewport_map                      (GtkWidget        *widget);
44 static void gtk_viewport_unmap                    (GtkWidget        *widget);
45 static void gtk_viewport_realize                  (GtkWidget        *widget);
46 static void gtk_viewport_unrealize                (GtkWidget        *widget);
47 static void gtk_viewport_paint                    (GtkWidget        *widget,
48                                                    GdkRectangle     *area);
49 static void gtk_viewport_draw                     (GtkWidget        *widget,
50                                                    GdkRectangle     *area);
51 static gint gtk_viewport_expose                   (GtkWidget        *widget,
52                                                    GdkEventExpose   *event);
53 static void gtk_viewport_add                      (GtkContainer     *container,
54                                                    GtkWidget        *widget);
55 static void gtk_viewport_size_request             (GtkWidget        *widget,
56                                                    GtkRequisition   *requisition);
57 static void gtk_viewport_size_allocate            (GtkWidget        *widget,
58                                                    GtkAllocation    *allocation);
59 static void gtk_viewport_adjustment_changed       (GtkAdjustment    *adjustment,
60                                                    gpointer          data);
61 static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
62                                                    gpointer          data);
63 static void gtk_viewport_style_set                (GtkWidget *widget,
64                                                    GtkStyle  *previous_style);
65
66 static GtkBinClass *parent_class;
67
68 GtkType
69 gtk_viewport_get_type (void)
70 {
71   static GtkType viewport_type = 0;
72
73   if (!viewport_type)
74     {
75       GtkTypeInfo viewport_info =
76       {
77         "GtkViewport",
78         sizeof (GtkViewport),
79         sizeof (GtkViewportClass),
80         (GtkClassInitFunc) gtk_viewport_class_init,
81         (GtkObjectInitFunc) gtk_viewport_init,
82         /* reserved_1 */ NULL,
83         /* reserved_2 */ NULL,
84         (GtkClassInitFunc) NULL,
85       };
86
87       viewport_type = gtk_type_unique (GTK_TYPE_BIN, &viewport_info);
88     }
89
90   return viewport_type;
91 }
92
93 static void
94 gtk_viewport_class_init (GtkViewportClass *class)
95 {
96   GtkObjectClass *object_class;
97   GtkWidgetClass *widget_class;
98   GtkContainerClass *container_class;
99
100   object_class = (GtkObjectClass*) class;
101   widget_class = (GtkWidgetClass*) class;
102   container_class = (GtkContainerClass*) class;
103   parent_class = (GtkBinClass*) gtk_type_class (GTK_TYPE_BIN);
104
105   gtk_object_add_arg_type ("GtkViewport::hadjustment",
106                            GTK_TYPE_ADJUSTMENT,
107                            GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
108                            ARG_HADJUSTMENT);
109   gtk_object_add_arg_type ("GtkViewport::vadjustment",
110                            GTK_TYPE_ADJUSTMENT,
111                            GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
112                            ARG_VADJUSTMENT);
113   gtk_object_add_arg_type ("GtkViewport::shadow_type",
114                            GTK_TYPE_SHADOW_TYPE,
115                            GTK_ARG_READWRITE,
116                            ARG_SHADOW_TYPE);
117
118   object_class->set_arg = gtk_viewport_set_arg;
119   object_class->get_arg = gtk_viewport_get_arg;
120   object_class->destroy = gtk_viewport_destroy;
121   object_class->finalize = gtk_viewport_finalize;
122   
123   widget_class->map = gtk_viewport_map;
124   widget_class->unmap = gtk_viewport_unmap;
125   widget_class->realize = gtk_viewport_realize;
126   widget_class->unrealize = gtk_viewport_unrealize;
127   widget_class->draw = gtk_viewport_draw;
128   widget_class->expose_event = gtk_viewport_expose;
129   widget_class->size_request = gtk_viewport_size_request;
130   widget_class->size_allocate = gtk_viewport_size_allocate;
131   widget_class->style_set = gtk_viewport_style_set;
132
133   widget_class->scroll_adjustments_signal =
134     gtk_signal_new ("scroll_adjustments",
135                     GTK_RUN_LAST,
136                     object_class->type,
137                     GTK_SIGNAL_OFFSET (GtkViewportClass, scroll_adjustments),
138                     gtk_marshal_NONE__POINTER_POINTER,
139                     GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
140   
141   container_class->add = gtk_viewport_add;
142
143   class->scroll_adjustments = gtk_viewport_scroll_adjustments;
144 }
145
146 static void
147 gtk_viewport_set_arg (GtkObject        *object,
148                       GtkArg           *arg,
149                       guint             arg_id)
150 {
151   GtkViewport *viewport;
152
153   viewport = GTK_VIEWPORT (object);
154
155   switch (arg_id)
156     {
157     case ARG_HADJUSTMENT:
158       gtk_viewport_set_hadjustment (viewport, GTK_VALUE_POINTER (*arg));
159       break;
160     case ARG_VADJUSTMENT:
161       gtk_viewport_set_vadjustment (viewport, GTK_VALUE_POINTER (*arg));
162       break;
163     case ARG_SHADOW_TYPE:
164       gtk_viewport_set_shadow_type (viewport, GTK_VALUE_ENUM (*arg));
165       break;
166     default:
167       break;
168     }
169 }
170
171 static void
172 gtk_viewport_get_arg (GtkObject        *object,
173                       GtkArg           *arg,
174                       guint             arg_id)
175 {
176   GtkViewport *viewport;
177
178   viewport = GTK_VIEWPORT (object);
179
180   switch (arg_id)
181     {
182     case ARG_HADJUSTMENT:
183       GTK_VALUE_POINTER (*arg) = viewport->hadjustment;
184       break;
185     case ARG_VADJUSTMENT:
186       GTK_VALUE_POINTER (*arg) = viewport->vadjustment;
187       break;
188     case ARG_SHADOW_TYPE:
189       GTK_VALUE_ENUM (*arg) = viewport->shadow_type;
190       break;
191     default:
192       arg->type = GTK_TYPE_INVALID;
193       break;
194     }
195 }
196
197 static void
198 gtk_viewport_init (GtkViewport *viewport)
199 {
200   GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
201
202   gtk_container_set_resize_mode (GTK_CONTAINER (viewport), GTK_RESIZE_QUEUE);
203   
204   viewport->shadow_type = GTK_SHADOW_IN;
205   viewport->view_window = NULL;
206   viewport->bin_window = NULL;
207   viewport->hadjustment = NULL;
208   viewport->vadjustment = NULL;
209 }
210
211 GtkWidget*
212 gtk_viewport_new (GtkAdjustment *hadjustment,
213                   GtkAdjustment *vadjustment)
214 {
215   GtkWidget *viewport;
216
217   viewport = gtk_widget_new (GTK_TYPE_VIEWPORT,
218                              "hadjustment", hadjustment,
219                              "vadjustment", vadjustment,
220                              NULL);
221
222   return viewport;
223 }
224
225 static void
226 gtk_viewport_destroy (GtkObject *object)
227 {
228   GtkViewport *viewport = GTK_VIEWPORT (object);
229
230   if (viewport->hadjustment)
231     gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment),
232                                    viewport);
233   if (viewport->vadjustment)
234     gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment),
235                                    viewport);
236
237   GTK_OBJECT_CLASS(parent_class)->destroy (object);
238 }
239
240 static void
241 gtk_viewport_finalize (GtkObject *object)
242 {
243   GtkViewport *viewport = GTK_VIEWPORT (object);
244
245   gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
246   gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
247
248   GTK_OBJECT_CLASS(parent_class)->finalize (object);
249 }
250
251 GtkAdjustment*
252 gtk_viewport_get_hadjustment (GtkViewport *viewport)
253 {
254   g_return_val_if_fail (viewport != NULL, NULL);
255   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
256
257   return viewport->hadjustment;
258 }
259
260 GtkAdjustment*
261 gtk_viewport_get_vadjustment (GtkViewport *viewport)
262 {
263   g_return_val_if_fail (viewport != NULL, NULL);
264   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
265
266   return viewport->vadjustment;
267 }
268
269 void
270 gtk_viewport_set_hadjustment (GtkViewport   *viewport,
271                               GtkAdjustment *adjustment)
272 {
273   g_return_if_fail (viewport != NULL);
274   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
275   if (adjustment)
276     g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
277
278   if (viewport->hadjustment && viewport->hadjustment != adjustment)
279     {
280       gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment),
281                                      (gpointer) viewport);
282       gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
283     }
284
285   if (!adjustment)
286     adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
287                                                      0.0, 0.0, 0.0));
288
289   if (viewport->hadjustment != adjustment)
290     {
291       viewport->hadjustment = adjustment;
292       gtk_object_ref (GTK_OBJECT (viewport->hadjustment));
293       gtk_object_sink (GTK_OBJECT (viewport->hadjustment));
294       
295       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
296                           (GtkSignalFunc) gtk_viewport_adjustment_changed,
297                           (gpointer) viewport);
298       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
299                           (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
300                           (gpointer) viewport);
301
302       gtk_viewport_adjustment_changed (adjustment, viewport);
303     }
304 }
305
306 void
307 gtk_viewport_set_vadjustment (GtkViewport   *viewport,
308                               GtkAdjustment *adjustment)
309 {
310   g_return_if_fail (viewport != NULL);
311   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
312   if (adjustment)
313     g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
314
315   if (viewport->vadjustment && viewport->vadjustment != adjustment)
316     {
317       gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment),
318                                      (gpointer) viewport);
319       gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
320     }
321
322   if (!adjustment)
323     adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
324                                                      0.0, 0.0, 0.0));
325
326   if (viewport->vadjustment != adjustment)
327     {
328       viewport->vadjustment = adjustment;
329       gtk_object_ref (GTK_OBJECT (viewport->vadjustment));
330       gtk_object_sink (GTK_OBJECT (viewport->vadjustment));
331       
332       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
333                           (GtkSignalFunc) gtk_viewport_adjustment_changed,
334                           (gpointer) viewport);
335       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
336                           (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
337                           (gpointer) viewport);
338
339       gtk_viewport_adjustment_changed (adjustment, viewport);
340     }
341 }
342
343 static void
344 gtk_viewport_scroll_adjustments (GtkViewport      *viewport,
345                                  GtkAdjustment    *hadjustment,
346                                  GtkAdjustment    *vadjustment)
347 {
348   if (viewport->hadjustment != hadjustment)
349     gtk_viewport_set_hadjustment (viewport, hadjustment);
350   if (viewport->vadjustment != vadjustment)
351     gtk_viewport_set_vadjustment (viewport, vadjustment);
352 }
353
354 void
355 gtk_viewport_set_shadow_type (GtkViewport   *viewport,
356                               GtkShadowType  type)
357 {
358   g_return_if_fail (viewport != NULL);
359   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
360
361   if ((GtkShadowType) viewport->shadow_type != type)
362     {
363       viewport->shadow_type = type;
364
365       if (GTK_WIDGET_VISIBLE (viewport))
366         {
367           gtk_widget_size_allocate (GTK_WIDGET (viewport), &(GTK_WIDGET (viewport)->allocation));
368           gtk_widget_queue_draw (GTK_WIDGET (viewport));
369         }
370     }
371 }
372
373
374 static void
375 gtk_viewport_map (GtkWidget *widget)
376 {
377   GtkBin *bin;
378
379   g_return_if_fail (widget != NULL);
380   g_return_if_fail (GTK_IS_VIEWPORT (widget));
381
382   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
383   bin = GTK_BIN (widget);
384
385   gdk_window_show (widget->window);
386
387   if (bin->child &&
388       GTK_WIDGET_VISIBLE (bin->child) &&
389       !GTK_WIDGET_MAPPED (bin->child))
390     gtk_widget_map (bin->child);
391 }
392
393 static void
394 gtk_viewport_unmap (GtkWidget *widget)
395 {
396   g_return_if_fail (widget != NULL);
397   g_return_if_fail (GTK_IS_VIEWPORT (widget));
398
399   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
400   
401   gdk_window_hide (widget->window);
402 }
403
404 static void
405 gtk_viewport_realize (GtkWidget *widget)
406 {
407   GtkBin *bin;
408   GtkViewport *viewport;
409   GdkWindowAttr attributes;
410   gint attributes_mask;
411   gint event_mask;
412   gint border_width;
413
414   g_return_if_fail (widget != NULL);
415   g_return_if_fail (GTK_IS_VIEWPORT (widget));
416
417   border_width = GTK_CONTAINER (widget)->border_width;
418
419   bin = GTK_BIN (widget);
420   viewport = GTK_VIEWPORT (widget);
421   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
422
423   attributes.x = widget->allocation.x + border_width;
424   attributes.y = widget->allocation.y + border_width;
425   attributes.width = widget->allocation.width - border_width * 2;
426   attributes.height = widget->allocation.height - border_width * 2;
427   attributes.window_type = GDK_WINDOW_CHILD;
428   attributes.wclass = GDK_INPUT_OUTPUT;
429   attributes.visual = gtk_widget_get_visual (widget);
430   attributes.colormap = gtk_widget_get_colormap (widget);
431
432   event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
433   attributes.event_mask = event_mask;
434
435   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
436
437   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
438                                    &attributes, attributes_mask);
439   gdk_window_set_user_data (widget->window, viewport);
440
441   if (viewport->shadow_type != GTK_SHADOW_NONE)
442     {
443       attributes.x = widget->style->klass->xthickness;
444       attributes.y = widget->style->klass->ythickness;
445     }
446   else
447     {
448       attributes.x = 0;
449       attributes.y = 0;
450     }
451
452   attributes.width = MAX (1, widget->allocation.width - attributes.x * 2 - border_width * 2);
453   attributes.height = MAX (1, widget->allocation.height - attributes.y * 2 - border_width * 2);
454   attributes.event_mask = 0;
455
456   viewport->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
457   gdk_window_set_user_data (viewport->view_window, viewport);
458
459   attributes.x = 0;
460   attributes.y = 0;
461
462   if (bin->child)
463     {
464       attributes.width = viewport->hadjustment->upper;
465       attributes.height = viewport->vadjustment->upper;
466     }
467   
468   attributes.event_mask = event_mask;
469
470   viewport->bin_window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
471   gdk_window_set_user_data (viewport->bin_window, viewport);
472
473   if (bin->child)
474     gtk_widget_set_parent_window (bin->child, viewport->bin_window);
475
476   widget->style = gtk_style_attach (widget->style, widget->window);
477   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
478   gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
479
480    gtk_paint_flat_box(widget->style, viewport->bin_window, GTK_STATE_NORMAL,
481                       GTK_SHADOW_NONE,
482                       NULL, widget, "viewportbin",
483                       0, 0, -1, -1);
484    
485   gdk_window_show (viewport->bin_window);
486   gdk_window_show (viewport->view_window);
487 }
488
489 static void
490 gtk_viewport_unrealize (GtkWidget *widget)
491 {
492   GtkViewport *viewport;
493
494   g_return_if_fail (widget != NULL);
495   g_return_if_fail (GTK_IS_VIEWPORT (widget));
496
497   viewport = GTK_VIEWPORT (widget);
498
499   gdk_window_set_user_data (viewport->view_window, NULL);
500   gdk_window_destroy (viewport->view_window);
501   viewport->view_window = NULL;
502
503   gdk_window_set_user_data (viewport->bin_window, NULL);
504   gdk_window_destroy (viewport->bin_window);
505   viewport->bin_window = NULL;
506
507   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
508     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
509 }
510
511 static void
512 gtk_viewport_paint (GtkWidget    *widget,
513                     GdkRectangle *area)
514 {
515   GtkViewport *viewport;
516
517   g_return_if_fail (widget != NULL);
518   g_return_if_fail (GTK_IS_VIEWPORT (widget));
519   g_return_if_fail (area != NULL);
520
521   if (GTK_WIDGET_DRAWABLE (widget))
522     {
523       viewport = GTK_VIEWPORT (widget);
524
525       gtk_draw_shadow (widget->style, widget->window,
526                        GTK_STATE_NORMAL, viewport->shadow_type,
527                        0, 0, -1, -1);
528     }
529 }
530
531 static void
532 gtk_viewport_draw (GtkWidget    *widget,
533                    GdkRectangle *area)
534 {
535   GtkViewport *viewport;
536   GtkBin *bin;
537   GdkRectangle tmp_area;
538   GdkRectangle child_area;
539   gint border_width;
540
541   g_return_if_fail (widget != NULL);
542   g_return_if_fail (GTK_IS_VIEWPORT (widget));
543   g_return_if_fail (area != NULL);
544
545   if (GTK_WIDGET_DRAWABLE (widget))
546     {
547       viewport = GTK_VIEWPORT (widget);
548       bin = GTK_BIN (widget);
549
550       border_width = GTK_CONTAINER (widget)->border_width;
551       
552       tmp_area = *area;
553       tmp_area.x -= border_width;
554       tmp_area.y -= border_width;
555       
556       gtk_viewport_paint (widget, &tmp_area);
557
558       if (bin->child)
559         {
560           tmp_area.x += viewport->hadjustment->value - widget->style->klass->xthickness;
561           tmp_area.y += viewport->vadjustment->value - widget->style->klass->ythickness;
562
563           if (gtk_widget_intersect (bin->child, &tmp_area, &child_area))
564             gtk_widget_draw (bin->child, &child_area);
565         }
566     }
567 }
568
569 static gint
570 gtk_viewport_expose (GtkWidget      *widget,
571                      GdkEventExpose *event)
572 {
573   GtkViewport *viewport;
574   GtkBin *bin;
575   GdkEventExpose child_event;
576
577   g_return_val_if_fail (widget != NULL, FALSE);
578   g_return_val_if_fail (GTK_IS_VIEWPORT (widget), FALSE);
579   g_return_val_if_fail (event != NULL, FALSE);
580
581   if (GTK_WIDGET_DRAWABLE (widget))
582     {
583       viewport = GTK_VIEWPORT (widget);
584       bin = GTK_BIN (widget);
585
586       if (event->window == widget->window)
587         gtk_viewport_paint (widget, &event->area);
588
589       child_event = *event;
590       if ((event->window == viewport->bin_window) &&
591           (bin->child != NULL) &&
592           GTK_WIDGET_NO_WINDOW (bin->child) &&
593           gtk_widget_intersect (bin->child, &event->area, &child_event.area))
594         gtk_widget_event (bin->child, (GdkEvent*) &child_event);
595     }
596
597   return FALSE;
598 }
599
600 static void
601 gtk_viewport_add (GtkContainer *container,
602                   GtkWidget    *child)
603 {
604   GtkBin *bin;
605
606   g_return_if_fail (container != NULL);
607   g_return_if_fail (GTK_IS_VIEWPORT (container));
608   g_return_if_fail (child != NULL);
609
610   bin = GTK_BIN (container);
611   g_return_if_fail (bin->child == NULL);
612
613   gtk_widget_set_parent_window (child, GTK_VIEWPORT (bin)->bin_window);
614
615   GTK_CONTAINER_CLASS (parent_class)->add (container, child);
616 }
617
618 static void
619 gtk_viewport_size_request (GtkWidget      *widget,
620                            GtkRequisition *requisition)
621 {
622   GtkViewport *viewport;
623   GtkBin *bin;
624
625   g_return_if_fail (widget != NULL);
626   g_return_if_fail (GTK_IS_VIEWPORT (widget));
627   g_return_if_fail (requisition != NULL);
628
629   viewport = GTK_VIEWPORT (widget);
630   bin = GTK_BIN (widget);
631
632   requisition->width = (GTK_CONTAINER (widget)->border_width +
633                         GTK_WIDGET (widget)->style->klass->xthickness) * 2 + 5;
634
635   requisition->height = (GTK_CONTAINER (widget)->border_width * 2 +
636                          GTK_WIDGET (widget)->style->klass->ythickness) * 2 + 5;
637
638   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
639     gtk_widget_size_request (bin->child, &bin->child->requisition);
640 }
641
642 static void
643 gtk_viewport_size_allocate (GtkWidget     *widget,
644                             GtkAllocation *allocation)
645 {
646   GtkViewport *viewport;
647   GtkBin *bin;
648   GtkAllocation child_allocation;
649   gint hval, vval;
650   gint border_width;
651
652   g_return_if_fail (widget != NULL);
653   g_return_if_fail (GTK_IS_VIEWPORT (widget));
654   g_return_if_fail (allocation != NULL);
655
656   widget->allocation = *allocation;
657   viewport = GTK_VIEWPORT (widget);
658   bin = GTK_BIN (widget);
659
660   border_width = GTK_CONTAINER (widget)->border_width;
661
662   child_allocation.x = 0;
663   child_allocation.y = 0;
664
665   if (viewport->shadow_type != GTK_SHADOW_NONE)
666     {
667       child_allocation.x = GTK_WIDGET (viewport)->style->klass->xthickness;
668       child_allocation.y = GTK_WIDGET (viewport)->style->klass->ythickness;
669     }
670
671   child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2 - border_width * 2);
672   child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2 - border_width * 2);
673
674   if (GTK_WIDGET_REALIZED (widget))
675     {
676       gdk_window_move_resize (widget->window,
677                               allocation->x + border_width,
678                               allocation->y + border_width,
679                               allocation->width - border_width * 2,
680                               allocation->height - border_width * 2);
681
682       gdk_window_move_resize (viewport->view_window,
683                               child_allocation.x,
684                               child_allocation.y,
685                               child_allocation.width,
686                               child_allocation.height);
687        gtk_paint_flat_box(widget->style, viewport->bin_window, GTK_STATE_NORMAL,
688                           GTK_SHADOW_NONE,
689                           NULL, widget, "viewportbin",
690                           0, 0, -1, -1);
691     }
692
693   viewport->hadjustment->page_size = child_allocation.width;
694   viewport->hadjustment->page_increment = viewport->hadjustment->page_size / 2;
695   viewport->hadjustment->step_increment = 10;
696
697   viewport->vadjustment->page_size = child_allocation.height;
698   viewport->vadjustment->page_increment = viewport->vadjustment->page_size / 2;
699   viewport->vadjustment->step_increment = 10;
700
701   hval = viewport->hadjustment->value;
702   vval = viewport->vadjustment->value;
703
704   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
705     {
706       viewport->hadjustment->lower = 0;
707       viewport->hadjustment->upper = MAX (bin->child->requisition.width,
708                                           child_allocation.width);
709
710       hval = CLAMP (hval, 0,
711                     viewport->hadjustment->upper -
712                     viewport->hadjustment->page_size);
713
714       viewport->vadjustment->lower = 0;
715       viewport->vadjustment->upper = MAX (bin->child->requisition.height,
716                                           child_allocation.height);
717
718       vval = CLAMP (vval, 0,
719                     viewport->vadjustment->upper -
720                     viewport->vadjustment->page_size);
721     }
722
723   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
724     {
725       child_allocation.x = 0;
726       child_allocation.y = 0;
727
728       child_allocation.width = viewport->hadjustment->upper;
729       child_allocation.height = viewport->vadjustment->upper;
730
731       if (!GTK_WIDGET_REALIZED (widget))
732         gtk_widget_realize (widget);
733
734       gdk_window_resize (viewport->bin_window,
735                          child_allocation.width,
736                          child_allocation.height);
737
738       child_allocation.x = 0;
739       child_allocation.y = 0;
740       gtk_widget_size_allocate (bin->child, &child_allocation);
741     }
742
743   gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "changed");
744   gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "changed");
745   if (viewport->hadjustment->value != hval)
746     {
747       viewport->hadjustment->value = hval;
748       gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "value_changed");
749     }
750   if (viewport->vadjustment->value != vval)
751     {
752       viewport->vadjustment->value = vval;
753       gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "value_changed");
754     }
755 }
756
757 static void
758 gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
759                                  gpointer       data)
760 {
761   GtkViewport *viewport;
762
763   g_return_if_fail (adjustment != NULL);
764   g_return_if_fail (data != NULL);
765   g_return_if_fail (GTK_IS_VIEWPORT (data));
766
767   viewport = GTK_VIEWPORT (data);
768 }
769
770 static void
771 gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
772                                        gpointer       data)
773 {
774   GtkViewport *viewport;
775   GtkBin *bin;
776   GtkAllocation child_allocation;
777   gint width, height;
778
779   g_return_if_fail (adjustment != NULL);
780   g_return_if_fail (data != NULL);
781   g_return_if_fail (GTK_IS_VIEWPORT (data));
782
783   viewport = GTK_VIEWPORT (data);
784   bin = GTK_BIN (data);
785
786   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
787     {
788       gdk_window_get_size (viewport->view_window, &width, &height);
789
790       child_allocation.x = 0;
791       child_allocation.y = 0;
792
793       if (viewport->hadjustment->lower != (viewport->hadjustment->upper -
794                                            viewport->hadjustment->page_size))
795         child_allocation.x =  viewport->hadjustment->lower - viewport->hadjustment->value;
796
797       if (viewport->vadjustment->lower != (viewport->vadjustment->upper -
798                                            viewport->vadjustment->page_size))
799         child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
800
801       if (GTK_WIDGET_REALIZED (viewport))
802         gdk_window_move (viewport->bin_window,
803                          child_allocation.x,
804                          child_allocation.y);
805     }
806 }
807
808 static void
809 gtk_viewport_style_set (GtkWidget *widget,
810                         GtkStyle  *previous_style)
811 {
812    GtkViewport *viewport;
813    
814    if (GTK_WIDGET_REALIZED (widget) &&
815        !GTK_WIDGET_NO_WINDOW (widget))
816      {
817         viewport = GTK_VIEWPORT (widget);
818         
819         gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
820         gtk_style_set_background (widget->style, widget->window, widget->state);
821         gtk_paint_flat_box(widget->style, viewport->bin_window, GTK_STATE_NORMAL,
822                            GTK_SHADOW_NONE,
823                            NULL, widget, "viewportbin",
824                            0, 0, -1, -1);
825         if (GTK_WIDGET_DRAWABLE (widget))
826           {
827              gdk_window_clear (widget->window);
828              gdk_window_clear (viewport->bin_window);
829           }
830      }
831 }