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