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