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