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