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