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