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