]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
ada44904e66c8d8988ac494c34bbaacd81681472
[wxWidgets.git] / src / gtk / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Created: 01/02/97
6 // Id:
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 #ifdef __GNUG__
13 #pragma implementation "window.h"
14 #endif
15
16 #include "wx/defs.h"
17 #include "wx/window.h"
18 #include "wx/dc.h"
19 #include "wx/frame.h"
20 #include "wx/app.h"
21 #include "wx/layout.h"
22 #include "wx/utils.h"
23 #include "wx/dialog.h"
24 #include "wx/msgdlg.h"
25 #include "wx/dcclient.h"
26 #include "wx/dnd.h"
27 #include "wx/mdi.h"
28 #include "wx/menu.h"
29 #include "wx/notebook.h"
30 #include "wx/statusbr.h"
31 #include <wx/intl.h>
32 #include "gdk/gdkkeysyms.h"
33 #include <math.h>
34 #include "wx/gtk/win_gtk.h"
35 #include "gdk/gdkprivate.h"
36
37 //-----------------------------------------------------------------------------
38 // data
39 //-----------------------------------------------------------------------------
40
41 extern wxList wxPendingDelete;
42 extern wxList wxTopLevelWindows;
43 extern bool g_blockEventsOnDrag;
44
45 //-----------------------------------------------------------------------------
46 // "expose_event" (of m_wxwindow, not of m_widget)
47 //-----------------------------------------------------------------------------
48
49 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
50 {
51 if (!win->HasVMT()) return;
52 if (g_blockEventsOnDrag) return;
53
54 win->m_updateRegion.Union( gdk_event->area.x,
55 gdk_event->area.y,
56 gdk_event->area.width,
57 gdk_event->area.height );
58
59 if (gdk_event->count > 0) return;
60
61 wxPaintEvent event( win->GetId() );
62 event.SetEventObject( win );
63 win->GetEventHandler()->ProcessEvent( event );
64
65 win->m_updateRegion.Clear();
66 }
67
68 //-----------------------------------------------------------------------------
69 // "draw" (of m_wxwindow, not of m_widget)
70 //-----------------------------------------------------------------------------
71
72 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
73 {
74 if (!win->HasVMT()) return;
75 if (g_blockEventsOnDrag) return;
76
77 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
78
79 wxPaintEvent event( win->GetId() );
80 event.SetEventObject( win );
81 win->GetEventHandler()->ProcessEvent( event );
82
83 win->m_updateRegion.Clear();
84 }
85
86 //-----------------------------------------------------------------------------
87 // "key_press_event"
88 //-----------------------------------------------------------------------------
89
90 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
91 {
92 if (!win->HasVMT()) return FALSE;
93 if (g_blockEventsOnDrag) return FALSE;
94
95 /*
96 printf( "OnKeyPress from " );
97 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
98 printf( win->GetClassInfo()->GetClassName() );
99 printf( ".\n" );
100 */
101
102 long key_code = 0;
103 switch (gdk_event->keyval)
104 {
105 case GDK_BackSpace: key_code = WXK_BACK; break;
106 case GDK_Tab: key_code = WXK_TAB; break;
107 case GDK_Linefeed: key_code = WXK_RETURN; break;
108 case GDK_Clear: key_code = WXK_CLEAR; break;
109 case GDK_Return: key_code = WXK_RETURN; break;
110 case GDK_Pause: key_code = WXK_PAUSE; break;
111 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
112 case GDK_Escape: key_code = WXK_ESCAPE; break;
113 case GDK_Delete: key_code = WXK_DELETE; break;
114 case GDK_Home: key_code = WXK_HOME; break;
115 case GDK_Left: key_code = WXK_LEFT; break;
116 case GDK_Up: key_code = WXK_UP; break;
117 case GDK_Right: key_code = WXK_RIGHT; break;
118 case GDK_Down: key_code = WXK_DOWN; break;
119 case GDK_Prior: key_code = WXK_PRIOR; break;
120 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
121 case GDK_Next: key_code = WXK_NEXT; break;
122 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
123 case GDK_End: key_code = WXK_END; break;
124 case GDK_Begin: key_code = WXK_HOME; break;
125 case GDK_Select: key_code = WXK_SELECT; break;
126 case GDK_Print: key_code = WXK_PRINT; break;
127 case GDK_Execute: key_code = WXK_EXECUTE; break;
128 case GDK_Insert: key_code = WXK_INSERT; break;
129 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
130 case GDK_KP_Tab: key_code = WXK_TAB; break;
131 case GDK_KP_Enter: key_code = WXK_RETURN; break;
132 case GDK_KP_Home: key_code = WXK_HOME; break;
133 case GDK_KP_Left: key_code = WXK_LEFT; break;
134 case GDK_KP_Up: key_code = WXK_UP; break;
135 case GDK_KP_Right: key_code = WXK_RIGHT; break;
136 case GDK_KP_Down: key_code = WXK_DOWN; break;
137 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
138 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
139 case GDK_KP_Next: key_code = WXK_NEXT; break;
140 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
141 case GDK_KP_End: key_code = WXK_END; break;
142 case GDK_KP_Begin: key_code = WXK_HOME; break;
143 case GDK_KP_Insert: key_code = WXK_INSERT; break;
144 case GDK_KP_Delete: key_code = WXK_DELETE; break;
145 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
146 case GDK_KP_Add: key_code = WXK_ADD; break;
147 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
148 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
149 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
150 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
151 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
152 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
153 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
154 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
155 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
156 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
157 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
158 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
159 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
160 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
161 case GDK_F1: key_code = WXK_F1; break;
162 case GDK_F2: key_code = WXK_F2; break;
163 case GDK_F3: key_code = WXK_F3; break;
164 case GDK_F4: key_code = WXK_F4; break;
165 case GDK_F5: key_code = WXK_F5; break;
166 case GDK_F6: key_code = WXK_F6; break;
167 case GDK_F7: key_code = WXK_F7; break;
168 case GDK_F8: key_code = WXK_F8; break;
169 case GDK_F9: key_code = WXK_F9; break;
170 case GDK_F10: key_code = WXK_F10; break;
171 case GDK_F11: key_code = WXK_F11; break;
172 case GDK_F12: key_code = WXK_F12; break;
173 default:
174 {
175 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
176 key_code = gdk_event->keyval;
177 }
178 }
179
180 if (!key_code) return FALSE;
181
182 wxKeyEvent event( wxEVT_CHAR );
183 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
184 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
185 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
186 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
187 event.m_keyCode = key_code;
188 event.m_x = 0;
189 event.m_y = 0;
190 event.SetEventObject( win );
191
192 bool ret = win->GetEventHandler()->ProcessEvent( event );
193
194 if (ret)
195 {
196 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
197 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
198 }
199
200 return ret;
201 }
202
203 //-----------------------------------------------------------------------------
204 // "button_press_event"
205 //-----------------------------------------------------------------------------
206
207 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
208 {
209 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
210
211 if (g_blockEventsOnDrag) return TRUE;
212
213 if (win->m_wxwindow)
214 {
215 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
216 {
217 gtk_widget_grab_focus (win->m_wxwindow);
218
219 /*
220 printf( "GrabFocus from " );
221 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
222 printf( win->GetClassInfo()->GetClassName() );
223 printf( ".\n" );
224 */
225
226 }
227 }
228
229 if (!win->HasVMT()) return TRUE;
230
231 printf( "OnButtonPress from " );
232 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
233 printf( win->GetClassInfo()->GetClassName() );
234 printf( ".\n" );
235
236 wxEventType event_type = wxEVT_LEFT_DOWN;
237
238 if (gdk_event->button == 1)
239 {
240 switch (gdk_event->type)
241 {
242 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
243 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
244 default: break;
245 }
246 }
247 else if (gdk_event->button == 2)
248 {
249 switch (gdk_event->type)
250 {
251 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
252 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
253 default: break;
254 }
255 }
256 else if (gdk_event->button == 3)
257 {
258 switch (gdk_event->type)
259 {
260 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
261 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
262 default: break;
263 }
264 }
265
266 wxMouseEvent event( event_type );
267 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
268 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
269 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
270 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
271 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
272 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
273 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
274
275 event.m_x = (long)gdk_event->x;
276 event.m_y = (long)gdk_event->y;
277
278 // Some control don't have their own X window and thus cannot get
279 // any events.
280
281 wxNode *node = win->GetChildren()->First();
282 while (node)
283 {
284 wxWindow *child = (wxWindow*)node->Data();
285 if ((child->m_x <= event.m_x) &&
286 (child->m_y <= event.m_y) &&
287 (child->m_x+child->m_width >= event.m_x) &&
288 (child->m_y+child->m_height >= event.m_y))
289 {
290 win = child;
291 event.m_x -= child->m_x;
292 event.m_y -= child->m_y;
293 break;
294 }
295 node = node->Next();
296 }
297
298 event.SetEventObject( win );
299
300 if (win->GetEventHandler()->ProcessEvent( event ))
301 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
302
303 return TRUE;
304 }
305
306 //-----------------------------------------------------------------------------
307 // "button_release"
308 //-----------------------------------------------------------------------------
309
310 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
311 {
312 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
313 if (g_blockEventsOnDrag) return TRUE;
314
315 if (!win->HasVMT()) return TRUE;
316
317 /*
318 printf( "OnButtonRelease from " );
319 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
320 printf( win->GetClassInfo()->GetClassName() );
321 printf( ".\n" );
322 */
323
324 wxEventType event_type = wxEVT_NULL;
325
326 switch (gdk_event->button)
327 {
328 case 1: event_type = wxEVT_LEFT_UP; break;
329 case 2: event_type = wxEVT_MIDDLE_UP; break;
330 case 3: event_type = wxEVT_RIGHT_UP; break;
331 }
332
333 wxMouseEvent event( event_type );
334 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
335 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
336 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
337 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
338 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
339 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
340 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
341 event.m_x = (long)gdk_event->x;
342 event.m_y = (long)gdk_event->y;
343
344 // Some control don't have their own X window and thus cannot get
345 // any events.
346
347 wxNode *node = win->GetChildren()->First();
348 while (node)
349 {
350 wxWindow *child = (wxWindow*)node->Data();
351 if ((child->m_x <= event.m_x) &&
352 (child->m_y <= event.m_y) &&
353 (child->m_x+child->m_width >= event.m_x) &&
354 (child->m_y+child->m_height >= event.m_y))
355 {
356 win = child;
357 event.m_x -= child->m_x;
358 event.m_y -= child->m_y;
359 break;
360 }
361 node = node->Next();
362 }
363
364 event.SetEventObject( win );
365
366 if (win->GetEventHandler()->ProcessEvent( event ))
367 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
368
369 return TRUE;
370 }
371
372 //-----------------------------------------------------------------------------
373 // "motion_notify_event"
374 //-----------------------------------------------------------------------------
375
376 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
377 {
378 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
379 if (g_blockEventsOnDrag) return TRUE;
380
381 if (!win->HasVMT()) return TRUE;
382
383 /*
384 printf( "OnMotion from " );
385 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
386 printf( win->GetClassInfo()->GetClassName() );
387 printf( ".\n" );
388 */
389
390 wxMouseEvent event( wxEVT_MOTION );
391 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
392 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
393 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
394 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
395 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
396 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
397 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
398
399 event.m_x = (long)gdk_event->x;
400 event.m_y = (long)gdk_event->y;
401
402 // Some control don't have their own X window and thus cannot get
403 // any events.
404
405 wxNode *node = win->GetChildren()->First();
406 while (node)
407 {
408 wxWindow *child = (wxWindow*)node->Data();
409 if ((child->m_x <= event.m_x) &&
410 (child->m_y <= event.m_y) &&
411 (child->m_x+child->m_width >= event.m_x) &&
412 (child->m_y+child->m_height >= event.m_y))
413 {
414 win = child;
415 event.m_x -= child->m_x;
416 event.m_y -= child->m_y;
417 break;
418 }
419 node = node->Next();
420 }
421
422 event.SetEventObject( win );
423
424 if (win->GetEventHandler()->ProcessEvent( event ))
425 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
426
427 return TRUE;
428 }
429
430 //-----------------------------------------------------------------------------
431 // "focus_in_event"
432 //-----------------------------------------------------------------------------
433
434 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
435 {
436 if (g_blockEventsOnDrag) return TRUE;
437 if (win->m_wxwindow)
438 {
439 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
440 {
441 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
442 /*
443 printf( "SetFocus flag from " );
444 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
445 printf( win->GetClassInfo()->GetClassName() );
446 printf( ".\n" );
447 */
448 }
449 }
450
451 if (!win->HasVMT()) return TRUE;
452
453 /*
454 printf( "OnSetFocus from " );
455 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
456 printf( win->GetClassInfo()->GetClassName() );
457 printf( " " );
458 printf( WXSTRINGCAST win->GetLabel() );
459 printf( ".\n" );
460 */
461
462 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
463 event.SetEventObject( win );
464
465 if (win->GetEventHandler()->ProcessEvent( event ))
466 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
467
468 return TRUE;
469 }
470
471 //-----------------------------------------------------------------------------
472 // "focus_out_event"
473 //-----------------------------------------------------------------------------
474
475 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
476 {
477 if (g_blockEventsOnDrag) return TRUE;
478 if (win->m_wxwindow)
479 {
480 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
481 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
482 }
483
484 if (!win->HasVMT()) return TRUE;
485
486 /*
487 printf( "OnKillFocus from " );
488 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
489 printf( win->GetClassInfo()->GetClassName() );
490 printf( ".\n" );
491 */
492
493 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
494 event.SetEventObject( win );
495
496 if (win->GetEventHandler()->ProcessEvent( event ))
497 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
498
499 return TRUE;
500 }
501
502 //-----------------------------------------------------------------------------
503 // "value_changed" from m_vAdjust
504 //-----------------------------------------------------------------------------
505
506 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
507 {
508 if (g_blockEventsOnDrag) return;
509
510 /*
511 printf( "OnVScroll from " );
512 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
513 printf( win->GetClassInfo()->GetClassName() );
514 printf( ".\n" );
515 */
516
517 if (!win->HasVMT()) return;
518
519 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
520 if (fabs(diff) < 0.2) return;
521
522 wxEventType command = wxEVT_NULL;
523
524 float line_step = win->m_vAdjust->step_increment;
525 float page_step = win->m_vAdjust->page_increment;
526
527 if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
528 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
529 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
530 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
531 else command = wxEVT_SCROLL_THUMBTRACK;
532
533 int value = (int)(win->m_vAdjust->value+0.5);
534
535 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
536 event.SetEventObject( win );
537 win->GetEventHandler()->ProcessEvent( event );
538 }
539
540 //-----------------------------------------------------------------------------
541 // "value_changed" from m_hAdjust
542 //-----------------------------------------------------------------------------
543
544 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
545 {
546 if (g_blockEventsOnDrag) return;
547
548 /*
549 printf( "OnHScroll from " );
550 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
551 printf( win->GetClassInfo()->GetClassName() );
552 printf( ".\n" );
553 */
554
555 if (!win->HasVMT()) return;
556
557 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
558 if (fabs(diff) < 0.2) return;
559
560 wxEventType command = wxEVT_NULL;
561
562 float line_step = win->m_hAdjust->step_increment;
563 float page_step = win->m_hAdjust->page_increment;
564
565 if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
566 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
567 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
568 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
569 else command = wxEVT_SCROLL_THUMBTRACK;
570
571 int value = (int)(win->m_hAdjust->value+0.5);
572
573 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
574 event.SetEventObject( win );
575 win->GetEventHandler()->ProcessEvent( event );
576 }
577
578 //-----------------------------------------------------------------------------
579 // "changed" from m_vAdjust
580 //-----------------------------------------------------------------------------
581
582 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
583 {
584 if (g_blockEventsOnDrag) return;
585
586 /*
587 printf( "OnVScroll change from " );
588 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
589 printf( win->GetClassInfo()->GetClassName() );
590 printf( ".\n" );
591 */
592
593 if (!win->HasVMT()) return;
594
595 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
596 int value = (int)(win->m_vAdjust->value+0.5);
597
598 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
599 event.SetEventObject( win );
600 win->GetEventHandler()->ProcessEvent( event );
601 }
602
603 //-----------------------------------------------------------------------------
604 // "changed" from m_hAdjust
605 //-----------------------------------------------------------------------------
606
607 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
608 {
609 if (g_blockEventsOnDrag) return;
610
611 /*
612 printf( "OnHScroll change from " );
613 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
614 printf( win->GetClassInfo()->GetClassName() );
615 printf( ".\n" );
616 */
617
618 if (!win->HasVMT()) return;
619
620 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
621 int value = (int)(win->m_hAdjust->value+0.5);
622
623 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
624 event.SetEventObject( win );
625 win->GetEventHandler()->ProcessEvent( event );
626 }
627
628 //-----------------------------------------------------------------------------
629 // "drop_data_available_event"
630 //-----------------------------------------------------------------------------
631
632 static void gtk_window_drop_callback( GtkWidget *widget, GdkEvent *event, wxWindow *win )
633 {
634 if (!win->HasVMT()) return;
635
636 if (win->GetDropTarget())
637 {
638 int x = 0;
639 int y = 0;
640 gdk_window_get_pointer( widget->window, &x, &y, (GdkModifierType *) NULL );
641 win->GetDropTarget()->Drop( event, x, y );
642 }
643
644 /*
645 g_free (event->dropdataavailable.data);
646 g_free (event->dropdataavailable.data_type);
647 */
648 }
649
650 //-----------------------------------------------------------------------------
651 // "enter_notify_event"
652 //-----------------------------------------------------------------------------
653
654 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
655 {
656 if (widget->window != gdk_event->window) return TRUE;
657 if (g_blockEventsOnDrag) return TRUE;
658 if (!win->HasVMT()) return TRUE;
659
660 if (widget->window)
661 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
662
663 wxMouseEvent event( wxEVT_ENTER_WINDOW );
664 event.SetEventObject( win );
665 return win->GetEventHandler()->ProcessEvent( event );
666 }
667
668 //-----------------------------------------------------------------------------
669 // "leave_notify_event"
670 //-----------------------------------------------------------------------------
671
672 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
673 {
674 if (widget->window != gdk_event->window) return TRUE;
675 if (!win->HasVMT()) return TRUE;
676 if (g_blockEventsOnDrag) return TRUE;
677
678 if (widget->window)
679 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
680
681 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
682 event.SetEventObject( win );
683 return win->GetEventHandler()->ProcessEvent( event );
684 }
685
686 //-----------------------------------------------------------------------------
687 // wxWindow
688 //-----------------------------------------------------------------------------
689
690 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
691
692 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
693 EVT_SIZE(wxWindow::OnSize)
694 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
695 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
696 EVT_IDLE(wxWindow::OnIdle)
697 END_EVENT_TABLE()
698
699 wxWindow::wxWindow()
700 {
701 m_widget = (GtkWidget *) NULL;
702 m_wxwindow = (GtkWidget *) NULL;
703 m_parent = (wxWindow *) NULL;
704 m_children.DeleteContents( FALSE );
705 m_x = 0;
706 m_y = 0;
707 m_width = 0;
708 m_height = 0;
709 m_minWidth = -1;
710 m_minHeight = -1;
711 m_maxWidth = -1;
712 m_maxHeight = -1;
713 m_retCode = 0;
714 m_eventHandler = this;
715 m_windowValidator = (wxValidator *) NULL;
716 m_windowId = -1;
717 m_cursor = new wxCursor( wxCURSOR_ARROW );
718 m_font = *wxSWISS_FONT;
719 m_windowStyle = 0;
720 m_windowName = "noname";
721 m_constraints = (wxLayoutConstraints *) NULL;
722 m_constraintsInvolvedIn = (wxList *) NULL;
723 m_windowSizer = (wxSizer *) NULL;
724 m_sizerParent = (wxWindow *) NULL;
725 m_autoLayout = FALSE;
726 m_sizeSet = FALSE;
727 m_hasVMT = FALSE;
728 m_needParent = TRUE;
729 m_hasScrolling = FALSE;
730 m_hAdjust = (GtkAdjustment *) NULL;
731 m_vAdjust = (GtkAdjustment *) NULL;
732 m_oldHorizontalPos = 0.0;
733 m_oldVerticalPos = 0.0;
734 m_isShown = FALSE;
735 m_isEnabled = TRUE;
736 m_pDropTarget = (wxDropTarget *) NULL;
737 m_resizing = FALSE;
738 }
739
740 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
741 const wxPoint &pos, const wxSize &size,
742 long style, const wxString &name )
743 {
744 m_isShown = FALSE;
745 m_isEnabled = TRUE;
746 m_needParent = TRUE;
747
748 m_cursor = (wxCursor *) NULL;
749
750 PreCreation( parent, id, pos, size, style, name );
751
752 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
753 m_hasScrolling = TRUE;
754
755 GtkScrolledWindow *s_window;
756 s_window = GTK_SCROLLED_WINDOW(m_widget);
757
758 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
759 scroll_class->scrollbar_spacing = 0;
760
761 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
762
763 m_oldHorizontalPos = 0.0;
764 m_oldVerticalPos = 0.0;
765
766 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
767 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
768
769 gtk_signal_connect (GTK_OBJECT (m_hAdjust), "value_changed",
770 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
771 gtk_signal_connect (GTK_OBJECT (m_vAdjust), "value_changed",
772 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
773
774 gtk_signal_connect (GTK_OBJECT (m_hAdjust), "changed",
775 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
776 gtk_signal_connect (GTK_OBJECT (m_vAdjust), "changed",
777 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
778
779 GtkViewport *viewport;
780 viewport = GTK_VIEWPORT(s_window->viewport);
781
782 if (m_windowStyle & wxRAISED_BORDER)
783 {
784 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
785 }
786 else if (m_windowStyle & wxSUNKEN_BORDER)
787 {
788 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
789 }
790 else
791 {
792 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
793 }
794
795 m_wxwindow = gtk_myfixed_new();
796
797 if (m_wxwindow) GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
798
799 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
800 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
801 else
802 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
803
804 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
805
806 // shut the viewport up
807 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
808 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
809
810 // I _really_ don't want scrollbars in the beginning
811 m_vAdjust->lower = 0.0;
812 m_vAdjust->upper = 1.0;
813 m_vAdjust->value = 0.0;
814 m_vAdjust->step_increment = 1.0;
815 m_vAdjust->page_increment = 1.0;
816 m_vAdjust->page_size = 5.0;
817 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
818 m_hAdjust->lower = 0.0;
819 m_hAdjust->upper = 1.0;
820 m_hAdjust->value = 0.0;
821 m_hAdjust->step_increment = 1.0;
822 m_hAdjust->page_increment = 1.0;
823 m_hAdjust->page_size = 5.0;
824 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
825
826 gtk_widget_show( m_wxwindow );
827
828 PostCreation();
829
830 Show( TRUE );
831
832 return TRUE;
833 }
834
835 wxWindow::~wxWindow(void)
836 {
837 m_hasVMT = FALSE;
838
839 if (m_pDropTarget) delete m_pDropTarget;
840
841 if (m_parent) m_parent->RemoveChild( this );
842 if (m_widget) Show( FALSE );
843
844 DestroyChildren();
845
846 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
847
848 if (m_widget) gtk_widget_destroy( m_widget );
849
850 wxDELETE(m_cursor);
851
852 DeleteRelatedConstraints();
853 if (m_constraints)
854 {
855 // This removes any dangling pointers to this window
856 // in other windows' constraintsInvolvedIn lists.
857 UnsetConstraints(m_constraints);
858 delete m_constraints;
859 m_constraints = (wxLayoutConstraints *) NULL;
860 }
861 if (m_windowSizer)
862 {
863 delete m_windowSizer;
864 m_windowSizer = (wxSizer *) NULL;
865 }
866 // If this is a child of a sizer, remove self from parent
867 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
868
869 // Just in case the window has been Closed, but
870 // we're then deleting immediately: don't leave
871 // dangling pointers.
872 wxPendingDelete.DeleteObject(this);
873
874 // Just in case we've loaded a top-level window via
875 // wxWindow::LoadNativeDialog but we weren't a dialog
876 // class
877 wxTopLevelWindows.DeleteObject(this);
878
879 if (m_windowValidator) delete m_windowValidator;
880 }
881
882 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
883 const wxPoint &pos, const wxSize &size,
884 long style, const wxString &name )
885 {
886 if (m_needParent && (parent == NULL))
887 wxFatalError( "Need complete parent.", name );
888
889 m_widget = (GtkWidget *) NULL;
890 m_hasVMT = FALSE;
891 m_parent = parent;
892 m_children.DeleteContents( FALSE );
893 m_x = (int)pos.x;
894 m_y = (int)pos.y;
895 m_width = size.x;
896 if (m_width == -1) m_width = 20;
897 m_height = size.y;
898 if (m_height == -1) m_height = 20;
899 m_minWidth = -1;
900 m_minHeight = -1;
901 m_maxWidth = -1;
902 m_maxHeight = -1;
903 m_retCode = 0;
904 m_eventHandler = this;
905 m_windowId = id;
906 m_sizeSet = FALSE;
907 if (m_cursor == NULL)
908 m_cursor = new wxCursor( wxCURSOR_ARROW );
909 m_font = *wxSWISS_FONT;
910 m_backgroundColour = wxWHITE;
911 m_foregroundColour = wxBLACK;
912 m_windowStyle = style;
913 m_windowName = name;
914 m_constraints = (wxLayoutConstraints *) NULL;
915 m_constraintsInvolvedIn = (wxList *) NULL;
916 m_windowSizer = (wxSizer *) NULL;
917 m_sizerParent = (wxWindow *) NULL;
918 m_autoLayout = FALSE;
919 m_pDropTarget = (wxDropTarget *) NULL;
920 m_resizing = FALSE;
921 m_windowValidator = (wxValidator *) NULL;
922 }
923
924 void wxWindow::PostCreation(void)
925 {
926 if (m_parent) m_parent->AddChild( this );
927
928 // GtkStyle *style = m_widget->style;
929 // style->font = m_font.GetInternalFont( 1.0 ); // destroy old font ?
930
931 GtkWidget *connect_widget = GetConnectWidget();
932
933 if (m_wxwindow)
934 {
935 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
936 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
937
938 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
939 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
940 }
941
942 gtk_signal_connect( GTK_OBJECT(connect_widget), "key_press_event",
943 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
944
945 gtk_signal_connect( GTK_OBJECT(connect_widget), "button_press_event",
946 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
947
948 gtk_signal_connect( GTK_OBJECT(connect_widget), "button_release_event",
949 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
950
951 gtk_signal_connect( GTK_OBJECT(connect_widget), "motion_notify_event",
952 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
953
954 gtk_signal_connect( GTK_OBJECT(connect_widget), "focus_in_event",
955 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
956
957 gtk_signal_connect( GTK_OBJECT(connect_widget), "focus_out_event",
958 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
959
960 // Only for cursor handling
961
962 gtk_signal_connect( GTK_OBJECT(m_widget), "enter_notify_event",
963 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
964
965 gtk_signal_connect( GTK_OBJECT(m_widget), "leave_notify_event",
966 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
967
968 if (m_wxwindow)
969 {
970 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "enter_notify_event",
971 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
972
973 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "leave_notify_event",
974 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
975 }
976
977 if (m_widget && m_parent) gtk_widget_realize( m_widget );
978
979 if (m_wxwindow)
980 {
981 gtk_widget_realize( m_wxwindow );
982 gdk_gc_set_exposures( m_wxwindow->style->fg_gc[0], TRUE );
983 }
984
985 SetCursor( wxSTANDARD_CURSOR );
986
987 m_hasVMT = TRUE;
988 }
989
990 bool wxWindow::HasVMT(void)
991 {
992 return m_hasVMT;
993 }
994
995 bool wxWindow::Close( bool force )
996 {
997 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
998 event.SetEventObject(this);
999 event.SetForce(force);
1000
1001 return GetEventHandler()->ProcessEvent(event);
1002 }
1003
1004 bool wxWindow::Destroy(void)
1005 {
1006 m_hasVMT = FALSE;
1007 delete this;
1008 return TRUE;
1009 }
1010
1011 bool wxWindow::DestroyChildren(void)
1012 {
1013 if (GetChildren())
1014 {
1015 wxNode *node;
1016 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1017 {
1018 wxWindow *child;
1019 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1020 {
1021 delete child;
1022 if (GetChildren()->Member(child)) delete node;
1023 }
1024 }
1025 }
1026 return TRUE;
1027 }
1028
1029 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1030 {
1031 // are we to set fonts here ?
1032 }
1033
1034 void wxWindow::ImplementSetSize(void)
1035 {
1036 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1037 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1038 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1039 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1040 gtk_widget_set_usize( m_widget, m_width, m_height );
1041 }
1042
1043 void wxWindow::ImplementSetPosition(void)
1044 {
1045 if (IS_KIND_OF(this,wxFrame) || IS_KIND_OF(this,wxDialog))
1046 {
1047 if ((m_x != -1) || (m_y != -1))
1048 gtk_widget_set_uposition( m_widget, m_x, m_y );
1049 return;
1050 }
1051
1052 if (!m_parent)
1053 {
1054 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1055 return;
1056 }
1057
1058 if ((m_parent) && (m_parent->m_wxwindow))
1059 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1060
1061 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1062 }
1063
1064 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1065 {
1066 if (m_resizing) return; // I don't like recursions
1067 m_resizing = TRUE;
1068
1069 int newX = x;
1070 int newY = y;
1071 int newW = width;
1072 int newH = height;
1073
1074 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1075 {
1076 if (newX == -1) newX = m_x;
1077 if (newY == -1) newY = m_y;
1078 if (newW == -1) newW = m_width;
1079 if (newH == -1) newH = m_height;
1080 }
1081
1082 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1083 {
1084 if (newW == -1) newW = 80;
1085 }
1086
1087 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1088 {
1089 if (newH == -1) newH = 26;
1090 }
1091
1092 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1093 {
1094 m_x = newX;
1095 m_y = newY;
1096 ImplementSetPosition();
1097 }
1098 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1099 {
1100 m_width = newW;
1101 m_height = newH;
1102 ImplementSetSize();
1103 }
1104 m_sizeSet = TRUE;
1105
1106 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1107 event.SetEventObject( this );
1108 ProcessEvent( event );
1109
1110 m_resizing = FALSE;
1111 }
1112
1113 void wxWindow::SetSize( int width, int height )
1114 {
1115 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1116 }
1117
1118 void wxWindow::Move( int x, int y )
1119 {
1120 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1121 }
1122
1123 void wxWindow::GetSize( int *width, int *height ) const
1124 {
1125 if (width) (*width) = m_width;
1126 if (height) (*height) = m_height;
1127 }
1128
1129 void wxWindow::SetClientSize( int width, int height )
1130 {
1131 if (!m_wxwindow)
1132 {
1133 SetSize( width, height );
1134 }
1135 else
1136 {
1137 int dw = 0;
1138 int dh = 0;
1139
1140 if (!m_hasScrolling)
1141 {
1142 /*
1143 do we have sunken dialogs ?
1144
1145 GtkStyleClass *window_class = m_wxwindow->style->klass;
1146
1147 dw += 2 * window_class->xthickness;
1148 dh += 2 * window_class->ythickness;
1149 */
1150 }
1151 else
1152 {
1153 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1154 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1155
1156 GtkWidget *viewport = scroll_window->viewport;
1157 GtkStyleClass *viewport_class = viewport->style->klass;
1158
1159 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1160 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1161
1162 if ((m_windowStyle & wxRAISED_BORDER) ||
1163 (m_windowStyle & wxSUNKEN_BORDER))
1164 {
1165 dw += 2 * viewport_class->xthickness;
1166 dh += 2 * viewport_class->ythickness;
1167 }
1168
1169 if (GTK_WIDGET_VISIBLE(vscrollbar))
1170 {
1171 dw += vscrollbar->allocation.width;
1172 dw += scroll_class->scrollbar_spacing;
1173 }
1174
1175 if (GTK_WIDGET_VISIBLE(hscrollbar))
1176 {
1177 dh += hscrollbar->allocation.height;
1178 dw += scroll_class->scrollbar_spacing;
1179 }
1180 }
1181
1182 SetSize( width+dw, height+dh );
1183 }
1184 }
1185
1186 void wxWindow::GetClientSize( int *width, int *height ) const
1187 {
1188 if (!m_wxwindow)
1189 {
1190 if (width) (*width) = m_width;
1191 if (height) (*height) = m_height;
1192 }
1193 else
1194 {
1195 int dw = 0;
1196 int dh = 0;
1197
1198 if (!m_hasScrolling)
1199 {
1200 /*
1201 do we have sunken dialogs ?
1202
1203 GtkStyleClass *window_class = m_wxwindow->style->klass;
1204
1205 dw += 2 * window_class->xthickness;
1206 dh += 2 * window_class->ythickness;
1207 */
1208 }
1209 else
1210 {
1211 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1212 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1213
1214 GtkWidget *viewport = scroll_window->viewport;
1215 GtkStyleClass *viewport_class = viewport->style->klass;
1216
1217 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1218 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1219
1220 if ((m_windowStyle & wxRAISED_BORDER) ||
1221 (m_windowStyle & wxSUNKEN_BORDER))
1222 {
1223 dw += 2 * viewport_class->xthickness;
1224 dh += 2 * viewport_class->ythickness;
1225 }
1226
1227 if (GTK_WIDGET_VISIBLE(vscrollbar))
1228 {
1229 // dw += vscrollbar->allocation.width;
1230 dw += 15; // range.slider_width = 11 + 2*2pts edge
1231 dw += scroll_class->scrollbar_spacing;
1232 }
1233
1234 if (GTK_WIDGET_VISIBLE(hscrollbar))
1235 {
1236 // dh += hscrollbar->allocation.height;
1237 dh += 15;
1238 dh += scroll_class->scrollbar_spacing;
1239 }
1240 }
1241
1242 if (width) (*width) = m_width - dw;
1243 if (height) (*height) = m_height - dh;
1244 }
1245 }
1246
1247 void wxWindow::GetPosition( int *x, int *y ) const
1248 {
1249 if (x) (*x) = m_x;
1250 if (y) (*y) = m_y;
1251 }
1252
1253 void wxWindow::ClientToScreen( int *x, int *y )
1254 {
1255 GdkWindow *source = (GdkWindow *) NULL;
1256 if (m_wxwindow)
1257 source = m_wxwindow->window;
1258 else
1259 source = m_widget->window;
1260
1261 int org_x = 0;
1262 int org_y = 0;
1263 gdk_window_get_origin( source, &org_x, &org_y );
1264
1265 if (!m_wxwindow)
1266 {
1267 if (GTK_WIDGET_NO_WINDOW (m_widget))
1268 {
1269 org_x += m_widget->allocation.x;
1270 org_y += m_widget->allocation.y;
1271 }
1272 }
1273
1274 if (x) *x += org_x;
1275 if (y) *y += org_y;
1276 }
1277
1278 void wxWindow::ScreenToClient( int *x, int *y )
1279 {
1280 GdkWindow *source = (GdkWindow *) NULL;
1281 if (m_wxwindow)
1282 source = m_wxwindow->window;
1283 else
1284 source = m_widget->window;
1285
1286 int org_x = 0;
1287 int org_y = 0;
1288 gdk_window_get_origin( source, &org_x, &org_y );
1289
1290 if (!m_wxwindow)
1291 {
1292 if (GTK_WIDGET_NO_WINDOW (m_widget))
1293 {
1294 org_x += m_widget->allocation.x;
1295 org_y += m_widget->allocation.y;
1296 }
1297 }
1298
1299 if (x) *x -= org_x;
1300 if (y) *y -= org_y;
1301 }
1302
1303 void wxWindow::Centre( int direction )
1304 {
1305 if (IS_KIND_OF(this,wxDialog) || IS_KIND_OF(this,wxFrame))
1306 {
1307 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
1308 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
1309 ImplementSetPosition();
1310 }
1311 else
1312 {
1313 if (m_parent)
1314 {
1315 int p_w = 0;
1316 int p_h = 0;
1317 m_parent->GetSize( &p_w, &p_h );
1318 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (p_w - m_width) / 2;
1319 if (direction & wxVERTICAL == wxVERTICAL) m_y = (p_h - m_height) / 2;
1320 ImplementSetPosition();
1321 }
1322 }
1323 }
1324
1325 void wxWindow::Fit(void)
1326 {
1327 int maxX = 0;
1328 int maxY = 0;
1329 wxNode *node = GetChildren()->First();
1330 while ( node )
1331 {
1332 wxWindow *win = (wxWindow *)node->Data();
1333 int wx, wy, ww, wh;
1334 win->GetPosition(&wx, &wy);
1335 win->GetSize(&ww, &wh);
1336 if ( wx + ww > maxX )
1337 maxX = wx + ww;
1338 if ( wy + wh > maxY )
1339 maxY = wy + wh;
1340
1341 node = node->Next();
1342 }
1343 SetClientSize(maxX + 5, maxY + 10);
1344 }
1345
1346 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1347 {
1348 m_minWidth = minW;
1349 m_minHeight = minH;
1350 m_maxWidth = maxW;
1351 m_maxHeight = maxH;
1352 }
1353
1354 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1355 {
1356 //if (GetAutoLayout()) Layout();
1357 }
1358
1359 bool wxWindow::Show( bool show )
1360 {
1361 if (show)
1362 gtk_widget_show( m_widget );
1363 else
1364 gtk_widget_hide( m_widget );
1365 m_isShown = show;
1366 return TRUE;
1367 }
1368
1369 void wxWindow::Enable( bool enable )
1370 {
1371 m_isEnabled = enable;
1372 gtk_widget_set_sensitive( m_widget, enable );
1373 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1374 }
1375
1376 int wxWindow::GetCharHeight(void) const
1377 {
1378 GdkFont *font = m_font.GetInternalFont( 1.0 );
1379 return font->ascent + font->descent;
1380 }
1381
1382 int wxWindow::GetCharWidth(void) const
1383 {
1384 GdkFont *font = m_font.GetInternalFont( 1.0 );
1385 return gdk_string_width( font, "H" );
1386 }
1387
1388 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1389 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1390 {
1391 wxFont fontToUse = m_font;
1392 if (theFont) fontToUse = *theFont;
1393
1394 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1395 if (x) (*y) = gdk_string_width( font, string );
1396 if (y) (*y) = font->ascent + font->descent;
1397 if (descent) (*descent) = font->descent;
1398 if (externalLeading) (*externalLeading) = 0; // ??
1399 }
1400
1401 void wxWindow::MakeModal( bool modal )
1402 {
1403 return;
1404 // Disable all other windows
1405 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1406 {
1407 wxNode *node = wxTopLevelWindows.First();
1408 while (node)
1409 {
1410 wxWindow *win = (wxWindow *)node->Data();
1411 if (win != this)
1412 win->Enable(!modal);
1413
1414 node = node->Next();
1415 }
1416 }
1417 }
1418
1419 void wxWindow::SetFocus(void)
1420 {
1421 GtkWidget *connect_widget = GetConnectWidget();
1422 if (connect_widget)
1423 {
1424 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1425 {
1426 gtk_widget_grab_focus (connect_widget);
1427 }
1428 }
1429 }
1430
1431 bool wxWindow::OnClose(void)
1432 {
1433 return TRUE;
1434 }
1435
1436 void wxWindow::AddChild( wxWindow *child )
1437 {
1438 // Addchild is (often) called before the program
1439 // has left the parents constructor so that no
1440 // virtual tables work yet. The approach below
1441 // practically imitates virtual tables, i.e. it
1442 // implements a different AddChild() behaviour
1443 // for wxFrame, wxDialog, wxWindow and
1444 // wxMDIParentFrame.
1445
1446 // wxFrame and wxDialog as children aren't placed into the parents
1447
1448 if (( IS_KIND_OF(child,wxFrame) || IS_KIND_OF(child,wxDialog) ) &&
1449 (!IS_KIND_OF(child,wxMDIChildFrame)))
1450 {
1451 m_children.Append( child );
1452
1453 if ((child->m_x != -1) && (child->m_y != -1))
1454 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1455
1456 return;
1457 }
1458
1459 // In the case of an wxMDIChildFrame descendant, we use the
1460 // client windows's AddChild()
1461
1462 if (IS_KIND_OF(this,wxMDIParentFrame))
1463 {
1464 if (IS_KIND_OF(child,wxMDIChildFrame))
1465 {
1466 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1467 if (client)
1468 {
1469 client->AddChild( child );
1470 return;
1471 }
1472 }
1473 }
1474
1475 // wxNotebook is very special, so it has a private AddChild()
1476
1477 if (IS_KIND_OF(this,wxNotebook))
1478 {
1479 wxNotebook *tab = (wxNotebook*)this;
1480 tab->AddChild( child );
1481 return;
1482 }
1483
1484 // wxFrame has a private AddChild
1485
1486 if (IS_KIND_OF(this,wxFrame) && !IS_KIND_OF(this,wxMDIChildFrame))
1487 {
1488 wxFrame *frame = (wxFrame*)this;
1489 frame->AddChild( child );
1490 return;
1491 }
1492
1493 // All the rest
1494
1495 m_children.Append( child );
1496 if (m_wxwindow) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget,
1497 child->m_x, child->m_y );
1498
1499 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
1500 }
1501
1502 wxList *wxWindow::GetChildren(void)
1503 {
1504 return (&m_children);
1505 }
1506
1507 void wxWindow::RemoveChild( wxWindow *child )
1508 {
1509 if (GetChildren())
1510 GetChildren()->DeleteObject( child );
1511 child->m_parent = (wxWindow *) NULL;
1512 }
1513
1514 void wxWindow::SetReturnCode( int retCode )
1515 {
1516 m_retCode = retCode;
1517 }
1518
1519 int wxWindow::GetReturnCode(void)
1520 {
1521 return m_retCode;
1522 }
1523
1524 void wxWindow::Raise(void)
1525 {
1526 if (m_widget) gdk_window_raise( m_widget->window );
1527 }
1528
1529 void wxWindow::Lower(void)
1530 {
1531 if (m_widget) gdk_window_lower( m_widget->window );
1532 }
1533
1534 wxEvtHandler *wxWindow::GetEventHandler(void)
1535 {
1536 return m_eventHandler;
1537 }
1538
1539 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1540 {
1541 m_eventHandler = handler;
1542 }
1543
1544 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1545 {
1546 handler->SetNextHandler(GetEventHandler());
1547 SetEventHandler(handler);
1548 }
1549
1550 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1551 {
1552 if ( GetEventHandler() )
1553 {
1554 wxEvtHandler *handlerA = GetEventHandler();
1555 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1556 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1557 SetEventHandler(handlerB);
1558 if ( deleteHandler )
1559 {
1560 delete handlerA;
1561 return (wxEvtHandler *) NULL;
1562 }
1563 else
1564 return handlerA;
1565 }
1566 else
1567 return (wxEvtHandler *) NULL;
1568 }
1569
1570 wxValidator *wxWindow::GetValidator(void)
1571 {
1572 return m_windowValidator;
1573 }
1574
1575 void wxWindow::SetValidator( const wxValidator& validator )
1576 {
1577 if (m_windowValidator) delete m_windowValidator;
1578 m_windowValidator = validator.Clone();
1579 if (m_windowValidator) m_windowValidator->SetWindow(this);
1580 }
1581
1582 bool wxWindow::IsBeingDeleted(void)
1583 {
1584 return FALSE;
1585 }
1586
1587 void wxWindow::SetId( wxWindowID id )
1588 {
1589 m_windowId = id;
1590 }
1591
1592 wxWindowID wxWindow::GetId(void)
1593 {
1594 return m_windowId;
1595 }
1596
1597 void wxWindow::SetCursor( const wxCursor &cursor )
1598 {
1599 wxASSERT(m_cursor != NULL);
1600
1601 if (m_cursor != NULL)
1602 if (*m_cursor == cursor)
1603 return;
1604 (*m_cursor) = cursor;
1605 if (m_widget->window)
1606 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1607 if (m_wxwindow && m_wxwindow->window)
1608 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1609 }
1610
1611 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1612 {
1613 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1614 {
1615 if (rect)
1616 gdk_window_clear_area( m_wxwindow->window,
1617 rect->x,
1618 rect->y,
1619 rect->width,
1620 rect->height );
1621 else
1622 Clear();
1623 }
1624 if (!rect)
1625 {
1626 if (m_wxwindow)
1627 {
1628 int w = 0;
1629 int h = 0;
1630 GetClientSize( &w, &h );
1631
1632 GdkRectangle gdk_rect;
1633 gdk_rect.x = 0;
1634 gdk_rect.y = 0;
1635 gdk_rect.width = w;
1636 gdk_rect.height = h;
1637 gtk_widget_draw( m_wxwindow, &gdk_rect );
1638 }
1639 }
1640 else
1641 {
1642 GdkRectangle gdk_rect;
1643 gdk_rect.x = rect->x;
1644 gdk_rect.y = rect->y;
1645 gdk_rect.width = rect->width;
1646 gdk_rect.height = rect->height;
1647
1648 if (m_wxwindow)
1649 gtk_widget_draw( m_wxwindow, &gdk_rect );
1650 else
1651 gtk_widget_draw( m_widget, &gdk_rect );
1652 }
1653 }
1654
1655 bool wxWindow::IsExposed( long x, long y )
1656 {
1657 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1658 }
1659
1660 bool wxWindow::IsExposed( long x, long y, long width, long height )
1661 {
1662 return (m_updateRegion.Contains( x, y, width, height ) != wxOutRegion );
1663 }
1664
1665 void wxWindow::Clear(void)
1666 {
1667 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
1668 }
1669
1670 wxColour wxWindow::GetBackgroundColour(void) const
1671 {
1672 return m_backgroundColour;
1673 }
1674
1675 void wxWindow::SetBackgroundColour( const wxColour &colour )
1676 {
1677 m_backgroundColour = colour;
1678 if (m_wxwindow)
1679 {
1680 m_backgroundColour.CalcPixel( m_wxwindow->style->colormap );
1681 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
1682 gdk_window_clear( m_wxwindow->window );
1683 }
1684 // do something ?
1685 }
1686
1687 wxColour wxWindow::GetForegroundColour(void) const
1688 {
1689 return m_foregroundColour;
1690 }
1691
1692 void wxWindow::SetForegroundColour( const wxColour &colour )
1693 {
1694 m_foregroundColour = colour;
1695 }
1696
1697 bool wxWindow::Validate(void)
1698 {
1699 wxNode *node = GetChildren()->First();
1700 while (node)
1701 {
1702 wxWindow *child = (wxWindow *)node->Data();
1703 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
1704 { return FALSE; }
1705 node = node->Next();
1706 }
1707 return TRUE;
1708 }
1709
1710 bool wxWindow::TransferDataToWindow(void)
1711 {
1712 wxNode *node = GetChildren()->First();
1713 while (node)
1714 {
1715 wxWindow *child = (wxWindow *)node->Data();
1716 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
1717 !child->GetValidator()->TransferToWindow() )
1718 {
1719 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
1720 return FALSE;
1721 }
1722 node = node->Next();
1723 }
1724 return TRUE;
1725 }
1726
1727 bool wxWindow::TransferDataFromWindow(void)
1728 {
1729 wxNode *node = GetChildren()->First();
1730 while (node)
1731 {
1732 wxWindow *child = (wxWindow *)node->Data();
1733 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
1734 { return FALSE; }
1735 node = node->Next();
1736 }
1737 return TRUE;
1738 }
1739
1740 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1741 {
1742 TransferDataToWindow();
1743 }
1744
1745 void wxWindow::InitDialog(void)
1746 {
1747 wxInitDialogEvent event(GetId());
1748 event.SetEventObject( this );
1749 GetEventHandler()->ProcessEvent(event);
1750 }
1751
1752 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
1753 {
1754 menu->SetInvokingWindow( win );
1755 wxNode *node = menu->m_items.First();
1756 while (node)
1757 {
1758 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
1759 if (menuitem->IsSubMenu())
1760 SetInvokingWindow( menuitem->GetSubMenu(), win );
1761 node = node->Next();
1762 }
1763 }
1764
1765 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
1766 {
1767 SetInvokingWindow( menu, this );
1768 gtk_menu_popup( GTK_MENU(menu->m_menu), (GtkWidget *) NULL, (GtkWidget *) NULL, (GtkMenuPositionFunc) NULL, NULL, 0, 0 );
1769 return TRUE;
1770 }
1771
1772 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
1773 {
1774 GtkWidget *dnd_widget = GetConnectWidget();
1775
1776 if (m_pDropTarget)
1777 {
1778 gtk_signal_disconnect_by_func( GTK_OBJECT(dnd_widget),
1779 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
1780
1781 m_pDropTarget->UnregisterWidget( dnd_widget );
1782 delete m_pDropTarget;
1783 }
1784 m_pDropTarget = dropTarget;
1785 if (m_pDropTarget)
1786 {
1787 m_pDropTarget->RegisterWidget( dnd_widget );
1788
1789 gtk_signal_connect( GTK_OBJECT(dnd_widget), "drop_data_available_event",
1790 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
1791 }
1792 }
1793
1794 wxDropTarget *wxWindow::GetDropTarget() const
1795 {
1796 return m_pDropTarget;
1797 }
1798
1799 GtkWidget* wxWindow::GetConnectWidget(void)
1800 {
1801 GtkWidget *connect_widget = m_widget;
1802 if (m_wxwindow) connect_widget = m_wxwindow;
1803
1804 return connect_widget;
1805 }
1806
1807 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
1808 {
1809 if (m_wxwindow) return (window == m_wxwindow->window);
1810 return (window == m_widget->window);
1811 }
1812
1813 void wxWindow::SetFont( const wxFont &font )
1814 {
1815 m_font = font;
1816 /*
1817 create new style
1818 copy old style values to new one
1819 set font in new style
1820 -> takes to many resources
1821
1822 GtkStyle *style = gtk_style_new();
1823 ...
1824 */
1825 }
1826
1827 wxFont *wxWindow::GetFont(void)
1828 {
1829 return &m_font;
1830 }
1831
1832 void wxWindow::SetWindowStyleFlag( long flag )
1833 {
1834 m_windowStyle = flag;
1835 }
1836
1837 long wxWindow::GetWindowStyleFlag(void) const
1838 {
1839 return m_windowStyle;
1840 }
1841
1842 void wxWindow::CaptureMouse(void)
1843 {
1844 GtkWidget *connect_widget = GetConnectWidget();
1845 gtk_grab_add( connect_widget );
1846 gdk_pointer_grab ( connect_widget->window, FALSE,
1847 (GdkEventMask)
1848 (GDK_BUTTON_PRESS_MASK |
1849 GDK_BUTTON_RELEASE_MASK |
1850 GDK_POINTER_MOTION_MASK),
1851 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
1852 }
1853
1854 void wxWindow::ReleaseMouse(void)
1855 {
1856 GtkWidget *connect_widget = GetConnectWidget();
1857 gtk_grab_remove( connect_widget );
1858 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
1859 }
1860
1861 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
1862 {
1863 }
1864
1865 wxString wxWindow::GetTitle(void) const
1866 {
1867 return (wxString&)m_windowName;
1868 }
1869
1870 wxString wxWindow::GetLabel(void) const
1871 {
1872 return GetTitle();
1873 }
1874
1875 void wxWindow::SetName( const wxString &name )
1876 {
1877 m_windowName = name;
1878 }
1879
1880 wxString wxWindow::GetName(void) const
1881 {
1882 return (wxString&)m_windowName;
1883 }
1884
1885 bool wxWindow::IsShown(void) const
1886 {
1887 return m_isShown;
1888 }
1889
1890 bool wxWindow::IsRetained(void)
1891 {
1892 return FALSE;
1893 }
1894
1895 wxWindow *wxWindow::FindWindow( long id )
1896 {
1897 if (id == m_windowId) return this;
1898 wxNode *node = m_children.First();
1899 while (node)
1900 {
1901 wxWindow *child = (wxWindow*)node->Data();
1902 wxWindow *res = child->FindWindow( id );
1903 if (res) return res;
1904 node = node->Next();
1905 }
1906 return (wxWindow *) NULL;
1907 }
1908
1909 wxWindow *wxWindow::FindWindow( const wxString& name )
1910 {
1911 if (name == m_windowName) return this;
1912 wxNode *node = m_children.First();
1913 while (node)
1914 {
1915 wxWindow *child = (wxWindow*)node->Data();
1916 wxWindow *res = child->FindWindow( name );
1917 if (res) return res;
1918 node = node->Next();
1919 }
1920 return (wxWindow *) NULL;
1921 }
1922
1923 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
1924 int range, bool WXUNUSED(refresh) )
1925 {
1926 if (!m_wxwindow) return;
1927
1928 if (orient == wxHORIZONTAL)
1929 {
1930 float fpos = (float)pos;
1931 m_oldHorizontalPos = fpos;
1932 float frange = (float)range;
1933 float fthumb = (float)thumbVisible;
1934
1935 if ((fabs(fpos-m_hAdjust->value) < 0.2) &&
1936 (fabs(frange-m_hAdjust->upper) < 0.2) &&
1937 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
1938 return;
1939
1940 m_hAdjust->lower = 0.0;
1941 m_hAdjust->upper = frange;
1942 m_hAdjust->value = fpos;
1943 m_hAdjust->step_increment = 1.0;
1944 m_hAdjust->page_increment = (float)(wxMax(fthumb-2,0));
1945 m_hAdjust->page_size = fthumb;
1946 }
1947 else
1948 {
1949 float fpos = (float)pos;
1950 m_oldVerticalPos = fpos;
1951 float frange = (float)range;
1952 float fthumb = (float)thumbVisible;
1953
1954 if ((fabs(fpos-m_vAdjust->value) < 0.2) &&
1955 (fabs(frange-m_vAdjust->upper) < 0.2) &&
1956 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
1957 return;
1958
1959 m_vAdjust->lower = 0.0;
1960 m_vAdjust->upper = frange;
1961 m_vAdjust->value = fpos;
1962 m_vAdjust->step_increment = 1.0;
1963 m_vAdjust->page_increment = (float)(wxMax(fthumb-2,0));
1964 m_vAdjust->page_size = fthumb;
1965 }
1966
1967 if (m_wxwindow->window)
1968 {
1969 if (orient == wxHORIZONTAL)
1970 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1971 else
1972 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1973
1974 gtk_widget_set_usize( m_widget, m_width, m_height );
1975 }
1976 }
1977
1978 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
1979 {
1980 if (!m_wxwindow) return;
1981
1982 if (orient == wxHORIZONTAL)
1983 {
1984 float fpos = (float)pos;
1985 m_oldHorizontalPos = fpos;
1986
1987 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
1988 m_hAdjust->value = fpos;
1989 }
1990 else
1991 {
1992 float fpos = (float)pos;
1993 m_oldVerticalPos = fpos;
1994 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
1995 m_vAdjust->value = fpos;
1996 }
1997
1998 if (m_wxwindow->window)
1999 {
2000 if (orient == wxHORIZONTAL)
2001 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2002 else
2003 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2004 }
2005 }
2006
2007 int wxWindow::GetScrollThumb( int orient ) const
2008 {
2009 if (!m_wxwindow) return 0;
2010
2011 if (orient == wxHORIZONTAL)
2012 return (int)(m_hAdjust->page_size+0.5);
2013 else
2014 return (int)(m_vAdjust->page_size+0.5);
2015 }
2016
2017 int wxWindow::GetScrollPos( int orient ) const
2018 {
2019 if (!m_wxwindow) return 0;
2020
2021 if (orient == wxHORIZONTAL)
2022 return (int)(m_hAdjust->value+0.5);
2023 else
2024 return (int)(m_vAdjust->value+0.5);
2025 }
2026
2027 int wxWindow::GetScrollRange( int orient ) const
2028 {
2029 if (!m_wxwindow) return 0;
2030
2031 if (orient == wxHORIZONTAL)
2032 return (int)(m_hAdjust->upper+0.5);
2033 else
2034 return (int)(m_vAdjust->upper+0.5);
2035 }
2036
2037 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2038 {
2039 if (!m_wxwindow) return;
2040
2041 /*
2042 bool refresh = FALSE;
2043
2044 if ((m_drawingOffsetX == 0) && (m_drawingOffsetY == 0))
2045 {
2046 m_drawingOffsetX = -16000;
2047 m_drawingOffsetY = -16000;
2048 refresh = TRUE;
2049 }
2050 else
2051 {
2052 m_drawingOffsetX += dx;
2053 m_drawingOffsetY += dy;
2054 }
2055
2056 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
2057
2058 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
2059
2060 if (refresh) Refresh();
2061
2062 The code here is very nifty, but it doesn't work with
2063 overlapping windows...
2064 */
2065
2066 int cw = 0;
2067 int ch = 0;
2068 GetClientSize( &cw, &ch );
2069
2070 int w = cw - abs(dx);
2071 int h = ch - abs(dy);
2072 if ((h < 0) || (w < 0))
2073 {
2074 Refresh();
2075 return;
2076 }
2077 int s_x = 0;
2078 int s_y = 0;
2079 if (dx < 0) s_x = -dx;
2080 if (dy < 0) s_y = -dy;
2081 int d_x = 0;
2082 int d_y = 0;
2083 if (dx > 0) d_x = dx;
2084 if (dy > 0) d_y = dy;
2085 gdk_window_copy_area( m_wxwindow->window, m_wxwindow->style->fg_gc[0], d_x, d_y,
2086 m_wxwindow->window, s_x, s_y, w, h );
2087
2088 wxRect rect;
2089 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2090 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2091 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2092 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2093
2094 Refresh( TRUE, &rect );
2095 }
2096
2097 //-------------------------------------------------------------------------------------
2098 // Layout
2099 //-------------------------------------------------------------------------------------
2100
2101 wxLayoutConstraints *wxWindow::GetConstraints(void) const
2102 {
2103 return m_constraints;
2104 }
2105
2106 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2107 {
2108 if (m_constraints)
2109 {
2110 UnsetConstraints(m_constraints);
2111 delete m_constraints;
2112 }
2113 m_constraints = constraints;
2114 if (m_constraints)
2115 {
2116 // Make sure other windows know they're part of a 'meaningful relationship'
2117 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2118 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2119 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2120 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2121 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2122 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2123 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2124 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2125 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2126 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2127 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2128 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2129 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2130 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2131 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2132 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2133 }
2134 ;
2135 }
2136 ;
2137
2138 void wxWindow::SetAutoLayout( bool autoLayout )
2139 {
2140 m_autoLayout = autoLayout;
2141 }
2142
2143 bool wxWindow::GetAutoLayout(void) const
2144 {
2145 return m_autoLayout;
2146 }
2147
2148 wxSizer *wxWindow::GetSizer(void) const
2149 {
2150 return m_windowSizer;
2151 }
2152
2153 void wxWindow::SetSizerParent( wxWindow *win )
2154 {
2155 m_sizerParent = win;
2156 }
2157
2158 wxWindow *wxWindow::GetSizerParent(void) const
2159 {
2160 return m_sizerParent;
2161 }
2162
2163 // This removes any dangling pointers to this window
2164 // in other windows' constraintsInvolvedIn lists.
2165 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2166 {
2167 if (c)
2168 {
2169 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2170 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2171 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2172 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2173 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2174 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2175 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2176 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2177 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2178 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2179 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2180 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2181 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2182 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2183 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2184 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2185 }
2186 }
2187
2188 // Back-pointer to other windows we're involved with, so if we delete
2189 // this window, we must delete any constraints we're involved with.
2190 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2191 {
2192 if (!m_constraintsInvolvedIn)
2193 m_constraintsInvolvedIn = new wxList;
2194 if (!m_constraintsInvolvedIn->Member(otherWin))
2195 m_constraintsInvolvedIn->Append(otherWin);
2196 }
2197
2198 // REMOVE back-pointer to other windows we're involved with.
2199 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2200 {
2201 if (m_constraintsInvolvedIn)
2202 m_constraintsInvolvedIn->DeleteObject(otherWin);
2203 }
2204
2205 // Reset any constraints that mention this window
2206 void wxWindow::DeleteRelatedConstraints(void)
2207 {
2208 if (m_constraintsInvolvedIn)
2209 {
2210 wxNode *node = m_constraintsInvolvedIn->First();
2211 while (node)
2212 {
2213 wxWindow *win = (wxWindow *)node->Data();
2214 wxNode *next = node->Next();
2215 wxLayoutConstraints *constr = win->GetConstraints();
2216
2217 // Reset any constraints involving this window
2218 if (constr)
2219 {
2220 constr->left.ResetIfWin((wxWindow *)this);
2221 constr->top.ResetIfWin((wxWindow *)this);
2222 constr->right.ResetIfWin((wxWindow *)this);
2223 constr->bottom.ResetIfWin((wxWindow *)this);
2224 constr->width.ResetIfWin((wxWindow *)this);
2225 constr->height.ResetIfWin((wxWindow *)this);
2226 constr->centreX.ResetIfWin((wxWindow *)this);
2227 constr->centreY.ResetIfWin((wxWindow *)this);
2228 }
2229 delete node;
2230 node = next;
2231 }
2232 delete m_constraintsInvolvedIn;
2233 m_constraintsInvolvedIn = (wxList *) NULL;
2234 }
2235 }
2236
2237 void wxWindow::SetSizer(wxSizer *sizer)
2238 {
2239 m_windowSizer = sizer;
2240 if (sizer)
2241 sizer->SetSizerParent((wxWindow *)this);
2242 }
2243
2244 /*
2245 * New version
2246 */
2247
2248 bool wxWindow::Layout(void)
2249 {
2250 if (GetConstraints())
2251 {
2252 int w, h;
2253 GetClientSize(&w, &h);
2254 GetConstraints()->width.SetValue(w);
2255 GetConstraints()->height.SetValue(h);
2256 }
2257
2258 // If top level (one sizer), evaluate the sizer's constraints.
2259 if (GetSizer())
2260 {
2261 int noChanges;
2262 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2263 GetSizer()->LayoutPhase1(&noChanges);
2264 GetSizer()->LayoutPhase2(&noChanges);
2265 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2266 return TRUE;
2267 }
2268 else
2269 {
2270 // Otherwise, evaluate child constraints
2271 ResetConstraints(); // Mark all constraints as unevaluated
2272 DoPhase(1); // Just one phase need if no sizers involved
2273 DoPhase(2);
2274 SetConstraintSizes(); // Recursively set the real window sizes
2275 }
2276 return TRUE;
2277 }
2278
2279
2280 // Do a phase of evaluating constraints:
2281 // the default behaviour. wxSizers may do a similar
2282 // thing, but also impose their own 'constraints'
2283 // and order the evaluation differently.
2284 bool wxWindow::LayoutPhase1(int *noChanges)
2285 {
2286 wxLayoutConstraints *constr = GetConstraints();
2287 if (constr)
2288 {
2289 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2290 }
2291 else
2292 return TRUE;
2293 }
2294
2295 bool wxWindow::LayoutPhase2(int *noChanges)
2296 {
2297 *noChanges = 0;
2298
2299 // Layout children
2300 DoPhase(1);
2301 DoPhase(2);
2302 return TRUE;
2303 }
2304
2305 // Do a phase of evaluating child constraints
2306 bool wxWindow::DoPhase(int phase)
2307 {
2308 int noIterations = 0;
2309 int maxIterations = 500;
2310 int noChanges = 1;
2311 int noFailures = 0;
2312 wxList succeeded;
2313 while ((noChanges > 0) && (noIterations < maxIterations))
2314 {
2315 noChanges = 0;
2316 noFailures = 0;
2317 wxNode *node = GetChildren()->First();
2318 while (node)
2319 {
2320 wxWindow *child = (wxWindow *)node->Data();
2321 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2322 {
2323 wxLayoutConstraints *constr = child->GetConstraints();
2324 if (constr)
2325 {
2326 if (succeeded.Member(child))
2327 {
2328 }
2329 else
2330 {
2331 int tempNoChanges = 0;
2332 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2333 noChanges += tempNoChanges;
2334 if (success)
2335 {
2336 succeeded.Append(child);
2337 }
2338 }
2339 }
2340 }
2341 node = node->Next();
2342 }
2343 noIterations ++;
2344 }
2345 return TRUE;
2346 }
2347
2348 void wxWindow::ResetConstraints(void)
2349 {
2350 wxLayoutConstraints *constr = GetConstraints();
2351 if (constr)
2352 {
2353 constr->left.SetDone(FALSE);
2354 constr->top.SetDone(FALSE);
2355 constr->right.SetDone(FALSE);
2356 constr->bottom.SetDone(FALSE);
2357 constr->width.SetDone(FALSE);
2358 constr->height.SetDone(FALSE);
2359 constr->centreX.SetDone(FALSE);
2360 constr->centreY.SetDone(FALSE);
2361 }
2362 wxNode *node = GetChildren()->First();
2363 while (node)
2364 {
2365 wxWindow *win = (wxWindow *)node->Data();
2366 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2367 win->ResetConstraints();
2368 node = node->Next();
2369 }
2370 }
2371
2372 // Need to distinguish between setting the 'fake' size for
2373 // windows and sizers, and setting the real values.
2374 void wxWindow::SetConstraintSizes(bool recurse)
2375 {
2376 wxLayoutConstraints *constr = GetConstraints();
2377 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2378 constr->width.GetDone() && constr->height.GetDone())
2379 {
2380 int x = constr->left.GetValue();
2381 int y = constr->top.GetValue();
2382 int w = constr->width.GetValue();
2383 int h = constr->height.GetValue();
2384
2385 // If we don't want to resize this window, just move it...
2386 if ((constr->width.GetRelationship() != wxAsIs) ||
2387 (constr->height.GetRelationship() != wxAsIs))
2388 {
2389 // Calls Layout() recursively. AAAGH. How can we stop that.
2390 // Simply take Layout() out of non-top level OnSizes.
2391 SizerSetSize(x, y, w, h);
2392 }
2393 else
2394 {
2395 SizerMove(x, y);
2396 }
2397 }
2398 else if (constr)
2399 {
2400 char *windowClass = this->GetClassInfo()->GetClassName();
2401
2402 wxString winName;
2403 if (GetName() == "")
2404 winName = _("unnamed");
2405 else
2406 winName = GetName();
2407 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2408 if (!constr->left.GetDone())
2409 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2410 if (!constr->right.GetDone())
2411 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2412 if (!constr->width.GetDone())
2413 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2414 if (!constr->height.GetDone())
2415 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2416 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2417 }
2418
2419 if (recurse)
2420 {
2421 wxNode *node = GetChildren()->First();
2422 while (node)
2423 {
2424 wxWindow *win = (wxWindow *)node->Data();
2425 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2426 win->SetConstraintSizes();
2427 node = node->Next();
2428 }
2429 }
2430 }
2431
2432 // This assumes that all sizers are 'on' the same
2433 // window, i.e. the parent of this window.
2434 void wxWindow::TransformSizerToActual(int *x, int *y) const
2435 {
2436 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2437 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2438 return;
2439
2440 int xp, yp;
2441 m_sizerParent->GetPosition(&xp, &yp);
2442 m_sizerParent->TransformSizerToActual(&xp, &yp);
2443 *x += xp;
2444 *y += yp;
2445 }
2446
2447 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2448 {
2449 int xx = x;
2450 int yy = y;
2451 TransformSizerToActual(&xx, &yy);
2452 SetSize(xx, yy, w, h);
2453 }
2454
2455 void wxWindow::SizerMove(int x, int y)
2456 {
2457 int xx = x;
2458 int yy = y;
2459 TransformSizerToActual(&xx, &yy);
2460 Move(xx, yy);
2461 }
2462
2463 // Only set the size/position of the constraint (if any)
2464 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2465 {
2466 wxLayoutConstraints *constr = GetConstraints();
2467 if (constr)
2468 {
2469 if (x != -1)
2470 {
2471 constr->left.SetValue(x);
2472 constr->left.SetDone(TRUE);
2473 }
2474 if (y != -1)
2475 {
2476 constr->top.SetValue(y);
2477 constr->top.SetDone(TRUE);
2478 }
2479 if (w != -1)
2480 {
2481 constr->width.SetValue(w);
2482 constr->width.SetDone(TRUE);
2483 }
2484 if (h != -1)
2485 {
2486 constr->height.SetValue(h);
2487 constr->height.SetDone(TRUE);
2488 }
2489 }
2490 }
2491
2492 void wxWindow::MoveConstraint(int x, int y)
2493 {
2494 wxLayoutConstraints *constr = GetConstraints();
2495 if (constr)
2496 {
2497 if (x != -1)
2498 {
2499 constr->left.SetValue(x);
2500 constr->left.SetDone(TRUE);
2501 }
2502 if (y != -1)
2503 {
2504 constr->top.SetValue(y);
2505 constr->top.SetDone(TRUE);
2506 }
2507 }
2508 }
2509
2510 void wxWindow::GetSizeConstraint(int *w, int *h) const
2511 {
2512 wxLayoutConstraints *constr = GetConstraints();
2513 if (constr)
2514 {
2515 *w = constr->width.GetValue();
2516 *h = constr->height.GetValue();
2517 }
2518 else
2519 GetSize(w, h);
2520 }
2521
2522 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2523 {
2524 wxLayoutConstraints *constr = GetConstraints();
2525 if (constr)
2526 {
2527 *w = constr->width.GetValue();
2528 *h = constr->height.GetValue();
2529 }
2530 else
2531 GetClientSize(w, h);
2532 }
2533
2534 void wxWindow::GetPositionConstraint(int *x, int *y) const
2535 {
2536 wxLayoutConstraints *constr = GetConstraints();
2537 if (constr)
2538 {
2539 *x = constr->left.GetValue();
2540 *y = constr->top.GetValue();
2541 }
2542 else
2543 GetPosition(x, y);
2544 }
2545
2546 bool wxWindow::AcceptsFocus() const
2547 {
2548 return IsEnabled() && IsShown();
2549 }
2550
2551 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
2552 {
2553 UpdateWindowUI();
2554 }