]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/win_gtk.c
put back obviously-not-redundant resize
[wxWidgets.git] / src / gtk / win_gtk.c
1 /* ///////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/win_gtk.c
3 // Purpose: Native GTK+ widget for wxWidgets, based on GtkLayout and
4 // GtkFixed. It makes use of the gravity window property and
5 // therefore does not work with GTK 1.0.
6 // Author: Robert Roebling
7 // Id: $Id$
8 // Copyright: (c) 1998 Robert Roebling
9 // Licence: wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////// */
11
12 #ifdef VMS
13 #define XCheckIfEvent XCHECKIFEVENT
14 #endif
15
16 #include "wx/platform.h"
17 #include "wx/gtk/win_gtk.h"
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif /* __cplusplus */
22
23 typedef struct _GtkPizzaAdjData GtkPizzaAdjData;
24
25 struct _GtkPizzaAdjData
26 {
27 gint dx;
28 gint dy;
29 };
30
31 static void gtk_pizza_class_init (GtkPizzaClass *klass);
32 static void gtk_pizza_init (GtkPizza *pizza);
33
34 static void gtk_pizza_realize (GtkWidget *widget);
35 static void gtk_pizza_unrealize (GtkWidget *widget);
36
37 static void gtk_pizza_map (GtkWidget *widget);
38
39 static void gtk_pizza_size_request (GtkWidget *widget,
40 GtkRequisition *requisition);
41 static void gtk_pizza_size_allocate (GtkWidget *widget,
42 GtkAllocation *allocation);
43 static gint gtk_pizza_expose (GtkWidget *widget,
44 GdkEventExpose *event);
45 static void gtk_pizza_style_set (GtkWidget *widget,
46 GtkStyle *previous_style);
47 static void gtk_pizza_add (GtkContainer *container,
48 GtkWidget *widget);
49 static void gtk_pizza_remove (GtkContainer *container,
50 GtkWidget *widget);
51 static void gtk_pizza_forall (GtkContainer *container,
52 gboolean include_internals,
53 GtkCallback callback,
54 gpointer callback_data);
55
56 static void gtk_pizza_allocate_child (GtkPizza *pizza,
57 GtkPizzaChild *child);
58 static void gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
59 gpointer cb_data);
60
61 static GtkType gtk_pizza_child_type (GtkContainer *container);
62
63 static void gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
64 GtkAdjustment *hadj,
65 GtkAdjustment *vadj);
66
67 static GtkWidgetClass* pizza_parent_class;
68
69 GtkType
70 gtk_pizza_get_type ()
71 {
72 static GtkType pizza_type = 0;
73
74 if (!pizza_type)
75 {
76 static const GTypeInfo pizza_info =
77 {
78 sizeof (GtkPizzaClass),
79 NULL, /* base_init */
80 NULL, /* base_finalize */
81 (GClassInitFunc) gtk_pizza_class_init,
82 NULL, /* class_finalize */
83 NULL, /* class_data */
84 sizeof (GtkPizza),
85 16, /* n_preallocs */
86 (GInstanceInitFunc) gtk_pizza_init,
87 NULL
88 };
89 pizza_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkPizza", &pizza_info, (GTypeFlags)0);
90 }
91
92 return pizza_type;
93 }
94
95 /* Marshaller needed for set_scroll_adjustments signal,
96 generated with GLib-2.4.6 glib-genmarshal */
97 #define g_marshal_value_peek_object(v) g_value_get_object (v)
98 static void
99 g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
100 GValue *return_value,
101 guint n_param_values,
102 const GValue *param_values,
103 gpointer invocation_hint,
104 gpointer marshal_data)
105 {
106 typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
107 gpointer arg_1,
108 gpointer arg_2,
109 gpointer data2);
110 register GMarshalFunc_VOID__OBJECT_OBJECT callback;
111 register GCClosure *cc = (GCClosure*) closure;
112 register gpointer data1, data2;
113
114 g_return_if_fail (n_param_values == 3);
115
116 if (G_CCLOSURE_SWAP_DATA (closure))
117 {
118 data1 = closure->data;
119 data2 = g_value_peek_pointer (param_values + 0);
120 }
121 else
122 {
123 data1 = g_value_peek_pointer (param_values + 0);
124 data2 = closure->data;
125 }
126 callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
127
128 callback (data1,
129 g_marshal_value_peek_object (param_values + 1),
130 g_marshal_value_peek_object (param_values + 2),
131 data2);
132 }
133
134 static void
135 gtk_pizza_class_init (GtkPizzaClass *klass)
136 {
137 GtkObjectClass *object_class;
138 GtkWidgetClass *widget_class;
139 GtkContainerClass *container_class;
140
141 object_class = (GtkObjectClass*) klass;
142 widget_class = (GtkWidgetClass*) klass;
143 container_class = (GtkContainerClass*) klass;
144 pizza_parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
145
146 widget_class->map = gtk_pizza_map;
147 widget_class->realize = gtk_pizza_realize;
148 widget_class->unrealize = gtk_pizza_unrealize;
149 widget_class->size_request = gtk_pizza_size_request;
150 widget_class->size_allocate = gtk_pizza_size_allocate;
151 widget_class->expose_event = gtk_pizza_expose;
152 widget_class->style_set = gtk_pizza_style_set;
153
154 container_class->add = gtk_pizza_add;
155 container_class->remove = gtk_pizza_remove;
156 container_class->forall = gtk_pizza_forall;
157
158 container_class->child_type = gtk_pizza_child_type;
159
160 klass->set_scroll_adjustments = gtk_pizza_scroll_set_adjustments;
161
162 widget_class->set_scroll_adjustments_signal =
163 g_signal_new(
164 "set_scroll_adjustments",
165 G_TYPE_FROM_CLASS(object_class),
166 G_SIGNAL_RUN_LAST,
167 G_STRUCT_OFFSET(GtkPizzaClass, set_scroll_adjustments),
168 NULL,
169 NULL,
170 g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
171 G_TYPE_NONE,
172 2,
173 GTK_TYPE_ADJUSTMENT,
174 GTK_TYPE_ADJUSTMENT);
175 }
176
177 static GtkType
178 gtk_pizza_child_type (GtkContainer *container)
179 {
180 return GTK_TYPE_WIDGET;
181 }
182
183 static void
184 gtk_pizza_init (GtkPizza *pizza)
185 {
186 GTK_WIDGET_UNSET_FLAGS (pizza, GTK_NO_WINDOW);
187
188 pizza->shadow_type = GTK_MYSHADOW_NONE;
189
190 pizza->children = NULL;
191
192 pizza->bin_window = NULL;
193
194 pizza->m_xoffset = 0;
195 pizza->m_yoffset = 0;
196 }
197
198 GtkWidget*
199 gtk_pizza_new ()
200 {
201 GtkPizza *pizza;
202
203 pizza = g_object_new (gtk_pizza_get_type (), NULL);
204
205 return GTK_WIDGET (pizza);
206 }
207
208 gint gtk_pizza_get_xoffset (GtkPizza *pizza)
209 {
210 g_return_val_if_fail ( (pizza != NULL), -1 );
211 g_return_val_if_fail ( (GTK_IS_PIZZA (pizza)), -1 );
212
213 return pizza->m_xoffset;
214 }
215
216 gint gtk_pizza_get_yoffset (GtkPizza *pizza)
217 {
218 g_return_val_if_fail ( (pizza != NULL), -1 );
219 g_return_val_if_fail ( (GTK_IS_PIZZA (pizza)), -1 );
220
221 return pizza->m_yoffset;
222 }
223
224 void gtk_pizza_set_xoffset (GtkPizza *pizza, gint xoffset)
225 {
226 g_return_if_fail (pizza != NULL);
227 g_return_if_fail (GTK_IS_PIZZA (pizza));
228
229 pizza->m_xoffset = xoffset;
230 // do something
231 }
232
233 void gtk_pizza_set_yoffset (GtkPizza *pizza, gint yoffset)
234 {
235 g_return_if_fail (pizza != NULL);
236 g_return_if_fail (GTK_IS_PIZZA (pizza));
237
238 pizza->m_xoffset = yoffset;
239 // do something
240 }
241
242 gint gtk_pizza_get_rtl_offset (GtkPizza *pizza)
243 {
244 gint width;
245 gint border;
246
247 g_return_val_if_fail ( (pizza != NULL), 0 );
248 g_return_val_if_fail ( (GTK_IS_PIZZA (pizza)), 0 );
249
250 if (!pizza->bin_window) return 0;
251
252 gdk_window_get_geometry( pizza->bin_window, NULL, NULL, &width, NULL, NULL );
253
254 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
255 border = 0;
256 else
257 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
258 border = 1;
259 else
260 border = 2;
261
262 return width-border*2;
263 }
264
265
266 static void
267 gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
268 GtkAdjustment *hadj,
269 GtkAdjustment *vadj)
270 {
271 /* We handle scrolling in the wxScrolledWindow, not here. */
272 }
273
274 void
275 gtk_pizza_set_shadow_type (GtkPizza *pizza,
276 GtkMyShadowType type)
277 {
278 g_return_if_fail (pizza != NULL);
279 g_return_if_fail (GTK_IS_PIZZA (pizza));
280
281 if (pizza->shadow_type != type)
282 {
283 pizza->shadow_type = type;
284
285 if (GTK_WIDGET_VISIBLE (pizza))
286 {
287 gtk_widget_size_allocate (GTK_WIDGET (pizza), &(GTK_WIDGET (pizza)->allocation));
288 gtk_widget_queue_draw (GTK_WIDGET (pizza));
289 }
290 }
291 }
292
293 void
294 gtk_pizza_put (GtkPizza *pizza,
295 GtkWidget *widget,
296 gint x,
297 gint y,
298 gint width,
299 gint height)
300 {
301 GtkPizzaChild *child_info;
302
303 g_return_if_fail (pizza != NULL);
304 g_return_if_fail (GTK_IS_PIZZA (pizza));
305 g_return_if_fail (widget != NULL);
306
307 if (gtk_widget_get_direction( GTK_WIDGET(pizza) ) == GTK_TEXT_DIR_RTL)
308 {
309 /* reverse horizontal placement */
310 x = GTK_WIDGET(pizza)->allocation.width - x - width;
311 }
312
313 child_info = g_new (GtkPizzaChild, 1);
314
315 child_info->widget = widget;
316 child_info->x = x;
317 child_info->y = y;
318 child_info->width = width;
319 child_info->height = height;
320
321 pizza->children = g_list_append (pizza->children, child_info);
322
323 if (GTK_WIDGET_REALIZED (pizza))
324 gtk_widget_set_parent_window (widget, pizza->bin_window);
325
326 gtk_widget_set_parent (widget, GTK_WIDGET (pizza));
327
328 gtk_widget_set_size_request (widget, width, height);
329 }
330
331 void
332 gtk_pizza_set_size (GtkPizza *pizza,
333 GtkWidget *widget,
334 gint x,
335 gint y,
336 gint width,
337 gint height)
338 {
339 GtkPizzaChild *child;
340 GList *children;
341
342 g_return_if_fail (pizza != NULL);
343 g_return_if_fail (GTK_IS_PIZZA (pizza));
344 g_return_if_fail (widget != NULL);
345
346 #ifndef WX_WARN_ILLEGAL_SETSIZE
347 /* this really shouldn't happen -- but it does, a lot, right now and we
348 can't pass negative values to gtk_widget_set_size_request() without getting
349 a warning printed out, so filter them out here */
350 if ( width < 0 )
351 width = 0;
352 if ( height < 0 )
353 height = 0;
354 #endif
355
356 children = pizza->children;
357 while (children)
358 {
359 child = children->data;
360 children = children->next;
361
362 if (child->widget == widget)
363 {
364 if ((child->x == x) &&
365 (child->y == y) &&
366 (child->width == width) &&
367 (child->height == height)) return;
368
369 child->x = x;
370 child->y = y;
371 child->width = width;
372 child->height = height;
373
374 gtk_widget_set_size_request (widget, width, height);
375
376 return;
377 }
378 }
379 }
380
381 static void
382 gtk_pizza_map (GtkWidget *widget)
383 {
384 GtkPizza *pizza;
385 GtkPizzaChild *child;
386 GList *children;
387
388 g_return_if_fail (widget != NULL);
389 g_return_if_fail (GTK_IS_PIZZA (widget));
390
391 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
392 pizza = GTK_PIZZA (widget);
393
394 children = pizza->children;
395 while (children)
396 {
397 child = children->data;
398 children = children->next;
399
400 if ( GTK_WIDGET_VISIBLE (child->widget) &&
401 !GTK_WIDGET_MAPPED (child->widget) )
402 {
403 gtk_widget_map (child->widget);
404 }
405 }
406
407 gdk_window_show (widget->window);
408 gdk_window_show (pizza->bin_window);
409 }
410
411 static void
412 gtk_pizza_realize (GtkWidget *widget)
413 {
414 GtkPizza *pizza;
415 GdkWindowAttr attributes;
416 gint attributes_mask;
417 GtkPizzaChild *child;
418 GList *children;
419
420 g_return_if_fail (widget != NULL);
421 g_return_if_fail (GTK_IS_PIZZA (widget));
422
423 pizza = GTK_PIZZA (widget);
424 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
425
426 attributes.window_type = GDK_WINDOW_CHILD;
427
428 attributes.x = widget->allocation.x;
429 attributes.y = widget->allocation.y;
430 attributes.width = widget->allocation.width;
431 attributes.height = widget->allocation.height;
432
433 #ifndef __WXUNIVERSAL__
434 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
435 {
436 /* no border, no changes to sizes */
437 }
438 else if (pizza->shadow_type == GTK_MYSHADOW_THIN)
439 {
440 /* GTK_MYSHADOW_THIN == wxSIMPLE_BORDER */
441 attributes.x += 1;
442 attributes.y += 1;
443 attributes.width -= 2;
444 attributes.height -= 2;
445 }
446 else
447 {
448 /* GTK_MYSHADOW_IN == wxSUNKEN_BORDER */
449 /* GTK_MYSHADOW_OUT == wxRAISED_BORDER */
450 attributes.x += 2;
451 attributes.y += 2;
452 attributes.width -= 4;
453 attributes.height -= 4;
454 }
455 #endif /* __WXUNIVERSAL__ */
456
457 /* minimal size */
458 if (attributes.width < 2) attributes.width = 2;
459 if (attributes.height < 2) attributes.height = 2;
460
461 attributes.wclass = GDK_INPUT_OUTPUT;
462 attributes.visual = gtk_widget_get_visual (widget);
463 attributes.colormap = gtk_widget_get_colormap (widget);
464 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
465 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
466
467 widget->window = gdk_window_new(gtk_widget_get_parent_window (widget),
468 &attributes, attributes_mask);
469 gdk_window_set_user_data (widget->window, widget);
470
471 attributes.x = 0;
472 attributes.y = 0;
473
474 attributes.event_mask = gtk_widget_get_events (widget);
475 attributes.event_mask |= GDK_EXPOSURE_MASK |
476 GDK_SCROLL_MASK |
477 GDK_POINTER_MOTION_MASK |
478 GDK_POINTER_MOTION_HINT_MASK |
479 GDK_BUTTON_MOTION_MASK |
480 GDK_BUTTON1_MOTION_MASK |
481 GDK_BUTTON2_MOTION_MASK |
482 GDK_BUTTON3_MOTION_MASK |
483 GDK_BUTTON_PRESS_MASK |
484 GDK_BUTTON_RELEASE_MASK |
485 GDK_KEY_PRESS_MASK |
486 GDK_KEY_RELEASE_MASK |
487 GDK_ENTER_NOTIFY_MASK |
488 GDK_LEAVE_NOTIFY_MASK |
489 GDK_FOCUS_CHANGE_MASK;
490
491 pizza->bin_window = gdk_window_new(widget->window,
492 &attributes, attributes_mask);
493 gdk_window_set_user_data (pizza->bin_window, widget);
494
495 widget->style = gtk_style_attach (widget->style, widget->window);
496 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
497 gtk_style_set_background (widget->style, pizza->bin_window, GTK_STATE_NORMAL );
498
499 /*
500 gdk_window_set_back_pixmap( widget->window, NULL, FALSE );
501 gdk_window_set_back_pixmap( pizza->bin_window, NULL, FALSE );
502 */
503
504 /* cannot be done before realisation */
505 children = pizza->children;
506 while (children)
507 {
508 child = children->data;
509 children = children->next;
510
511 gtk_widget_set_parent_window (child->widget, pizza->bin_window);
512 }
513 }
514
515 static void
516 gtk_pizza_unrealize (GtkWidget *widget)
517 {
518 GtkPizza *pizza;
519
520 g_return_if_fail (widget != NULL);
521 g_return_if_fail (GTK_IS_PIZZA (widget));
522
523 pizza = GTK_PIZZA (widget);
524
525 gdk_window_set_user_data (pizza->bin_window, NULL);
526 gdk_window_destroy (pizza->bin_window);
527 pizza->bin_window = NULL;
528
529 if (pizza_parent_class->unrealize)
530 pizza_parent_class->unrealize(widget);
531 }
532
533 static void
534 gtk_pizza_size_request (GtkWidget *widget,
535 GtkRequisition *requisition)
536 {
537 GtkPizza *pizza;
538 GtkPizzaChild *child;
539 GList *children;
540 GtkRequisition child_requisition;
541
542 g_return_if_fail (widget != NULL);
543 g_return_if_fail (GTK_IS_PIZZA (widget));
544 g_return_if_fail (requisition != NULL);
545
546 pizza = GTK_PIZZA (widget);
547
548 children = pizza->children;
549 while (children)
550 {
551 child = children->data;
552 children = children->next;
553
554 if (GTK_WIDGET_VISIBLE (child->widget))
555 {
556 gtk_widget_size_request (child->widget, &child_requisition);
557 }
558 }
559
560 /* request very little, I'm not sure if requesting nothing
561 will always have positive effects on stability... */
562 requisition->width = 2;
563 requisition->height = 2;
564 }
565
566 static void
567 gtk_pizza_size_allocate (GtkWidget *widget,
568 GtkAllocation *allocation)
569 {
570 GtkPizza *pizza;
571 gint border;
572 gint x,y,w,h;
573 GtkPizzaChild *child;
574 GList *children;
575 gboolean only_resize;
576
577 g_return_if_fail (widget != NULL);
578 g_return_if_fail (GTK_IS_PIZZA(widget));
579 g_return_if_fail (allocation != NULL);
580
581 pizza = GTK_PIZZA (widget);
582
583 only_resize = ((widget->allocation.x == allocation->x) &&
584 (widget->allocation.y == allocation->y));
585 widget->allocation = *allocation;
586
587 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
588 border = 0;
589 else
590 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
591 border = 1;
592 else
593 border = 2;
594
595 x = allocation->x + border;
596 y = allocation->y + border;
597 w = allocation->width - border*2;
598 h = allocation->height - border*2;
599 if (w < 0)
600 w = 0;
601 if (h < 0)
602 h = 0;
603
604 if (GTK_WIDGET_REALIZED (widget))
605 {
606 if (only_resize)
607 gdk_window_resize( widget->window, w, h );
608 else
609 gdk_window_move_resize( widget->window, x, y, w, h );
610
611 gdk_window_resize( pizza->bin_window, w, h );
612 }
613
614 children = pizza->children;
615 while (children)
616 {
617 child = children->data;
618 children = children->next;
619
620 gtk_pizza_allocate_child (pizza, child);
621 }
622 }
623
624 static gint
625 gtk_pizza_expose (GtkWidget *widget,
626 GdkEventExpose *event)
627 {
628 GtkPizza *pizza;
629
630 g_return_val_if_fail (widget != NULL, FALSE);
631 g_return_val_if_fail (GTK_IS_PIZZA (widget), FALSE);
632 g_return_val_if_fail (event != NULL, FALSE);
633
634 pizza = (GtkPizza*)widget;
635
636 if (event->window != pizza->bin_window)
637 return FALSE;
638
639 pizza_parent_class->expose_event(widget, event);
640
641 return FALSE;
642 }
643
644 static void
645 gtk_pizza_style_set(GtkWidget *widget, GtkStyle *previous_style)
646 {
647 if (GTK_WIDGET_REALIZED(widget))
648 {
649 gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
650 gtk_style_set_background(widget->style, GTK_PIZZA(widget)->bin_window, GTK_STATE_NORMAL );
651 }
652
653 pizza_parent_class->style_set(widget, previous_style);
654 }
655
656 static void
657 gtk_pizza_add (GtkContainer *container,
658 GtkWidget *widget)
659 {
660 g_return_if_fail (container != NULL);
661 g_return_if_fail (GTK_IS_PIZZA (container));
662 g_return_if_fail (widget != NULL);
663
664 gtk_pizza_put (GTK_PIZZA (container), widget, 0, 0, 20, 20 );
665 }
666
667 static void
668 gtk_pizza_remove (GtkContainer *container,
669 GtkWidget *widget)
670 {
671 GtkPizza *pizza;
672 GtkPizzaChild *child;
673 GList *children;
674
675 g_return_if_fail (container != NULL);
676 g_return_if_fail (GTK_IS_PIZZA (container));
677 g_return_if_fail (widget != NULL);
678
679 pizza = GTK_PIZZA (container);
680
681 children = pizza->children;
682 while (children)
683 {
684 child = children->data;
685
686 if (child->widget == widget)
687 {
688 gtk_widget_unparent (widget);
689
690 /* security checks */
691 g_return_if_fail (GTK_IS_WIDGET (widget));
692
693 pizza->children = g_list_remove_link (pizza->children, children);
694 g_list_free (children);
695 g_free (child);
696
697 /* security checks */
698 g_return_if_fail (GTK_IS_WIDGET (widget));
699
700 break;
701 }
702
703 children = children->next;
704 }
705 }
706
707 static void
708 gtk_pizza_forall (GtkContainer *container,
709 gboolean include_internals,
710 GtkCallback callback,
711 gpointer callback_data)
712 {
713 GtkPizza *pizza;
714 GtkPizzaChild *child;
715 GList *children;
716
717 g_return_if_fail (container != NULL);
718 g_return_if_fail (GTK_IS_PIZZA (container));
719 g_return_if_fail (callback != (GtkCallback)NULL);
720
721 pizza = GTK_PIZZA (container);
722
723 children = pizza->children;
724 while (children)
725 {
726 child = children->data;
727 children = children->next;
728
729 (* callback) (child->widget, callback_data);
730 }
731 }
732
733 static void
734 gtk_pizza_allocate_child (GtkPizza *pizza,
735 GtkPizzaChild *child)
736 {
737 GtkAllocation allocation;
738 GtkRequisition requisition;
739
740 allocation.x = child->x - pizza->m_xoffset;
741 allocation.y = child->y - pizza->m_yoffset;
742 gtk_widget_get_child_requisition (child->widget, &requisition);
743 allocation.width = requisition.width;
744 allocation.height = requisition.height;
745
746 if (gtk_widget_get_direction( GTK_WIDGET(pizza) ) == GTK_TEXT_DIR_RTL)
747 {
748 /* reverse horizontal placement */
749 gint offset,border;
750
751 offset = GTK_WIDGET(pizza)->allocation.width;
752
753 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
754 border = 0;
755 else
756 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
757 border = 1;
758 else
759 border = 2;
760 offset -= border*2;
761
762 allocation.x = offset - child->x - allocation.width - pizza->m_xoffset;
763 }
764
765 gtk_widget_size_allocate (child->widget, &allocation);
766 }
767
768 static void
769 gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
770 gpointer cb_data)
771 {
772 GtkPizzaAdjData *data = cb_data;
773
774 widget->allocation.x += data->dx;
775 widget->allocation.y += data->dy;
776
777 if (GTK_WIDGET_NO_WINDOW (widget) && GTK_IS_CONTAINER (widget))
778 {
779 gtk_container_forall (GTK_CONTAINER (widget),
780 gtk_pizza_adjust_allocations_recurse,
781 cb_data);
782 }
783 }
784
785 static void
786 gtk_pizza_adjust_allocations (GtkPizza *pizza,
787 gint dx,
788 gint dy)
789 {
790 GList *tmp_list;
791 GtkPizzaAdjData data;
792
793 data.dx = dx;
794 data.dy = dy;
795
796 tmp_list = pizza->children;
797 while (tmp_list)
798 {
799 GtkPizzaChild *child = tmp_list->data;
800 tmp_list = tmp_list->next;
801
802 child->widget->allocation.x += dx;
803 child->widget->allocation.y += dy;
804
805 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
806 GTK_IS_CONTAINER (child->widget))
807 {
808 gtk_container_forall (GTK_CONTAINER (child->widget),
809 gtk_pizza_adjust_allocations_recurse,
810 &data);
811 }
812 }
813 }
814
815 void
816 gtk_pizza_scroll (GtkPizza *pizza, gint dx, gint dy)
817 {
818 pizza->m_xoffset += dx;
819 pizza->m_yoffset += dy;
820
821 gtk_pizza_adjust_allocations (pizza, -dx, -dy);
822
823 if (pizza->bin_window)
824 gdk_window_scroll( pizza->bin_window, -dx, -dy );
825 }
826
827 #ifdef __cplusplus
828 }
829 #endif /* __cplusplus */