]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/win_gtk.c
d7f721c56b66d89ec0844f63fde2ce1d3ad57d9b
[wxWidgets.git] / src / gtk1 / win_gtk.c
1 /* ///////////////////////////////////////////////////////////////////////////
2 // Name: win_gtk.c
3 // Purpose: native GTK+ widget for wxWindows
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////// */
9
10 #include "wx/gtk/win_gtk.h"
11 #include "gtk/gtksignal.h"
12 #include "gtk/gtknotebook.h"
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif /* __cplusplus */
17
18 static void gtk_myfixed_class_init (GtkMyFixedClass *klass);
19 static void gtk_myfixed_init (GtkMyFixed *myfixed);
20 static void gtk_myfixed_map (GtkWidget *widget);
21 #if (GTK_MINOR_VERSION == 0)
22 static void gtk_myfixed_unmap (GtkWidget *widget);
23 #endif
24 static void gtk_myfixed_realize (GtkWidget *widget);
25 static void gtk_myfixed_size_request (GtkWidget *widget,
26 GtkRequisition *requisition);
27 static void gtk_myfixed_size_allocate (GtkWidget *widget,
28 GtkAllocation *allocation);
29 static void gtk_myfixed_paint (GtkWidget *widget,
30 GdkRectangle *area);
31 static void gtk_myfixed_draw (GtkWidget *widget,
32 GdkRectangle *area);
33 static gint gtk_myfixed_expose (GtkWidget *widget,
34 GdkEventExpose *event);
35 static void gtk_myfixed_add (GtkContainer *container,
36 GtkWidget *widget);
37 static void gtk_myfixed_remove (GtkContainer *container,
38 GtkWidget *widget);
39 static void gtk_myfixed_foreach (GtkContainer *container,
40 #if (GTK_MINOR_VERSION > 0)
41 gboolean include_internals,
42 #endif
43 GtkCallback callback,
44 gpointer callback_data);
45 #if (GTK_MINOR_VERSION > 0)
46 static GtkType gtk_myfixed_child_type (GtkContainer *container);
47 #endif
48
49 #if (GTK_MINOR_VERSION > 0)
50 static void gtk_myfixed_scroll_set_adjustments (GtkMyFixed *myfixed,
51 GtkAdjustment *hadj,
52 GtkAdjustment *vadj);
53 #endif
54
55
56
57 static GtkContainerClass *parent_class = NULL;
58
59 guint
60 gtk_myfixed_get_type ()
61 {
62 static guint myfixed_type = 0;
63
64 if (!myfixed_type)
65 {
66 GtkTypeInfo myfixed_info =
67 {
68 "GtkMyFixed",
69 sizeof (GtkMyFixed),
70 sizeof (GtkMyFixedClass),
71 (GtkClassInitFunc) gtk_myfixed_class_init,
72 (GtkObjectInitFunc) gtk_myfixed_init,
73 #if (GTK_MINOR_VERSION > 0)
74 /* reserved_1 */ NULL,
75 /* reserved_2 */ NULL,
76 (GtkClassInitFunc) NULL,
77 #else
78 (GtkArgSetFunc) NULL,
79 (GtkArgGetFunc) NULL,
80 #endif
81 };
82
83 myfixed_type = gtk_type_unique (gtk_container_get_type (), &myfixed_info);
84 }
85
86 return myfixed_type;
87 }
88
89 static void
90 gtk_myfixed_class_init (GtkMyFixedClass *klass)
91 {
92 GtkObjectClass *object_class;
93 GtkWidgetClass *widget_class;
94 GtkContainerClass *container_class;
95
96 object_class = (GtkObjectClass*) klass;
97 widget_class = (GtkWidgetClass*) klass;
98 container_class = (GtkContainerClass*) klass;
99
100 #if (GTK_MINOR_VERSION > 0)
101 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
102 #else
103 parent_class = gtk_type_class (gtk_container_get_type ());
104 #endif
105
106 widget_class->map = gtk_myfixed_map;
107 #if (GTK_MINOR_VERSION == 0)
108 widget_class->unmap = gtk_myfixed_unmap;
109 #endif
110 widget_class->realize = gtk_myfixed_realize;
111 widget_class->size_request = gtk_myfixed_size_request;
112 widget_class->size_allocate = gtk_myfixed_size_allocate;
113 widget_class->draw = gtk_myfixed_draw;
114 widget_class->expose_event = gtk_myfixed_expose;
115
116 container_class->add = gtk_myfixed_add;
117 container_class->remove = gtk_myfixed_remove;
118 #if (GTK_MINOR_VERSION > 0)
119 container_class->forall = gtk_myfixed_foreach;
120 #else
121 container_class->foreach = gtk_myfixed_foreach;
122 #endif
123
124 #if (GTK_MINOR_VERSION > 0)
125 container_class->child_type = gtk_myfixed_child_type;
126 #endif
127
128 #if (GTK_MINOR_VERSION > 0)
129 klass->set_scroll_adjustments = gtk_myfixed_scroll_set_adjustments;
130
131 widget_class->set_scroll_adjustments_signal =
132 gtk_signal_new ("set_scroll_adjustments",
133 GTK_RUN_LAST,
134 object_class->type,
135 GTK_SIGNAL_OFFSET (GtkMyFixedClass, set_scroll_adjustments),
136 gtk_marshal_NONE__POINTER_POINTER,
137 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
138 #endif
139 }
140
141 #if (GTK_MINOR_VERSION > 0)
142 static GtkType
143 gtk_myfixed_child_type (GtkContainer *container)
144 {
145 return GTK_TYPE_WIDGET;
146 }
147 #endif
148
149 static void
150 gtk_myfixed_init (GtkMyFixed *myfixed)
151 {
152 GTK_WIDGET_UNSET_FLAGS (myfixed, GTK_NO_WINDOW);
153
154 #if (GTK_MINOR_VERSION == 0)
155 GTK_WIDGET_SET_FLAGS (myfixed, GTK_BASIC);
156 #endif
157
158 #if (GTK_MINOR_VERSION > 0)
159 myfixed->shadow_type = GTK_SHADOW_NONE;
160 #endif
161
162 myfixed->children = NULL;
163 }
164
165 GtkWidget*
166 gtk_myfixed_new ()
167 {
168 GtkMyFixed *myfixed;
169
170 myfixed = gtk_type_new (gtk_myfixed_get_type ());
171
172 return GTK_WIDGET (myfixed);
173 }
174
175 #if (GTK_MINOR_VERSION > 0)
176 void gtk_myfixed_scroll_set_adjustments (GtkMyFixed *myfixed,
177 GtkAdjustment *hadj,
178 GtkAdjustment *vadj)
179 {
180 /* OK, this is embarassing, but this function has to be here */
181 }
182
183 void
184 gtk_myfixed_set_shadow_type (GtkMyFixed *myfixed,
185 GtkShadowType type)
186 {
187 g_return_if_fail (myfixed != NULL);
188 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
189
190 if ((GtkShadowType) myfixed->shadow_type != type)
191 {
192 myfixed->shadow_type = type;
193
194 if (GTK_WIDGET_VISIBLE (myfixed))
195 {
196 gtk_widget_size_allocate (GTK_WIDGET (myfixed), &(GTK_WIDGET (myfixed)->allocation));
197 gtk_widget_queue_draw (GTK_WIDGET (myfixed));
198 }
199 }
200 }
201 #endif
202
203 void
204 gtk_myfixed_put (GtkMyFixed *myfixed,
205 GtkWidget *widget,
206 gint16 x,
207 gint16 y,
208 gint16 width,
209 gint16 height)
210 {
211 GtkMyFixedChild *child_info;
212
213 g_return_if_fail (myfixed != NULL);
214 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
215 g_return_if_fail (widget != NULL);
216
217 child_info = g_new (GtkMyFixedChild, 1);
218 child_info->widget = widget;
219 child_info->x = x;
220 child_info->y = y;
221 child_info->width = width;
222 child_info->height = height;
223
224 gtk_widget_set_parent (widget, GTK_WIDGET (myfixed));
225
226 myfixed->children = g_list_append (myfixed->children, child_info);
227
228 if (GTK_WIDGET_REALIZED (myfixed) && !GTK_WIDGET_REALIZED (widget))
229 gtk_widget_realize (widget);
230
231 if (GTK_WIDGET_MAPPED (myfixed) && !GTK_WIDGET_MAPPED (widget))
232 gtk_widget_map (widget);
233
234 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (myfixed))
235 gtk_widget_queue_resize (GTK_WIDGET (myfixed));
236 }
237
238 void
239 gtk_myfixed_move (GtkMyFixed *myfixed,
240 GtkWidget *widget,
241 gint16 x,
242 gint16 y)
243 {
244 GtkMyFixedChild *child;
245 GList *children;
246
247 g_return_if_fail (myfixed != NULL);
248 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
249 g_return_if_fail (widget != NULL);
250
251 children = myfixed->children;
252 while (children)
253 {
254 child = children->data;
255 children = children->next;
256
257 if (child->widget == widget)
258 {
259 gtk_myfixed_set_size( myfixed, widget, x, y, child->width, child->height );
260 break;
261 }
262 }
263 }
264
265 void
266 gtk_myfixed_resize (GtkMyFixed *myfixed,
267 GtkWidget *widget,
268 gint16 width,
269 gint16 height)
270 {
271 GtkMyFixedChild *child;
272 GList *children;
273
274 g_return_if_fail (myfixed != NULL);
275 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
276 g_return_if_fail (widget != NULL);
277
278 children = myfixed->children;
279 while (children)
280 {
281 child = children->data;
282 children = children->next;
283
284 if (child->widget == widget)
285 {
286 gtk_myfixed_set_size( myfixed, widget, child->x, child->y, width, height );
287 break;
288 }
289 }
290 }
291
292 void
293 gtk_myfixed_set_size (GtkMyFixed *myfixed,
294 GtkWidget *widget,
295 gint16 x,
296 gint16 y,
297 gint16 width,
298 gint16 height)
299 {
300 GtkMyFixedChild *child;
301 GList *children;
302 GtkAllocation child_allocation;
303
304 g_return_if_fail (myfixed != NULL);
305 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
306 g_return_if_fail (widget != NULL);
307
308 children = myfixed->children;
309 while (children)
310 {
311 child = children->data;
312 children = children->next;
313
314 if (child->widget == widget)
315 {
316 if ((child->x == x) &&
317 (child->y == y) &&
318 (child->width == width) &&
319 (child->height == height)) return;
320
321 child->x = x;
322 child->y = y;
323 child->width = width;
324 child->height = height;
325
326 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (myfixed))
327 {
328 if ((child->width > 1) && (child->height > 1) && (GTK_WIDGET_REALIZED(widget)))
329 {
330 child_allocation.x = child->x;
331 child_allocation.y = child->y;
332 child_allocation.width = child->width;
333 child_allocation.height = child->height;
334 gtk_widget_size_allocate (widget, &child_allocation);
335 }
336 else
337 {
338 gtk_widget_queue_resize (GTK_WIDGET (myfixed));
339 }
340 }
341
342 break;
343 }
344 }
345 }
346
347 static void
348 gtk_myfixed_map (GtkWidget *widget)
349 {
350 GtkMyFixed *myfixed;
351 GtkMyFixedChild *child;
352 GList *children;
353
354 g_return_if_fail (widget != NULL);
355 g_return_if_fail (GTK_IS_MYFIXED (widget));
356
357 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
358 myfixed = GTK_MYFIXED (widget);
359
360 gdk_window_show (widget->window);
361
362 children = myfixed->children;
363 while (children)
364 {
365 child = children->data;
366 children = children->next;
367
368 if (GTK_WIDGET_VISIBLE (child->widget) &&
369 !GTK_WIDGET_MAPPED (child->widget))
370 gtk_widget_map (child->widget);
371 }
372 }
373
374 #if (GTK_MINOR_VERSION == 0)
375 static void
376 gtk_myfixed_unmap (GtkWidget *widget)
377 {
378 g_return_if_fail (widget != NULL);
379 g_return_if_fail (GTK_IS_MYFIXED (widget));
380
381 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
382 }
383 #endif
384
385 static void
386 gtk_myfixed_realize (GtkWidget *widget)
387 {
388 GtkMyFixed *myfixed;
389 GdkWindowAttr attributes;
390 gint attributes_mask;
391
392 g_return_if_fail (widget != NULL);
393 g_return_if_fail (GTK_IS_MYFIXED (widget));
394
395 myfixed = GTK_MYFIXED (widget);
396
397 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
398
399 attributes.window_type = GDK_WINDOW_CHILD;
400
401 #if (GTK_MINOR_VERSION > 0)
402 attributes.x = widget->allocation.x;
403 attributes.y = widget->allocation.y;
404 attributes.width = widget->allocation.width;
405 attributes.height = widget->allocation.height;
406
407 if (myfixed->shadow_type != GTK_SHADOW_NONE)
408 {
409 attributes.x += 2;
410 attributes.y += 2;
411 attributes.width -= 4;
412 attributes.height -= 4;
413 }
414
415 if (attributes.width < 2) attributes.width = 2;
416 if (attributes.height < 2) attributes.height = 2;
417 #else
418 attributes.x = widget->allocation.x;
419 attributes.y = widget->allocation.y;
420 attributes.width = 32000;
421 attributes.height = 32000;
422 #endif
423 attributes.wclass = GDK_INPUT_OUTPUT;
424 attributes.visual = gtk_widget_get_visual (widget);
425 attributes.colormap = gtk_widget_get_colormap (widget);
426 attributes.event_mask = gtk_widget_get_events (widget);
427 attributes.event_mask |=
428 GDK_EXPOSURE_MASK |
429 GDK_POINTER_MOTION_MASK |
430 GDK_POINTER_MOTION_HINT_MASK |
431 GDK_BUTTON_MOTION_MASK |
432 GDK_BUTTON1_MOTION_MASK |
433 GDK_BUTTON2_MOTION_MASK |
434 GDK_BUTTON3_MOTION_MASK |
435 GDK_BUTTON_PRESS_MASK |
436 GDK_BUTTON_RELEASE_MASK |
437 GDK_KEY_PRESS_MASK |
438 GDK_KEY_RELEASE_MASK |
439 GDK_ENTER_NOTIFY_MASK |
440 GDK_LEAVE_NOTIFY_MASK |
441 GDK_FOCUS_CHANGE_MASK;
442
443 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
444
445 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes,
446 attributes_mask);
447 gdk_window_set_user_data (widget->window, widget);
448
449 widget->style = gtk_style_attach (widget->style, widget->window);
450 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
451 }
452
453 static void
454 gtk_myfixed_size_request (GtkWidget *widget,
455 GtkRequisition *requisition)
456 {
457 GtkMyFixed *myfixed;
458 GtkMyFixedChild *child;
459 GList *children;
460
461 g_return_if_fail (widget != NULL);
462 g_return_if_fail (GTK_IS_MYFIXED (widget));
463 g_return_if_fail (requisition != NULL);
464
465 myfixed = GTK_MYFIXED (widget);
466
467 /* request very little, I'm not sure if requesting nothing
468 will always have positive effects on stability... */
469 requisition->width = 2;
470 requisition->height = 2;
471
472 children = myfixed->children;
473 while (children)
474 {
475 child = children->data;
476 children = children->next;
477
478 if (GTK_WIDGET_VISIBLE (child->widget))
479 {
480 gtk_widget_size_request (child->widget, &child->widget->requisition);
481 }
482 }
483 }
484
485 static void
486 gtk_myfixed_size_allocate (GtkWidget *widget,
487 GtkAllocation *allocation)
488 {
489 GtkMyFixed *myfixed;
490 gint border;
491 GtkMyFixedChild *child;
492 GtkAllocation child_allocation;
493 GList *children;
494
495 g_return_if_fail (widget != NULL);
496 g_return_if_fail (GTK_IS_MYFIXED(widget));
497 g_return_if_fail (allocation != NULL);
498
499 myfixed = GTK_MYFIXED (widget);
500
501 widget->allocation = *allocation;
502 #if (GTK_MINOR_VERSION > 0)
503 if (myfixed->shadow_type == GTK_SHADOW_NONE)
504 border = 0;
505 else
506 border = 2;
507 #else
508 border = 0;
509 #endif
510
511 if (GTK_WIDGET_REALIZED (widget))
512 {
513 gdk_window_move_resize( widget->window,
514 allocation->x+border, allocation->y+border,
515 #if (GTK_MINOR_VERSION > 0)
516 allocation->width-border*2, allocation->height-border*2
517 #else
518 32000, 32000
519 #endif
520 );
521 }
522
523 children = myfixed->children;
524 while (children)
525 {
526 child = children->data;
527 children = children->next;
528
529 /* please look at the text in wxWindow::DoSetSize() on why the
530 test GTK_WIDGET_REALIZED() has to be here */
531 if (GTK_WIDGET_VISIBLE (child->widget) &&
532 !(!GTK_WIDGET_REALIZED(child->widget) &&
533 GTK_IS_NOTEBOOK(child->widget) ))
534 {
535 child_allocation.x = child->x;
536 child_allocation.y = child->y;
537 child_allocation.width = child->width;
538 child_allocation.height = child->height;
539 gtk_widget_size_allocate (child->widget, &child_allocation);
540 }
541 }
542 }
543
544 static void
545 gtk_myfixed_paint (GtkWidget *widget,
546 GdkRectangle *area)
547 {
548 g_return_if_fail (widget != NULL);
549 g_return_if_fail (GTK_IS_MYFIXED (widget));
550 g_return_if_fail (area != NULL);
551
552 if (GTK_WIDGET_DRAWABLE (widget))
553 gdk_window_clear_area (widget->window,
554 area->x, area->y,
555 area->width, area->height);
556 }
557
558 static void
559 gtk_myfixed_draw (GtkWidget *widget,
560 GdkRectangle *area)
561 {
562 GtkMyFixed *myfixed;
563 GtkMyFixedChild *child;
564 GdkRectangle child_area;
565 GList *children;
566
567 g_return_if_fail (widget != NULL);
568 g_return_if_fail (GTK_IS_MYFIXED (widget));
569
570 if (GTK_WIDGET_DRAWABLE (widget))
571 {
572 myfixed = GTK_MYFIXED (widget);
573 gtk_myfixed_paint (widget, area);
574
575 children = myfixed->children;
576 while (children)
577 {
578 child = children->data;
579 children = children->next;
580
581 if (gtk_widget_intersect (child->widget, area, &child_area))
582 gtk_widget_draw (child->widget, &child_area);
583 }
584 }
585 }
586
587 static gint
588 gtk_myfixed_expose (GtkWidget *widget,
589 GdkEventExpose *event)
590 {
591 GtkMyFixed *myfixed;
592 GtkMyFixedChild *child;
593 GdkEventExpose child_event;
594 GList *children;
595
596 g_return_val_if_fail (widget != NULL, FALSE);
597 g_return_val_if_fail (GTK_IS_MYFIXED (widget), FALSE);
598 g_return_val_if_fail (event != NULL, FALSE);
599
600 if (GTK_WIDGET_DRAWABLE (widget))
601 {
602 myfixed = GTK_MYFIXED (widget);
603
604 child_event = *event;
605
606 children = myfixed->children;
607 while (children)
608 {
609 child = children->data;
610 children = children->next;
611
612 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
613 gtk_widget_intersect (child->widget, &event->area,
614 &child_event.area))
615 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
616 }
617 }
618
619 return FALSE;
620 }
621
622 static void
623 gtk_myfixed_add (GtkContainer *container,
624 GtkWidget *widget)
625 {
626 g_return_if_fail (container != NULL);
627 g_return_if_fail (GTK_IS_MYFIXED (container));
628 g_return_if_fail (widget != NULL);
629
630 gtk_myfixed_put (GTK_MYFIXED (container), widget, 0, 0, 20, 20 );
631 }
632
633 static void
634 gtk_myfixed_remove (GtkContainer *container,
635 GtkWidget *widget)
636 {
637 GtkMyFixed *myfixed;
638 GtkMyFixedChild *child;
639 GList *children;
640
641 g_return_if_fail (container != NULL);
642 g_return_if_fail (GTK_IS_MYFIXED (container));
643 g_return_if_fail (widget != NULL);
644
645 myfixed = GTK_MYFIXED (container);
646
647 children = myfixed->children;
648 while (children)
649 {
650 child = children->data;
651
652 if (child->widget == widget)
653 {
654 gtk_widget_unparent (widget);
655
656 myfixed->children = g_list_remove_link (myfixed->children, children);
657 g_list_free (children);
658 g_free (child);
659
660 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
661 gtk_widget_queue_resize (GTK_WIDGET (container));
662
663 break;
664 }
665
666 children = children->next;
667 }
668 }
669
670 static void
671 gtk_myfixed_foreach (GtkContainer *container,
672 #if (GTK_MINOR_VERSION > 0)
673 gboolean include_internals,
674 #endif
675 GtkCallback callback,
676 gpointer callback_data)
677 {
678 GtkMyFixed *myfixed;
679 GtkMyFixedChild *child;
680 GList *children;
681
682 g_return_if_fail (container != NULL);
683 g_return_if_fail (GTK_IS_MYFIXED (container));
684 g_return_if_fail (callback != NULL);
685
686 myfixed = GTK_MYFIXED (container);
687
688 children = myfixed->children;
689 while (children)
690 {
691 child = children->data;
692 children = children->next;
693
694 (* callback) (child->widget, callback_data);
695 }
696 }
697
698
699 #ifdef __cplusplus
700 }
701 #endif /* __cplusplus */
702