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