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