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