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