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