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