]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
event/leave events
[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 wxEventType 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 wxEventType event_type = wxEVT_NULL;
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 gint gtk_window_focus_in_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxWindow *win )
418 {
419 if (g_blockEventsOnDrag) return FALSE;
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 FALSE;
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 return win->ProcessEvent( event );
448 };
449
450 //-----------------------------------------------------------------------------
451 // focus out
452
453 gint gtk_window_focus_out_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxWindow *win )
454 {
455 if (g_blockEventsOnDrag) return FALSE;
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 FALSE;
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 return 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 wxEventType command = wxEVT_NULL;
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 wxEventType command = wxEVT_NULL;
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 wxEventType 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 wxEventType 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, GdkEventCrossing *gdk_event, wxWindow *win )
652 {
653 if (widget->window != gdk_event->window) return TRUE;
654
655 if (g_blockEventsOnDrag) return FALSE;
656
657 if (widget->window)
658 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
659
660 wxMouseEvent event( wxEVT_ENTER_WINDOW );
661 event.SetEventObject( win );
662 return win->ProcessEvent( event );
663 };
664
665 //-----------------------------------------------------------------------------
666 // leave
667
668 bool gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
669 {
670 if (widget->window != gdk_event->window) return TRUE;
671
672 if (g_blockEventsOnDrag) return FALSE;
673
674 if (widget->window)
675 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
676
677 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
678 event.SetEventObject( win );
679 return win->ProcessEvent( event );
680 };
681
682 //-----------------------------------------------------------------------------
683 // wxWindow implementation
684 //-----------------------------------------------------------------------------
685
686 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
687
688 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
689 // EVT_CHAR(wxWindow::OnChar)
690 EVT_SIZE(wxWindow::OnSize)
691 // EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
692 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
693 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
694 // EVT_IDLE(wxWindow::OnIdle)
695 END_EVENT_TABLE()
696
697 wxWindow::wxWindow()
698 {
699 m_widget = NULL;
700 m_wxwindow = NULL;
701 m_parent = NULL;
702 m_children.DeleteContents( FALSE );
703 m_x = 0;
704 m_y = 0;
705 m_width = 0;
706 m_height = 0;
707 m_retCode = 0;
708 m_eventHandler = this;
709 m_windowValidator = NULL;
710 m_windowId = -1;
711 m_cursor = new wxCursor( wxCURSOR_ARROW );
712 m_font = *wxSWISS_FONT;
713 m_windowStyle = 0;
714 m_windowName = "noname";
715 m_constraints = NULL;
716 m_constraintsInvolvedIn = NULL;
717 m_windowSizer = NULL;
718 m_sizerParent = NULL;
719 m_autoLayout = FALSE;
720 m_sizeSet = FALSE;
721 m_hasVMT = FALSE;
722 m_needParent = TRUE;
723 m_hasScrolling = FALSE;
724 m_hAdjust = NULL;
725 m_vAdjust = NULL;
726 m_oldHorizontalPos = 0.0;
727 m_oldVerticalPos = 0.0;
728 m_isShown = FALSE;
729 m_isEnabled = TRUE;
730 m_drawingOffsetX = 0;
731 m_drawingOffsetY = 0;
732 m_pDropTarget = NULL;
733 };
734
735 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
736 const wxPoint &pos, const wxSize &size,
737 long style, const wxString &name )
738 {
739 Create( parent, id, pos, size, style, name );
740 };
741
742 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
743 const wxPoint &pos, const wxSize &size,
744 long style, const wxString &name )
745 {
746 m_isShown = FALSE;
747 m_isEnabled = TRUE;
748 m_needParent = TRUE;
749
750 PreCreation( parent, id, pos, size, style, name );
751
752 m_widget = gtk_scrolled_window_new( NULL, 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_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
798 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
799 else
800 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
801
802 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
803
804 // shut the viewport up
805 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
806 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
807
808 // I _really_ don't want scrollbars in the beginning
809 m_vAdjust->lower = 0.0;
810 m_vAdjust->upper = 1.0;
811 m_vAdjust->value = 0.0;
812 m_vAdjust->step_increment = 1.0;
813 m_vAdjust->page_increment = 1.0;
814 m_vAdjust->page_size = 5.0;
815 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
816 m_hAdjust->lower = 0.0;
817 m_hAdjust->upper = 1.0;
818 m_hAdjust->value = 0.0;
819 m_hAdjust->step_increment = 1.0;
820 m_hAdjust->page_increment = 1.0;
821 m_hAdjust->page_size = 5.0;
822 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
823
824 gtk_widget_show( m_wxwindow );
825
826 PostCreation();
827
828 Show( TRUE );
829
830 return TRUE;
831 };
832
833 wxWindow::~wxWindow(void)
834 {
835 m_hasVMT = FALSE;
836
837 if (m_pDropTarget) delete m_pDropTarget;
838
839 if (m_parent) m_parent->RemoveChild( this );
840 if (m_widget) Show( FALSE );
841
842 DestroyChildren();
843
844 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
845
846 if (m_widget) gtk_widget_destroy( m_widget );
847
848 // delete m_cursor;
849
850 DeleteRelatedConstraints();
851 if (m_constraints)
852 {
853 // This removes any dangling pointers to this window
854 // in other windows' constraintsInvolvedIn lists.
855 UnsetConstraints(m_constraints);
856 delete m_constraints;
857 m_constraints = NULL;
858 }
859 if (m_windowSizer)
860 {
861 delete m_windowSizer;
862 m_windowSizer = NULL;
863 }
864 // If this is a child of a sizer, remove self from parent
865 if (m_sizerParent)
866 m_sizerParent->RemoveChild((wxWindow *)this);
867
868 // Just in case the window has been Closed, but
869 // we're then deleting immediately: don't leave
870 // dangling pointers.
871 wxPendingDelete.DeleteObject(this);
872
873 // Just in case we've loaded a top-level window via
874 // wxWindow::LoadNativeDialog but we weren't a dialog
875 // class
876 wxTopLevelWindows.DeleteObject(this);
877
878 };
879
880 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
881 const wxPoint &pos, const wxSize &size,
882 long style, const wxString &name )
883 {
884 if (m_needParent && (parent == NULL))
885 wxFatalError( "Need complete parent.", name );
886
887 m_widget = NULL;
888 m_hasVMT = FALSE;
889 m_parent = parent;
890 m_children.DeleteContents( FALSE );
891 m_x = (int)pos.x;
892 m_y = (int)pos.y;
893 m_width = size.x;
894 if (m_width == -1) m_width = 20;
895 m_height = size.y;
896 if (m_height == -1) m_height = 20;
897 m_retCode = 0;
898 m_eventHandler = this;
899 m_windowValidator = NULL;
900 m_windowId = id;
901 m_sizeSet = FALSE;
902 m_cursor = new wxCursor( wxCURSOR_ARROW );
903 m_font = *wxSWISS_FONT;
904 m_backgroundColour = wxWHITE;
905 m_foregroundColour = wxBLACK;
906 m_windowStyle = style;
907 m_windowName = name;
908 m_constraints = NULL;
909 m_constraintsInvolvedIn = NULL;
910 m_windowSizer = NULL;
911 m_sizerParent = NULL;
912 m_autoLayout = FALSE;
913 m_drawingOffsetX = 0;
914 m_drawingOffsetY = 0;
915 m_pDropTarget = NULL;
916 }
917
918 void wxWindow::PostCreation(void)
919 {
920 if (m_parent) m_parent->AddChild( this );
921
922 // GtkStyle *style = m_widget->style;
923 // style->font = m_font.GetInternalFont( 1.0 ); // destroy old font ?
924
925 GtkWidget *connect_widget = m_widget;
926 if (m_wxwindow) connect_widget = m_wxwindow;
927
928 gtk_object_set_data (GTK_OBJECT (connect_widget), "MyWxWindow", (gpointer)this );
929
930 if (m_wxwindow)
931 {
932 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
933 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
934
935 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
936 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
937 };
938
939 /*
940 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
941 GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
942 */
943
944 gtk_signal_connect( GTK_OBJECT(connect_widget), "key_press_event",
945 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
946
947 gtk_signal_connect( GTK_OBJECT(connect_widget), "button_press_event",
948 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
949
950 gtk_signal_connect( GTK_OBJECT(connect_widget), "button_release_event",
951 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
952
953 gtk_signal_connect( GTK_OBJECT(connect_widget), "motion_notify_event",
954 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
955
956 gtk_signal_connect( GTK_OBJECT(connect_widget), "focus_in_event",
957 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
958
959 gtk_signal_connect( GTK_OBJECT(connect_widget), "focus_out_event",
960 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
961
962 gtk_signal_connect( GTK_OBJECT(connect_widget), "drop_data_available_event",
963 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
964
965 // Only for cursor handling
966
967 gtk_signal_connect( GTK_OBJECT(m_widget), "enter_notify_event",
968 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
969
970 gtk_signal_connect( GTK_OBJECT(m_widget), "leave_notify_event",
971 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
972
973 if (m_wxwindow)
974 {
975 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "enter_notify_event",
976 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
977
978 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "leave_notify_event",
979 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
980 };
981
982 /*
983 // Does destroy ever get called ?
984
985 gtk_signal_connect( GTK_OBJECT(m_widget), "destroy_event",
986 GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this );
987
988 if (m_wxwindow)
989 {
990 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "destroy_event",
991 GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this );
992 };
993 */
994
995 if (m_widget && m_parent) gtk_widget_realize( m_widget );
996 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
997
998 SetCursor( wxSTANDARD_CURSOR );
999
1000 m_hasVMT = TRUE;
1001 };
1002
1003 bool wxWindow::HasVMT(void)
1004 {
1005 return m_hasVMT;
1006 };
1007
1008 bool wxWindow::Close( bool force )
1009 {
1010 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1011 event.SetEventObject(this);
1012 event.SetForce(force);
1013
1014 return GetEventHandler()->ProcessEvent(event);
1015 };
1016
1017 bool wxWindow::Destroy(void)
1018 {
1019 m_hasVMT = FALSE;
1020 delete this;
1021 return TRUE;
1022 };
1023
1024 bool wxWindow::DestroyChildren(void)
1025 {
1026 if (GetChildren())
1027 {
1028 wxNode *node;
1029 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1030 {
1031 wxWindow *child;
1032 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1033 {
1034 delete child;
1035 if (GetChildren()->Member(child)) delete node;
1036 };
1037 };
1038 };
1039 return TRUE;
1040 };
1041
1042 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1043 {
1044 // are we to set fonts here ?
1045 };
1046
1047 void wxWindow::ImplementSetSize(void)
1048 {
1049 gtk_widget_set_usize( m_widget, m_width, m_height );
1050 };
1051
1052 void wxWindow::ImplementSetPosition(void)
1053 {
1054 if ((m_parent) && (m_parent->m_wxwindow))
1055 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1056 else
1057 gtk_widget_set_uposition( m_widget, m_x, m_y );
1058 };
1059
1060 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1061 {
1062 int newX = x;
1063 int newY = y;
1064 int newW = width;
1065 int newH = height;
1066
1067 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1068 {
1069 if (newX == -1) newX = m_x;
1070 if (newY == -1) newY = m_y;
1071 if (newW == -1) newW = m_width;
1072 if (newH == -1) newH = m_height;
1073 };
1074
1075 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1076 {
1077 if (newW == -1) newW = 80;
1078 };
1079
1080 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1081 {
1082 if (newH == -1) newH = 26;
1083 };
1084
1085 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1086 {
1087 m_x = newX;
1088 m_y = newY;
1089 ImplementSetPosition();
1090 };
1091 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1092 {
1093 m_width = newW;
1094 m_height = newH;
1095 ImplementSetSize();
1096 };
1097 m_sizeSet = TRUE;
1098
1099 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1100 event.SetEventObject( this );
1101 ProcessEvent( event );
1102 };
1103
1104 void wxWindow::SetSize( int width, int height )
1105 {
1106 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1107 };
1108
1109 void wxWindow::Move( int x, int y )
1110 {
1111 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1112 };
1113
1114 void wxWindow::GetSize( int *width, int *height ) const
1115 {
1116 (*width) = m_width;
1117 (*height) = m_height;
1118 };
1119
1120 void wxWindow::SetClientSize( int width, int height )
1121 {
1122 if (!m_wxwindow)
1123 {
1124 SetSize( width, height );
1125 }
1126 else
1127 {
1128 int dw = 0;
1129 int dh = 0;
1130
1131 if (!m_hasScrolling)
1132 {
1133 /*
1134 do we have sunken dialogs ?
1135
1136 GtkStyleClass *window_class = m_wxwindow->style->klass;
1137
1138 dw += 2 * window_class->xthickness;
1139 dh += 2 * window_class->ythickness;
1140 */
1141 }
1142 else
1143 {
1144 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1145 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1146
1147 GtkWidget *viewport = scroll_window->viewport;
1148 GtkStyleClass *viewport_class = viewport->style->klass;
1149
1150 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1151 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1152
1153 if ((m_windowStyle & wxRAISED_BORDER) ||
1154 (m_windowStyle & wxSUNKEN_BORDER)
1155 )
1156 {
1157 dw += 2 * viewport_class->xthickness;
1158 dh += 2 * viewport_class->ythickness;
1159 };
1160
1161 if (GTK_WIDGET_VISIBLE(vscrollbar))
1162 {
1163 dw += vscrollbar->allocation.width;
1164 dw += scroll_class->scrollbar_spacing;
1165 };
1166
1167 if (GTK_WIDGET_VISIBLE(hscrollbar))
1168 {
1169 dh += hscrollbar->allocation.height;
1170 dw += scroll_class->scrollbar_spacing;
1171 };
1172 };
1173
1174 SetSize( width+dw, height+dh );
1175 };
1176 };
1177
1178 void wxWindow::GetClientSize( int *width, int *height ) const
1179 {
1180 if (!m_wxwindow)
1181 {
1182 if (width) (*width) = m_width;
1183 if (height) (*height) = m_height;
1184 }
1185 else
1186 {
1187 int dw = 0;
1188 int dh = 0;
1189
1190 if (!m_hasScrolling)
1191 {
1192 /*
1193 do we have sunken dialogs ?
1194
1195 GtkStyleClass *window_class = m_wxwindow->style->klass;
1196
1197 dw += 2 * window_class->xthickness;
1198 dh += 2 * window_class->ythickness;
1199 */
1200 }
1201 else
1202 {
1203 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1204 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1205
1206 GtkWidget *viewport = scroll_window->viewport;
1207 GtkStyleClass *viewport_class = viewport->style->klass;
1208
1209 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1210 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1211
1212 if ((m_windowStyle & wxRAISED_BORDER) ||
1213 (m_windowStyle & wxSUNKEN_BORDER)
1214 )
1215 {
1216 dw += 2 * viewport_class->xthickness;
1217 dh += 2 * viewport_class->ythickness;
1218 };
1219
1220 if (GTK_WIDGET_VISIBLE(vscrollbar))
1221 {
1222 // dw += vscrollbar->allocation.width;
1223 dw += 15; // range.slider_width = 11 + 2*2pts edge
1224 dw += scroll_class->scrollbar_spacing;
1225 };
1226
1227 if (GTK_WIDGET_VISIBLE(hscrollbar))
1228 {
1229 // dh += hscrollbar->allocation.height;
1230 dh += 15;
1231 dh += scroll_class->scrollbar_spacing;
1232 };
1233 };
1234
1235 if (width) (*width) = m_width - dw;
1236 if (height) (*height) = m_height - dh;
1237 };
1238 };
1239
1240 void wxWindow::GetPosition( int *x, int *y ) const
1241 {
1242 if (x) (*x) = m_x;
1243 if (y) (*y) = m_y;
1244 };
1245
1246 void wxWindow::ClientToScreen( int *x, int *y )
1247 {
1248 // Does this look simple ?
1249
1250 GdkWindow *source = NULL;
1251 if (m_wxwindow)
1252 source = m_wxwindow->window;
1253 else
1254 source = m_widget->window;
1255
1256 int org_x = 0;
1257 int org_y = 0;
1258 gdk_window_get_origin( source, &org_x, &org_y );
1259
1260 if (!m_wxwindow)
1261 {
1262 if (GTK_WIDGET_NO_WINDOW (m_widget))
1263 {
1264 org_x += m_widget->allocation.x;
1265 org_y += m_widget->allocation.y;
1266 };
1267 };
1268
1269 if (x) *x += org_x;
1270 if (y) *y += org_y;
1271 };
1272
1273 void wxWindow::ScreenToClient( int *x, int *y )
1274 {
1275 GdkWindow *source = NULL;
1276 if (m_wxwindow)
1277 source = m_wxwindow->window;
1278 else
1279 source = m_widget->window;
1280
1281 int org_x = 0;
1282 int org_y = 0;
1283 gdk_window_get_origin( source, &org_x, &org_y );
1284
1285 if (!m_wxwindow)
1286 {
1287 if (GTK_WIDGET_NO_WINDOW (m_widget))
1288 {
1289 org_x += m_widget->allocation.x;
1290 org_y += m_widget->allocation.y;
1291 };
1292 };
1293
1294 if (x) *x -= org_x;
1295 if (y) *y -= org_y;
1296 };
1297
1298 void wxWindow::Centre( int direction )
1299 {
1300 int x = 0;
1301 int y = 0;
1302 GetPosition( &x, &y );
1303 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1304 {
1305 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
1306 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
1307 gtk_widget_set_uposition( m_widget, x, y );
1308 }
1309 else
1310 {
1311 if (m_parent)
1312 {
1313 int p_w = 0;
1314 int p_h = 0;
1315 m_parent->GetSize( &p_w, &p_h );
1316 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
1317 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
1318 gtk_widget_set_uposition( m_widget, x, y );
1319 };
1320 }
1321 };
1322
1323 void wxWindow::Fit(void)
1324 {
1325 int maxX = 0;
1326 int maxY = 0;
1327 wxNode *node = GetChildren()->First();
1328 while ( node )
1329 {
1330 wxWindow *win = (wxWindow *)node->Data();
1331 int wx, wy, ww, wh;
1332 win->GetPosition(&wx, &wy);
1333 win->GetSize(&ww, &wh);
1334 if ( wx + ww > maxX )
1335 maxX = wx + ww;
1336 if ( wy + wh > maxY )
1337 maxY = wy + wh;
1338
1339 node = node->Next();
1340 }
1341 SetClientSize(maxX + 5, maxY + 5);
1342 };
1343
1344 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1345 {
1346 //if (GetAutoLayout()) Layout();
1347 };
1348
1349 bool wxWindow::Show( bool show )
1350 {
1351 if (show)
1352 gtk_widget_show( m_widget );
1353 else
1354 gtk_widget_hide( m_widget );
1355 m_isShown = show;
1356 return TRUE;
1357 };
1358
1359 void wxWindow::Enable( bool enable )
1360 {
1361 m_isEnabled = enable;
1362 gtk_widget_set_sensitive( m_widget, enable );
1363 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1364 };
1365
1366 void wxWindow::MakeModal( bool modal )
1367 {
1368 return;
1369 // Disable all other windows
1370 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1371 {
1372 wxNode *node = wxTopLevelWindows.First();
1373 while (node)
1374 {
1375 wxWindow *win = (wxWindow *)node->Data();
1376 if (win != this)
1377 win->Enable(!modal);
1378
1379 node = node->Next();
1380 }
1381 }
1382 }
1383
1384 void wxWindow::SetFocus(void)
1385 {
1386 GtkWidget *connect_widget = m_widget;
1387 if (m_wxwindow) connect_widget = m_wxwindow;
1388 if (connect_widget)
1389 {
1390 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1391 {
1392 gtk_widget_grab_focus (connect_widget);
1393 };
1394 };
1395 };
1396
1397 bool wxWindow::OnClose(void)
1398 {
1399 printf( "OnClose event.\n" );
1400 return TRUE;
1401 };
1402
1403 void wxWindow::AddChild( wxWindow *child )
1404 {
1405 // Addchild is (often) called before the program
1406 // has left the parents constructor so that no
1407 // virtual tables work yet. The approach below
1408 // practically imitates virtual tables, i.e. it
1409 // implements a different AddChild() behaviour
1410 // for wxFrame, wxDialog, wxWindow and
1411 // wxMDIParentFrame.
1412
1413 if (IsKindOf(CLASSINFO(wxMDIParentFrame)))
1414 {
1415 if (child->IsKindOf(CLASSINFO(wxMDIChildFrame)))
1416 {
1417 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1418 if (client)
1419 {
1420 client->AddChild( child );
1421 return;
1422 };
1423 };
1424 };
1425
1426 if (IsKindOf(CLASSINFO(wxNotebook)))
1427 {
1428 wxNotebook *tab = (wxNotebook*)this;
1429 tab->AddChild( child );
1430 return;
1431 };
1432
1433 m_children.Append( child );
1434 if (child->IsKindOf(CLASSINFO(wxFrame)) || child->IsKindOf(CLASSINFO(wxDialog)))
1435 {
1436 if ((child->m_x != -1) && (child->m_y != -1))
1437 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1438 }
1439 else
1440 {
1441 if (m_wxwindow)
1442 gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget, child->m_x, child->m_y );
1443 };
1444 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
1445 };
1446
1447 wxList *wxWindow::GetChildren(void)
1448 {
1449 return (&m_children);
1450 };
1451
1452 void wxWindow::RemoveChild( wxWindow *child )
1453 {
1454 if (GetChildren())
1455 GetChildren()->DeleteObject( child );
1456 child->m_parent = NULL;
1457 };
1458
1459 void wxWindow::SetReturnCode( int retCode )
1460 {
1461 m_retCode = retCode;
1462 };
1463
1464 int wxWindow::GetReturnCode(void)
1465 {
1466 return m_retCode;
1467 };
1468
1469 wxWindow *wxWindow::GetParent(void)
1470 {
1471 return m_parent;
1472 };
1473
1474 wxEvtHandler *wxWindow::GetEventHandler(void)
1475 {
1476 return m_eventHandler;
1477 };
1478
1479 void wxWindow::SetEventhandler( wxEvtHandler *handler )
1480 {
1481 m_eventHandler = handler;
1482 };
1483
1484 wxValidator *wxWindow::GetValidator(void)
1485 {
1486 return m_windowValidator;
1487 };
1488
1489 void wxWindow::SetValidator( wxValidator *validator )
1490 {
1491 m_windowValidator = validator;
1492 };
1493
1494 bool wxWindow::IsBeingDeleted(void)
1495 {
1496 return FALSE;
1497 };
1498
1499 void wxWindow::SetId( wxWindowID id )
1500 {
1501 m_windowId = id;
1502 };
1503
1504 wxWindowID wxWindow::GetId(void)
1505 {
1506 return m_windowId;
1507 };
1508
1509 void wxWindow::SetCursor( const wxCursor &cursor )
1510 {
1511 if (*m_cursor == cursor) return;
1512 (*m_cursor) = cursor;
1513 if (m_widget->window)
1514 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1515 if (m_wxwindow && m_wxwindow->window)
1516 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1517 };
1518
1519 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1520 {
1521 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1522 {
1523 if (rect)
1524 gdk_window_clear_area( m_wxwindow->window,
1525 rect->x,
1526 rect->y,
1527 rect->width,
1528 rect->height );
1529 else
1530 Clear();
1531 };
1532 if (!rect)
1533 {
1534 if (m_wxwindow)
1535 {
1536 wxClientDC dc(this);
1537 PrepareDC(dc);
1538 long x = 0;
1539 long y = 0;
1540 dc.GetInternalDeviceOrigin( &x, &y );
1541
1542 int w = 0;
1543 int h = 0;
1544 GetClientSize( &w, &h );
1545
1546 GdkRectangle gdk_rect;
1547 gdk_rect.x = x;
1548 gdk_rect.y = y;
1549 gdk_rect.width = w;
1550 gdk_rect.height = h;
1551 gtk_widget_draw( m_wxwindow, &gdk_rect );
1552 };
1553 }
1554 else
1555 {
1556 GdkRectangle gdk_rect;
1557 gdk_rect.x = rect->x;
1558 gdk_rect.y = rect->y;
1559 gdk_rect.width = rect->width;
1560 gdk_rect.height = rect->height;
1561 if (m_wxwindow)
1562 gtk_widget_draw( m_wxwindow, &gdk_rect );
1563 else
1564 gtk_widget_draw( m_widget, &gdk_rect );
1565 };
1566 };
1567
1568 bool wxWindow::IsExposed( long x, long y )
1569 {
1570 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1571 };
1572
1573 bool wxWindow::IsExposed( long x, long y, long width, long height )
1574 {
1575 return (m_updateRegion.Contains( x, y, width, height ) != wxOutRegion );
1576 };
1577
1578 void wxWindow::Clear(void)
1579 {
1580 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
1581 };
1582
1583 wxColour wxWindow::GetBackgroundColour(void) const
1584 {
1585 return m_backgroundColour;
1586 };
1587
1588 void wxWindow::SetBackgroundColour( const wxColour &colour )
1589 {
1590 m_backgroundColour = colour;
1591 if (m_wxwindow)
1592 {
1593 m_backgroundColour.CalcPixel( m_wxwindow->style->colormap );
1594 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
1595 gdk_window_clear( m_wxwindow->window );
1596 };
1597 // do something ?
1598 };
1599
1600 bool wxWindow::Validate(void)
1601 {
1602 wxNode *node = GetChildren()->First();
1603 while (node)
1604 {
1605 wxWindow *child = (wxWindow *)node->Data();
1606 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
1607 { return FALSE; }
1608 node = node->Next();
1609 };
1610 return TRUE;
1611 };
1612
1613 bool wxWindow::TransferDataToWindow(void)
1614 {
1615 wxNode *node = GetChildren()->First();
1616 while (node)
1617 {
1618 wxWindow *child = (wxWindow *)node->Data();
1619 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
1620 !child->GetValidator()->TransferToWindow() )
1621 {
1622 wxMessageBox( "Application Error", "Could not transfer data to window", wxOK|wxICON_EXCLAMATION );
1623 return FALSE;
1624 };
1625 node = node->Next();
1626 };
1627 return TRUE;
1628 };
1629
1630 bool wxWindow::TransferDataFromWindow(void)
1631 {
1632 wxNode *node = GetChildren()->First();
1633 while (node)
1634 {
1635 wxWindow *child = (wxWindow *)node->Data();
1636 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
1637 { return FALSE; }
1638 node = node->Next();
1639 }
1640 return TRUE;
1641 };
1642
1643 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1644 {
1645 TransferDataToWindow();
1646 };
1647
1648 void wxWindow::InitDialog(void)
1649 {
1650 wxInitDialogEvent event(GetId());
1651 event.SetEventObject( this );
1652 GetEventHandler()->ProcessEvent(event);
1653 };
1654
1655 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
1656 {
1657 GtkWidget *connect_widget = m_widget;
1658 if (m_wxwindow) connect_widget = m_wxwindow;
1659 if (m_pDropTarget)
1660 {
1661 m_pDropTarget->UnregisterWidget( connect_widget );
1662 delete m_pDropTarget;
1663 };
1664 m_pDropTarget = dropTarget;
1665 if (m_pDropTarget)
1666 {
1667 m_pDropTarget->RegisterWidget( connect_widget );
1668 };
1669 };
1670
1671 wxDropTarget *wxWindow::GetDropTarget() const
1672 {
1673 return m_pDropTarget;
1674 };
1675
1676 void wxWindow::SetFont( const wxFont &font )
1677 {
1678 m_font = font;
1679 /*
1680 create new style
1681 copy old style values to new one
1682 set font in new style
1683 -> takes to many resources
1684
1685 GtkStyle *style = gtk_style_new();
1686 ...
1687 */
1688 };
1689
1690 wxFont *wxWindow::GetFont(void)
1691 {
1692 return &m_font;
1693 };
1694
1695 void wxWindow::SetWindowStyleFlag( long flag )
1696 {
1697 m_windowStyle = flag;
1698 };
1699
1700 long wxWindow::GetWindowStyleFlag(void) const
1701 {
1702 return m_windowStyle;
1703 };
1704
1705 void wxWindow::CaptureMouse(void)
1706 {
1707 GtkWidget *connect_widget = m_widget;
1708 if (m_wxwindow) connect_widget = m_wxwindow;
1709 gtk_grab_add( connect_widget );
1710 gdk_pointer_grab ( connect_widget->window, FALSE,
1711 (GdkEventMask)
1712 (GDK_BUTTON_PRESS_MASK |
1713 GDK_BUTTON_RELEASE_MASK |
1714 GDK_POINTER_MOTION_MASK),
1715 NULL, NULL, GDK_CURRENT_TIME );
1716 };
1717
1718 void wxWindow::ReleaseMouse(void)
1719 {
1720 GtkWidget *connect_widget = m_widget;
1721 if (m_wxwindow) connect_widget = m_wxwindow;
1722 gtk_grab_remove( connect_widget );
1723 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
1724 };
1725
1726 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
1727 {
1728 };
1729
1730 wxString wxWindow::GetTitle(void) const
1731 {
1732 return (wxString&)m_windowName;
1733 };
1734
1735 wxString wxWindow::GetLabel(void) const
1736 {
1737 return GetTitle();
1738 };
1739
1740 void wxWindow::SetName( const wxString &name )
1741 {
1742 m_windowName = name;
1743 };
1744
1745 wxString wxWindow::GetName(void) const
1746 {
1747 return (wxString&)m_windowName;
1748 };
1749
1750 bool wxWindow::IsShown(void) const
1751 {
1752 return m_isShown;
1753 };
1754
1755 bool wxWindow::IsRetained(void)
1756 {
1757 return FALSE;
1758 };
1759
1760 wxWindow *wxWindow::FindWindow( long id )
1761 {
1762 if (id == m_windowId) return this;
1763 wxNode *node = m_children.First();
1764 while (node)
1765 {
1766 wxWindow *child = (wxWindow*)node->Data();
1767 wxWindow *res = child->FindWindow( id );
1768 if (res) return res;
1769 node = node->Next();
1770 };
1771 return NULL;
1772 };
1773
1774 wxWindow *wxWindow::FindWindow( const wxString& name )
1775 {
1776 if (name == m_windowName) return this;
1777 wxNode *node = m_children.First();
1778 while (node)
1779 {
1780 wxWindow *child = (wxWindow*)node->Data();
1781 wxWindow *res = child->FindWindow( name );
1782 if (res) return res;
1783 node = node->Next();
1784 };
1785 return NULL;
1786 };
1787
1788 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
1789 int range, bool WXUNUSED(refresh) )
1790 {
1791 if (!m_wxwindow) return;
1792
1793 if (orient == wxHORIZONTAL)
1794 {
1795 float fpos = (float)pos;
1796 m_oldHorizontalPos = fpos;
1797 float frange = (float)range;
1798 float fthumb = (float)thumbVisible;
1799
1800 if ((fabs(fpos-m_hAdjust->value) < 0.2) &&
1801 (fabs(frange-m_hAdjust->upper) < 0.2) &&
1802 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
1803 return;
1804
1805 m_hAdjust->lower = 0.0;
1806 m_hAdjust->upper = frange;
1807 m_hAdjust->value = fpos;
1808 m_hAdjust->step_increment = 1.0;
1809 m_hAdjust->page_increment = (float)(wxMax(fthumb-2,0));
1810 m_hAdjust->page_size = fthumb;
1811 }
1812 else
1813 {
1814 float fpos = (float)pos;
1815 m_oldVerticalPos = fpos;
1816 float frange = (float)range;
1817 float fthumb = (float)thumbVisible;
1818
1819 if ((fabs(fpos-m_vAdjust->value) < 0.2) &&
1820 (fabs(frange-m_vAdjust->upper) < 0.2) &&
1821 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
1822 return;
1823
1824 m_vAdjust->lower = 0.0;
1825 m_vAdjust->upper = frange;
1826 m_vAdjust->value = fpos;
1827 m_vAdjust->step_increment = 1.0;
1828 m_vAdjust->page_increment = (float)(wxMax(fthumb-2,0));
1829 m_vAdjust->page_size = fthumb;
1830 };
1831
1832 if (m_wxwindow->window)
1833 {
1834 if (orient == wxHORIZONTAL)
1835 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1836 else
1837 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1838
1839 gtk_widget_set_usize( m_widget, m_width, m_height );
1840 };
1841 };
1842
1843 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
1844 {
1845 if (!m_wxwindow) return;
1846
1847 if (orient == wxHORIZONTAL)
1848 {
1849 float fpos = (float)pos;
1850 m_oldHorizontalPos = fpos;
1851
1852 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
1853 m_hAdjust->value = fpos;
1854 }
1855 else
1856 {
1857 float fpos = (float)pos;
1858 m_oldVerticalPos = fpos;
1859 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
1860 m_vAdjust->value = fpos;
1861 };
1862
1863 if (m_wxwindow->window)
1864 {
1865 if (orient == wxHORIZONTAL)
1866 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
1867 else
1868 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
1869 };
1870 };
1871
1872 int wxWindow::GetScrollThumb( int orient ) const
1873 {
1874 if (!m_wxwindow) return 0;
1875
1876 if (orient == wxHORIZONTAL)
1877 return (int)(m_hAdjust->page_size+0.5);
1878 else
1879 return (int)(m_vAdjust->page_size+0.5);
1880 };
1881
1882 int wxWindow::GetScrollPos( int orient ) const
1883 {
1884 if (!m_wxwindow) return 0;
1885
1886 if (orient == wxHORIZONTAL)
1887 return (int)(m_hAdjust->value+0.5);
1888 else
1889 return (int)(m_vAdjust->value+0.5);
1890 };
1891
1892 int wxWindow::GetScrollRange( int orient ) const
1893 {
1894 if (!m_wxwindow) return 0;
1895
1896 if (orient == wxHORIZONTAL)
1897 return (int)(m_hAdjust->upper+0.5);
1898 else
1899 return (int)(m_vAdjust->upper+0.5);
1900 };
1901
1902 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
1903 {
1904 if (!m_wxwindow) return;
1905
1906 m_drawingOffsetX += dx;
1907 m_drawingOffsetY += dy;
1908
1909 // printf( "X: %d Y: %d \n", (int)m_drawingOffsetX, (int)m_drawingOffsetY );
1910
1911 gtk_myfixed_set_offset( GTK_MYFIXED(m_wxwindow), m_drawingOffsetX, m_drawingOffsetY );
1912
1913 /*
1914 The code here is very nifty, but it doesn't work with
1915 overlapping windows...
1916
1917 int cw = 0;
1918 int ch = 0;
1919 GetClientSize( &cw, &ch );
1920
1921 int w = cw - abs(dx);
1922 int h = ch - abs(dy);
1923 if ((h < 0) || (w < 0))
1924 {
1925 Refresh();
1926 return;
1927 };
1928 int s_x = 0;
1929 int s_y = 0;
1930 if (dx < 0) s_x = -dx;
1931 if (dy < 0) s_y = -dy;
1932 int d_x = 0;
1933 int d_y = 0;
1934 if (dx > 0) d_x = dx;
1935 if (dy > 0) d_y = dy;
1936 gdk_window_copy_area( m_wxwindow->window, m_wxwindow->style->fg_gc[0], d_x, d_y,
1937 m_wxwindow->window, s_x, s_y, w, h );
1938
1939 wxRect rect;
1940 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
1941 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
1942 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
1943 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
1944
1945 Refresh( TRUE, &rect );
1946 */
1947 };
1948
1949 void wxWindow::GetDrawingOffset( long *x, long *y )
1950 {
1951 if (x) *x = m_drawingOffsetX;
1952 if (y) *y = m_drawingOffsetY;
1953 };
1954
1955 //-------------------------------------------------------------------------------------
1956 // Layout
1957 //-------------------------------------------------------------------------------------
1958
1959 wxLayoutConstraints *wxWindow::GetConstraints(void) const
1960 {
1961 return m_constraints;
1962 };
1963
1964 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
1965 {
1966 if (m_constraints)
1967 {
1968 UnsetConstraints(m_constraints);
1969 delete m_constraints;
1970 }
1971 m_constraints = constraints;
1972 if (m_constraints)
1973 {
1974 // Make sure other windows know they're part of a 'meaningful relationship'
1975 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
1976 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1977 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
1978 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1979 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
1980 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1981 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
1982 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1983 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
1984 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1985 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
1986 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1987 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
1988 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1989 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
1990 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
1991 }
1992 ;
1993 }
1994 ;
1995
1996 void wxWindow::SetAutoLayout( bool autoLayout )
1997 {
1998 m_autoLayout = autoLayout;
1999 };
2000
2001 bool wxWindow::GetAutoLayout(void) const
2002 {
2003 return m_autoLayout;
2004 };
2005
2006 wxSizer *wxWindow::GetSizer(void) const
2007 {
2008 return m_windowSizer;
2009 };
2010
2011 void wxWindow::SetSizerParent( wxWindow *win )
2012 {
2013 m_sizerParent = win;
2014 };
2015
2016 wxWindow *wxWindow::GetSizerParent(void) const
2017 {
2018 return m_sizerParent;
2019 };
2020
2021 // This removes any dangling pointers to this window
2022 // in other windows' constraintsInvolvedIn lists.
2023 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2024 {
2025 if (c)
2026 {
2027 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2028 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2029 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2030 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2031 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2032 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2033 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2034 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2035 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2036 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2037 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2038 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2039 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2040 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2041 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2042 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2043 }
2044 }
2045
2046 // Back-pointer to other windows we're involved with, so if we delete
2047 // this window, we must delete any constraints we're involved with.
2048 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2049 {
2050 if (!m_constraintsInvolvedIn)
2051 m_constraintsInvolvedIn = new wxList;
2052 if (!m_constraintsInvolvedIn->Member(otherWin))
2053 m_constraintsInvolvedIn->Append(otherWin);
2054 }
2055
2056 // REMOVE back-pointer to other windows we're involved with.
2057 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2058 {
2059 if (m_constraintsInvolvedIn)
2060 m_constraintsInvolvedIn->DeleteObject(otherWin);
2061 }
2062
2063 // Reset any constraints that mention this window
2064 void wxWindow::DeleteRelatedConstraints(void)
2065 {
2066 if (m_constraintsInvolvedIn)
2067 {
2068 wxNode *node = m_constraintsInvolvedIn->First();
2069 while (node)
2070 {
2071 wxWindow *win = (wxWindow *)node->Data();
2072 wxNode *next = node->Next();
2073 wxLayoutConstraints *constr = win->GetConstraints();
2074
2075 // Reset any constraints involving this window
2076 if (constr)
2077 {
2078 constr->left.ResetIfWin((wxWindow *)this);
2079 constr->top.ResetIfWin((wxWindow *)this);
2080 constr->right.ResetIfWin((wxWindow *)this);
2081 constr->bottom.ResetIfWin((wxWindow *)this);
2082 constr->width.ResetIfWin((wxWindow *)this);
2083 constr->height.ResetIfWin((wxWindow *)this);
2084 constr->centreX.ResetIfWin((wxWindow *)this);
2085 constr->centreY.ResetIfWin((wxWindow *)this);
2086 }
2087 delete node;
2088 node = next;
2089 }
2090 delete m_constraintsInvolvedIn;
2091 m_constraintsInvolvedIn = NULL;
2092 }
2093 }
2094
2095 void wxWindow::SetSizer(wxSizer *sizer)
2096 {
2097 m_windowSizer = sizer;
2098 if (sizer)
2099 sizer->SetSizerParent((wxWindow *)this);
2100 }
2101
2102 /*
2103 * New version
2104 */
2105
2106 bool wxWindow::Layout(void)
2107 {
2108 if (GetConstraints())
2109 {
2110 int w, h;
2111 GetClientSize(&w, &h);
2112 GetConstraints()->width.SetValue(w);
2113 GetConstraints()->height.SetValue(h);
2114 }
2115
2116 // If top level (one sizer), evaluate the sizer's constraints.
2117 if (GetSizer())
2118 {
2119 int noChanges;
2120 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2121 GetSizer()->LayoutPhase1(&noChanges);
2122 GetSizer()->LayoutPhase2(&noChanges);
2123 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2124 return TRUE;
2125 }
2126 else
2127 {
2128 // Otherwise, evaluate child constraints
2129 ResetConstraints(); // Mark all constraints as unevaluated
2130 DoPhase(1); // Just one phase need if no sizers involved
2131 DoPhase(2);
2132 SetConstraintSizes(); // Recursively set the real window sizes
2133 }
2134 return TRUE;
2135 }
2136
2137
2138 // Do a phase of evaluating constraints:
2139 // the default behaviour. wxSizers may do a similar
2140 // thing, but also impose their own 'constraints'
2141 // and order the evaluation differently.
2142 bool wxWindow::LayoutPhase1(int *noChanges)
2143 {
2144 wxLayoutConstraints *constr = GetConstraints();
2145 if (constr)
2146 {
2147 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2148 }
2149 else
2150 return TRUE;
2151 }
2152
2153 bool wxWindow::LayoutPhase2(int *noChanges)
2154 {
2155 *noChanges = 0;
2156
2157 // Layout children
2158 DoPhase(1);
2159 DoPhase(2);
2160 return TRUE;
2161 }
2162
2163 // Do a phase of evaluating child constraints
2164 bool wxWindow::DoPhase(int phase)
2165 {
2166 int noIterations = 0;
2167 int maxIterations = 500;
2168 int noChanges = 1;
2169 int noFailures = 0;
2170 wxList succeeded;
2171 while ((noChanges > 0) && (noIterations < maxIterations))
2172 {
2173 noChanges = 0;
2174 noFailures = 0;
2175 wxNode *node = GetChildren()->First();
2176 while (node)
2177 {
2178 wxWindow *child = (wxWindow *)node->Data();
2179 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2180 {
2181 wxLayoutConstraints *constr = child->GetConstraints();
2182 if (constr)
2183 {
2184 if (succeeded.Member(child))
2185 {
2186 }
2187 else
2188 {
2189 int tempNoChanges = 0;
2190 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2191 noChanges += tempNoChanges;
2192 if (success)
2193 {
2194 succeeded.Append(child);
2195 }
2196 }
2197 }
2198 }
2199 node = node->Next();
2200 }
2201 noIterations ++;
2202 }
2203 return TRUE;
2204 }
2205
2206 void wxWindow::ResetConstraints(void)
2207 {
2208 wxLayoutConstraints *constr = GetConstraints();
2209 if (constr)
2210 {
2211 constr->left.SetDone(FALSE);
2212 constr->top.SetDone(FALSE);
2213 constr->right.SetDone(FALSE);
2214 constr->bottom.SetDone(FALSE);
2215 constr->width.SetDone(FALSE);
2216 constr->height.SetDone(FALSE);
2217 constr->centreX.SetDone(FALSE);
2218 constr->centreY.SetDone(FALSE);
2219 }
2220 wxNode *node = GetChildren()->First();
2221 while (node)
2222 {
2223 wxWindow *win = (wxWindow *)node->Data();
2224 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2225 win->ResetConstraints();
2226 node = node->Next();
2227 }
2228 }
2229
2230 // Need to distinguish between setting the 'fake' size for
2231 // windows and sizers, and setting the real values.
2232 void wxWindow::SetConstraintSizes(bool recurse)
2233 {
2234 wxLayoutConstraints *constr = GetConstraints();
2235 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2236 constr->width.GetDone() && constr->height.GetDone())
2237 {
2238 int x = constr->left.GetValue();
2239 int y = constr->top.GetValue();
2240 int w = constr->width.GetValue();
2241 int h = constr->height.GetValue();
2242
2243 // If we don't want to resize this window, just move it...
2244 if ((constr->width.GetRelationship() != wxAsIs) ||
2245 (constr->height.GetRelationship() != wxAsIs))
2246 {
2247 // Calls Layout() recursively. AAAGH. How can we stop that.
2248 // Simply take Layout() out of non-top level OnSizes.
2249 SizerSetSize(x, y, w, h);
2250 }
2251 else
2252 {
2253 SizerMove(x, y);
2254 }
2255 }
2256 else if (constr)
2257 {
2258 char *windowClass = this->GetClassInfo()->GetClassName();
2259
2260 wxString winName;
2261 if (GetName() == "")
2262 winName = "unnamed";
2263 else
2264 winName = GetName();
2265 wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName);
2266 if (!constr->left.GetDone())
2267 wxDebugMsg(" unsatisfied 'left' constraint.\n");
2268 if (!constr->right.GetDone())
2269 wxDebugMsg(" unsatisfied 'right' constraint.\n");
2270 if (!constr->width.GetDone())
2271 wxDebugMsg(" unsatisfied 'width' constraint.\n");
2272 if (!constr->height.GetDone())
2273 wxDebugMsg(" unsatisfied 'height' constraint.\n");
2274 wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n");
2275 }
2276
2277 if (recurse)
2278 {
2279 wxNode *node = GetChildren()->First();
2280 while (node)
2281 {
2282 wxWindow *win = (wxWindow *)node->Data();
2283 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2284 win->SetConstraintSizes();
2285 node = node->Next();
2286 }
2287 }
2288 }
2289
2290 // This assumes that all sizers are 'on' the same
2291 // window, i.e. the parent of this window.
2292 void wxWindow::TransformSizerToActual(int *x, int *y) const
2293 {
2294 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2295 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2296 return;
2297
2298 int xp, yp;
2299 m_sizerParent->GetPosition(&xp, &yp);
2300 m_sizerParent->TransformSizerToActual(&xp, &yp);
2301 *x += xp;
2302 *y += yp;
2303 }
2304
2305 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2306 {
2307 int xx = x;
2308 int yy = y;
2309 TransformSizerToActual(&xx, &yy);
2310 SetSize(xx, yy, w, h);
2311 }
2312
2313 void wxWindow::SizerMove(int x, int y)
2314 {
2315 int xx = x;
2316 int yy = y;
2317 TransformSizerToActual(&xx, &yy);
2318 Move(xx, yy);
2319 }
2320
2321 // Only set the size/position of the constraint (if any)
2322 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2323 {
2324 wxLayoutConstraints *constr = GetConstraints();
2325 if (constr)
2326 {
2327 if (x != -1)
2328 {
2329 constr->left.SetValue(x);
2330 constr->left.SetDone(TRUE);
2331 }
2332 if (y != -1)
2333 {
2334 constr->top.SetValue(y);
2335 constr->top.SetDone(TRUE);
2336 }
2337 if (w != -1)
2338 {
2339 constr->width.SetValue(w);
2340 constr->width.SetDone(TRUE);
2341 }
2342 if (h != -1)
2343 {
2344 constr->height.SetValue(h);
2345 constr->height.SetDone(TRUE);
2346 }
2347 }
2348 }
2349
2350 void wxWindow::MoveConstraint(int x, int y)
2351 {
2352 wxLayoutConstraints *constr = GetConstraints();
2353 if (constr)
2354 {
2355 if (x != -1)
2356 {
2357 constr->left.SetValue(x);
2358 constr->left.SetDone(TRUE);
2359 }
2360 if (y != -1)
2361 {
2362 constr->top.SetValue(y);
2363 constr->top.SetDone(TRUE);
2364 }
2365 }
2366 }
2367
2368 void wxWindow::GetSizeConstraint(int *w, int *h) const
2369 {
2370 wxLayoutConstraints *constr = GetConstraints();
2371 if (constr)
2372 {
2373 *w = constr->width.GetValue();
2374 *h = constr->height.GetValue();
2375 }
2376 else
2377 GetSize(w, h);
2378 }
2379
2380 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2381 {
2382 wxLayoutConstraints *constr = GetConstraints();
2383 if (constr)
2384 {
2385 *w = constr->width.GetValue();
2386 *h = constr->height.GetValue();
2387 }
2388 else
2389 GetClientSize(w, h);
2390 }
2391
2392 void wxWindow::GetPositionConstraint(int *x, int *y) const
2393 {
2394 wxLayoutConstraints *constr = GetConstraints();
2395 if (constr)
2396 {
2397 *x = constr->left.GetValue();
2398 *y = constr->top.GetValue();
2399 }
2400 else
2401 GetPosition(x, y);
2402 }
2403
2404 bool wxWindow::AcceptsFocus() const
2405 {
2406 return IsEnabled() && IsShown();
2407 }