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