]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/window.cpp
no message
[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 m_scrollGC = (GdkGC*) NULL;
917 }
918
919 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
920 const wxPoint &pos, const wxSize &size,
921 long style, const wxString &name )
922 {
923 m_isShown = FALSE;
924 m_isEnabled = TRUE;
925 m_needParent = TRUE;
926
927 m_cursor = (wxCursor *) NULL;
928
929 PreCreation( parent, id, pos, size, style, name );
930
931 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
932 m_hasScrolling = TRUE;
933
934 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
935
936 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
937 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
938
939 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
940 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
941
942 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
943 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
944
945 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
946 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
947
948 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
949 scroll_class->scrollbar_spacing = 0;
950
951 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
952
953 m_oldHorizontalPos = 0.0;
954 m_oldVerticalPos = 0.0;
955
956 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
957 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
958
959 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
960 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
961 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
962 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
963
964 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
965 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
966 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
967 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
968
969 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
970
971 if (m_windowStyle & wxRAISED_BORDER)
972 {
973 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
974 }
975 else if (m_windowStyle & wxSUNKEN_BORDER)
976 {
977 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
978 }
979 else
980 {
981 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
982 }
983
984 m_wxwindow = gtk_myfixed_new();
985
986 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
987
988 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
989 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
990 else
991 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
992
993 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
994
995 // shut the viewport up
996 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
997 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
998
999 // I _really_ don't want scrollbars in the beginning
1000 m_vAdjust->lower = 0.0;
1001 m_vAdjust->upper = 1.0;
1002 m_vAdjust->value = 0.0;
1003 m_vAdjust->step_increment = 1.0;
1004 m_vAdjust->page_increment = 1.0;
1005 m_vAdjust->page_size = 5.0;
1006 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1007 m_hAdjust->lower = 0.0;
1008 m_hAdjust->upper = 1.0;
1009 m_hAdjust->value = 0.0;
1010 m_hAdjust->step_increment = 1.0;
1011 m_hAdjust->page_increment = 1.0;
1012 m_hAdjust->page_size = 5.0;
1013 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1014
1015 gtk_widget_show( m_wxwindow );
1016
1017 PostCreation();
1018
1019 Show( TRUE );
1020
1021 return TRUE;
1022 }
1023
1024 wxWindow::~wxWindow()
1025 {
1026 m_hasVMT = FALSE;
1027
1028 if (m_pDropTarget) delete m_pDropTarget;
1029
1030 if (m_parent) m_parent->RemoveChild( this );
1031 if (m_widget) Show( FALSE );
1032
1033 DestroyChildren();
1034
1035 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1036
1037 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1038
1039 if (m_widget) gtk_widget_destroy( m_widget );
1040
1041 wxDELETE(m_cursor);
1042
1043 DeleteRelatedConstraints();
1044 if (m_constraints)
1045 {
1046 // This removes any dangling pointers to this window
1047 // in other windows' constraintsInvolvedIn lists.
1048 UnsetConstraints(m_constraints);
1049 delete m_constraints;
1050 m_constraints = (wxLayoutConstraints *) NULL;
1051 }
1052 if (m_windowSizer)
1053 {
1054 delete m_windowSizer;
1055 m_windowSizer = (wxSizer *) NULL;
1056 }
1057 // If this is a child of a sizer, remove self from parent
1058 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1059
1060 // Just in case the window has been Closed, but
1061 // we're then deleting immediately: don't leave
1062 // dangling pointers.
1063 wxPendingDelete.DeleteObject(this);
1064
1065 // Just in case we've loaded a top-level window via
1066 // wxWindow::LoadNativeDialog but we weren't a dialog
1067 // class
1068 wxTopLevelWindows.DeleteObject(this);
1069
1070 if (m_windowValidator) delete m_windowValidator;
1071 }
1072
1073 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1074 const wxPoint &pos, const wxSize &size,
1075 long style, const wxString &name )
1076 {
1077 if (m_needParent && (parent == NULL))
1078 wxFatalError( "Need complete parent.", name );
1079
1080 m_widget = (GtkWidget *) NULL;
1081 m_hasVMT = FALSE;
1082 m_parent = parent;
1083 m_children.DeleteContents( FALSE );
1084 m_x = (int)pos.x;
1085 m_y = (int)pos.y;
1086 m_width = size.x;
1087 if (m_width == -1) m_width = 20;
1088 m_height = size.y;
1089 if (m_height == -1) m_height = 20;
1090 m_minWidth = -1;
1091 m_minHeight = -1;
1092 m_maxWidth = -1;
1093 m_maxHeight = -1;
1094 m_retCode = 0;
1095 m_eventHandler = this;
1096 m_windowId = id;
1097 m_sizeSet = FALSE;
1098 if (m_cursor == NULL)
1099 m_cursor = new wxCursor( wxCURSOR_ARROW );
1100 m_font = *wxSWISS_FONT;
1101 // m_backgroundColour = wxWHITE;
1102 m_foregroundColour = wxBLACK;
1103 m_windowStyle = style;
1104 m_windowName = name;
1105 m_constraints = (wxLayoutConstraints *) NULL;
1106 m_constraintsInvolvedIn = (wxList *) NULL;
1107 m_windowSizer = (wxSizer *) NULL;
1108 m_sizerParent = (wxWindow *) NULL;
1109 m_autoLayout = FALSE;
1110 m_hasScrolling = FALSE;
1111 m_isScrolling = FALSE;
1112 m_pDropTarget = (wxDropTarget *) NULL;
1113 m_resizing = FALSE;
1114 m_windowValidator = (wxValidator *) NULL;
1115 m_hasOwnStyle = FALSE;
1116 }
1117
1118 void wxWindow::PostCreation()
1119 {
1120 if (m_parent) m_parent->AddChild( this );
1121
1122 if (m_wxwindow)
1123 {
1124 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1125 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1126
1127 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1128 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1129 }
1130
1131 ConnectWidget( GetConnectWidget() );
1132
1133 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1134
1135 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1136
1137 SetCursor( *wxSTANDARD_CURSOR );
1138
1139 m_hasVMT = TRUE;
1140 }
1141
1142 void wxWindow::ConnectWidget( GtkWidget *widget )
1143 {
1144 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1145 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1146
1147 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1148 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1149
1150 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1151 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1152
1153 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1154 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1155
1156 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1157 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1158
1159 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1160 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1161
1162 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1163 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1164
1165 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1166 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1167 }
1168
1169 bool wxWindow::HasVMT()
1170 {
1171 return m_hasVMT;
1172 }
1173
1174 bool wxWindow::Close( bool force )
1175 {
1176 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1177
1178 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1179 event.SetEventObject(this);
1180 event.SetForce(force);
1181
1182 return GetEventHandler()->ProcessEvent(event);
1183 }
1184
1185 bool wxWindow::Destroy()
1186 {
1187 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1188
1189 m_hasVMT = FALSE;
1190 delete this;
1191 return TRUE;
1192 }
1193
1194 bool wxWindow::DestroyChildren()
1195 {
1196 if (GetChildren())
1197 {
1198 wxNode *node;
1199 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1200 {
1201 wxWindow *child;
1202 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1203 {
1204 delete child;
1205 if (GetChildren()->Member(child)) delete node;
1206 }
1207 }
1208 }
1209 return TRUE;
1210 }
1211
1212 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1213 {
1214 // are we to set fonts here ?
1215 }
1216
1217 void wxWindow::ImplementSetSize()
1218 {
1219 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1220 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1221 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1222 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1223 gtk_widget_set_usize( m_widget, m_width, m_height );
1224 }
1225
1226 void wxWindow::ImplementSetPosition()
1227 {
1228 if (IS_KIND_OF(this,wxFrame) || IS_KIND_OF(this,wxDialog))
1229 {
1230 if ((m_x != -1) || (m_y != -1))
1231 gtk_widget_set_uposition( m_widget, m_x, m_y );
1232 return;
1233 }
1234
1235 if (!m_parent)
1236 {
1237 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1238 return;
1239 }
1240
1241 if ((m_parent) && (m_parent->m_wxwindow))
1242 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1243
1244 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1245 }
1246
1247 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1248 {
1249 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1250
1251 if (m_resizing) return; // I don't like recursions
1252 m_resizing = TRUE;
1253
1254 int newX = x;
1255 int newY = y;
1256 int newW = width;
1257 int newH = height;
1258
1259 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1260 {
1261 if (newX == -1) newX = m_x;
1262 if (newY == -1) newY = m_y;
1263 if (newW == -1) newW = m_width;
1264 if (newH == -1) newH = m_height;
1265 }
1266
1267 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1268 {
1269 if (newW == -1) newW = 80;
1270 }
1271
1272 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1273 {
1274 if (newH == -1) newH = 26;
1275 }
1276
1277 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1278 {
1279 m_x = newX;
1280 m_y = newY;
1281 ImplementSetPosition();
1282 }
1283 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1284 {
1285 m_width = newW;
1286 m_height = newH;
1287 ImplementSetSize();
1288 }
1289 m_sizeSet = TRUE;
1290
1291 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1292 event.SetEventObject( this );
1293 ProcessEvent( event );
1294
1295 m_resizing = FALSE;
1296 }
1297
1298 void wxWindow::SetSize( int width, int height )
1299 {
1300 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1301 }
1302
1303 void wxWindow::Move( int x, int y )
1304 {
1305 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1306 }
1307
1308 void wxWindow::GetSize( int *width, int *height ) const
1309 {
1310 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1311
1312 if (width) (*width) = m_width;
1313 if (height) (*height) = m_height;
1314 }
1315
1316 void wxWindow::SetClientSize( int width, int height )
1317 {
1318 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1319
1320 if (!m_wxwindow)
1321 {
1322 SetSize( width, height );
1323 }
1324 else
1325 {
1326 int dw = 0;
1327 int dh = 0;
1328
1329 if (!m_hasScrolling)
1330 {
1331 /*
1332 do we have sunken dialogs ?
1333
1334 GtkStyleClass *window_class = m_wxwindow->style->klass;
1335
1336 dw += 2 * window_class->xthickness;
1337 dh += 2 * window_class->ythickness;
1338 */
1339 }
1340 else
1341 {
1342 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1343 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1344
1345 GtkWidget *viewport = scroll_window->viewport;
1346 GtkStyleClass *viewport_class = viewport->style->klass;
1347
1348 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1349 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1350
1351 if ((m_windowStyle & wxRAISED_BORDER) ||
1352 (m_windowStyle & wxSUNKEN_BORDER))
1353 {
1354 dw += 2 * viewport_class->xthickness;
1355 dh += 2 * viewport_class->ythickness;
1356 }
1357
1358 if (GTK_WIDGET_VISIBLE(vscrollbar))
1359 {
1360 dw += vscrollbar->allocation.width;
1361 dw += scroll_class->scrollbar_spacing;
1362 }
1363
1364 if (GTK_WIDGET_VISIBLE(hscrollbar))
1365 {
1366 dh += hscrollbar->allocation.height;
1367 dw += scroll_class->scrollbar_spacing;
1368 }
1369 }
1370
1371 SetSize( width+dw, height+dh );
1372 }
1373 }
1374
1375 void wxWindow::GetClientSize( int *width, int *height ) const
1376 {
1377 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1378
1379 if (!m_wxwindow)
1380 {
1381 if (width) (*width) = m_width;
1382 if (height) (*height) = m_height;
1383 }
1384 else
1385 {
1386 int dw = 0;
1387 int dh = 0;
1388
1389 if (!m_hasScrolling)
1390 {
1391 /*
1392 do we have sunken dialogs ?
1393
1394 GtkStyleClass *window_class = m_wxwindow->style->klass;
1395
1396 dw += 2 * window_class->xthickness;
1397 dh += 2 * window_class->ythickness;
1398 */
1399 }
1400 else
1401 {
1402 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1403 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1404
1405 GtkWidget *viewport = scroll_window->viewport;
1406 GtkStyleClass *viewport_class = viewport->style->klass;
1407
1408 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1409 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1410
1411 if ((m_windowStyle & wxRAISED_BORDER) ||
1412 (m_windowStyle & wxSUNKEN_BORDER))
1413 {
1414 dw += 2 * viewport_class->xthickness;
1415 dh += 2 * viewport_class->ythickness;
1416 }
1417
1418 if (GTK_WIDGET_VISIBLE(vscrollbar))
1419 {
1420 // dw += vscrollbar->allocation.width;
1421 dw += 15; // range.slider_width = 11 + 2*2pts edge
1422 dw += scroll_class->scrollbar_spacing;
1423 }
1424
1425 if (GTK_WIDGET_VISIBLE(hscrollbar))
1426 {
1427 // dh += hscrollbar->allocation.height;
1428 dh += 15;
1429 dh += scroll_class->scrollbar_spacing;
1430 }
1431 }
1432
1433 if (width) (*width) = m_width - dw;
1434 if (height) (*height) = m_height - dh;
1435 }
1436 }
1437
1438 void wxWindow::GetPosition( int *x, int *y ) const
1439 {
1440 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1441
1442 if (x) (*x) = m_x;
1443 if (y) (*y) = m_y;
1444 }
1445
1446 void wxWindow::ClientToScreen( int *x, int *y )
1447 {
1448 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1449
1450 GdkWindow *source = (GdkWindow *) NULL;
1451 if (m_wxwindow)
1452 source = m_wxwindow->window;
1453 else
1454 source = m_widget->window;
1455
1456 int org_x = 0;
1457 int org_y = 0;
1458 gdk_window_get_origin( source, &org_x, &org_y );
1459
1460 if (!m_wxwindow)
1461 {
1462 if (GTK_WIDGET_NO_WINDOW (m_widget))
1463 {
1464 org_x += m_widget->allocation.x;
1465 org_y += m_widget->allocation.y;
1466 }
1467 }
1468
1469 if (x) *x += org_x;
1470 if (y) *y += org_y;
1471 }
1472
1473 void wxWindow::ScreenToClient( int *x, int *y )
1474 {
1475 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1476
1477 GdkWindow *source = (GdkWindow *) NULL;
1478 if (m_wxwindow)
1479 source = m_wxwindow->window;
1480 else
1481 source = m_widget->window;
1482
1483 int org_x = 0;
1484 int org_y = 0;
1485 gdk_window_get_origin( source, &org_x, &org_y );
1486
1487 if (!m_wxwindow)
1488 {
1489 if (GTK_WIDGET_NO_WINDOW (m_widget))
1490 {
1491 org_x += m_widget->allocation.x;
1492 org_y += m_widget->allocation.y;
1493 }
1494 }
1495
1496 if (x) *x -= org_x;
1497 if (y) *y -= org_y;
1498 }
1499
1500 void wxWindow::Centre( int direction )
1501 {
1502 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1503
1504 if (IS_KIND_OF(this,wxDialog) || IS_KIND_OF(this,wxFrame))
1505 {
1506 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
1507 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
1508 ImplementSetPosition();
1509 }
1510 else
1511 {
1512 if (m_parent)
1513 {
1514 int p_w = 0;
1515 int p_h = 0;
1516 m_parent->GetSize( &p_w, &p_h );
1517 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (p_w - m_width) / 2;
1518 if (direction & wxVERTICAL == wxVERTICAL) m_y = (p_h - m_height) / 2;
1519 ImplementSetPosition();
1520 }
1521 }
1522 }
1523
1524 void wxWindow::Fit()
1525 {
1526 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1527
1528 int maxX = 0;
1529 int maxY = 0;
1530 wxNode *node = GetChildren()->First();
1531 while ( node )
1532 {
1533 wxWindow *win = (wxWindow *)node->Data();
1534 int wx, wy, ww, wh;
1535 win->GetPosition(&wx, &wy);
1536 win->GetSize(&ww, &wh);
1537 if ( wx + ww > maxX )
1538 maxX = wx + ww;
1539 if ( wy + wh > maxY )
1540 maxY = wy + wh;
1541
1542 node = node->Next();
1543 }
1544 SetClientSize(maxX + 5, maxY + 10);
1545 }
1546
1547 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1548 {
1549 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1550
1551 m_minWidth = minW;
1552 m_minHeight = minH;
1553 m_maxWidth = maxW;
1554 m_maxHeight = maxH;
1555 }
1556
1557 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1558 {
1559 //if (GetAutoLayout()) Layout();
1560 }
1561
1562 bool wxWindow::Show( bool show )
1563 {
1564 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1565
1566 if (show)
1567 gtk_widget_show( m_widget );
1568 else
1569 gtk_widget_hide( m_widget );
1570 m_isShown = show;
1571 return TRUE;
1572 }
1573
1574 void wxWindow::Enable( bool enable )
1575 {
1576 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1577
1578 m_isEnabled = enable;
1579 gtk_widget_set_sensitive( m_widget, enable );
1580 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1581 }
1582
1583 int wxWindow::GetCharHeight() const
1584 {
1585 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1586
1587 if (!m_font.Ok())
1588 {
1589 wxFAIL_MSG( "invalid font" );
1590 return -1;
1591 }
1592
1593 GdkFont *font = m_font.GetInternalFont( 1.0 );
1594 return font->ascent + font->descent;
1595 }
1596
1597 int wxWindow::GetCharWidth() const
1598 {
1599 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1600
1601 if (!m_font.Ok())
1602 {
1603 wxFAIL_MSG( "invalid font" );
1604 return -1;
1605 }
1606
1607 GdkFont *font = m_font.GetInternalFont( 1.0 );
1608 return gdk_string_width( font, "H" );
1609 }
1610
1611 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1612 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1613 {
1614 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1615
1616 wxFont fontToUse = m_font;
1617 if (theFont) fontToUse = *theFont;
1618
1619 if (!fontToUse.Ok())
1620 {
1621 wxFAIL_MSG( "invalid font" );
1622 return;
1623 }
1624 wxASSERT_MSG( (m_font.Ok()), "invalid font" );
1625
1626 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1627 if (x) (*x) = gdk_string_width( font, string );
1628 if (y) (*y) = font->ascent + font->descent;
1629 if (descent) (*descent) = font->descent;
1630 if (externalLeading) (*externalLeading) = 0; // ??
1631 }
1632
1633 void wxWindow::MakeModal( bool modal )
1634 {
1635 return;
1636 // Disable all other windows
1637 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1638 {
1639 wxNode *node = wxTopLevelWindows.First();
1640 while (node)
1641 {
1642 wxWindow *win = (wxWindow *)node->Data();
1643 if (win != this)
1644 win->Enable(!modal);
1645
1646 node = node->Next();
1647 }
1648 }
1649 }
1650
1651 void wxWindow::SetFocus()
1652 {
1653 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1654
1655 GtkWidget *connect_widget = GetConnectWidget();
1656 if (connect_widget)
1657 {
1658 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1659 {
1660 gtk_widget_grab_focus (connect_widget);
1661 }
1662 }
1663 }
1664
1665 bool wxWindow::OnClose()
1666 {
1667 return TRUE;
1668 }
1669
1670 void wxWindow::AddChild( wxWindow *child )
1671 {
1672 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1673 wxASSERT_MSG( (m_wxwindow != NULL), "window need client area" );
1674 wxASSERT_MSG( (child != NULL), "invalid child" );
1675 wxASSERT_MSG( (child->m_widget != NULL), "invalid child" );
1676
1677 // Addchild is (often) called before the program
1678 // has left the parents constructor so that no
1679 // virtual tables work yet. The approach below
1680 // practically imitates virtual tables, i.e. it
1681 // implements a different AddChild() behaviour
1682 // for wxFrame, wxDialog, wxWindow and
1683 // wxMDIParentFrame.
1684
1685 // wxFrame and wxDialog as children aren't placed into the parents
1686
1687 if (( IS_KIND_OF(child,wxFrame) || IS_KIND_OF(child,wxDialog) ) &&
1688 (!IS_KIND_OF(child,wxMDIChildFrame)))
1689 {
1690 m_children.Append( child );
1691
1692 if ((child->m_x != -1) && (child->m_y != -1))
1693 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1694
1695 return;
1696 }
1697
1698 // In the case of an wxMDIChildFrame descendant, we use the
1699 // client windows's AddChild()
1700
1701 if (IS_KIND_OF(this,wxMDIParentFrame))
1702 {
1703 if (IS_KIND_OF(child,wxMDIChildFrame))
1704 {
1705 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1706 if (client)
1707 {
1708 client->AddChild( child );
1709 return;
1710 }
1711 }
1712 }
1713
1714 // wxNotebook is very special, so it has a private AddChild()
1715
1716 if (IS_KIND_OF(this,wxNotebook))
1717 {
1718 wxNotebook *tab = (wxNotebook*)this;
1719 tab->AddChild( child );
1720 return;
1721 }
1722
1723 // wxFrame has a private AddChild
1724
1725 if (IS_KIND_OF(this,wxFrame) && !IS_KIND_OF(this,wxMDIChildFrame))
1726 {
1727 wxFrame *frame = (wxFrame*)this;
1728 frame->AddChild( child );
1729 return;
1730 }
1731
1732 // All the rest
1733
1734 m_children.Append( child );
1735 if (m_wxwindow) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget,
1736 child->m_x, child->m_y );
1737
1738 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
1739 }
1740
1741 wxList *wxWindow::GetChildren()
1742 {
1743 return (&m_children);
1744 }
1745
1746 void wxWindow::RemoveChild( wxWindow *child )
1747 {
1748 if (GetChildren())
1749 GetChildren()->DeleteObject( child );
1750 child->m_parent = (wxWindow *) NULL;
1751 }
1752
1753 void wxWindow::SetReturnCode( int retCode )
1754 {
1755 m_retCode = retCode;
1756 }
1757
1758 int wxWindow::GetReturnCode()
1759 {
1760 return m_retCode;
1761 }
1762
1763 void wxWindow::Raise()
1764 {
1765 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1766
1767 if (m_widget) gdk_window_raise( m_widget->window );
1768 }
1769
1770 void wxWindow::Lower()
1771 {
1772 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1773
1774 if (m_widget) gdk_window_lower( m_widget->window );
1775 }
1776
1777 wxEvtHandler *wxWindow::GetEventHandler()
1778 {
1779 return m_eventHandler;
1780 }
1781
1782 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1783 {
1784 m_eventHandler = handler;
1785 }
1786
1787 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1788 {
1789 handler->SetNextHandler(GetEventHandler());
1790 SetEventHandler(handler);
1791 }
1792
1793 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1794 {
1795 if (GetEventHandler())
1796 {
1797 wxEvtHandler *handlerA = GetEventHandler();
1798 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1799 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1800 SetEventHandler(handlerB);
1801 if (deleteHandler)
1802 {
1803 delete handlerA;
1804 return (wxEvtHandler*) NULL;
1805 }
1806 else
1807 return handlerA;
1808 }
1809 else
1810 return (wxEvtHandler *) NULL;
1811 }
1812
1813 wxValidator *wxWindow::GetValidator()
1814 {
1815 return m_windowValidator;
1816 }
1817
1818 void wxWindow::SetValidator( const wxValidator& validator )
1819 {
1820 if (m_windowValidator) delete m_windowValidator;
1821 m_windowValidator = validator.Clone();
1822 if (m_windowValidator) m_windowValidator->SetWindow(this);
1823 }
1824
1825 bool wxWindow::IsBeingDeleted()
1826 {
1827 return FALSE;
1828 }
1829
1830 void wxWindow::SetId( wxWindowID id )
1831 {
1832 m_windowId = id;
1833 }
1834
1835 wxWindowID wxWindow::GetId()
1836 {
1837 return m_windowId;
1838 }
1839
1840 void wxWindow::SetCursor( const wxCursor &cursor )
1841 {
1842 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1843
1844 if (m_cursor == NULL)
1845 {
1846 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1847 m_cursor = new wxCursor( wxCURSOR_ARROW );
1848 }
1849
1850 if (cursor.Ok())
1851 {
1852 if (*((wxCursor*)&cursor) == m_cursor) return;
1853 *m_cursor = cursor;
1854 }
1855 else
1856 {
1857 *m_cursor = *wxSTANDARD_CURSOR;
1858 }
1859
1860 if ((m_widget) && (m_widget->window))
1861 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1862
1863 if ((m_wxwindow) && (m_wxwindow->window))
1864 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1865 }
1866
1867 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1868 {
1869 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1870
1871 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1872 {
1873 if (rect)
1874 gdk_window_clear_area( m_wxwindow->window,
1875 rect->x,
1876 rect->y,
1877 rect->width,
1878 rect->height );
1879 else
1880 Clear();
1881 }
1882 if (!rect)
1883 {
1884 if (m_wxwindow)
1885 {
1886 int w = 0;
1887 int h = 0;
1888 GetClientSize( &w, &h );
1889
1890 GdkRectangle gdk_rect;
1891 gdk_rect.x = 0;
1892 gdk_rect.y = 0;
1893 gdk_rect.width = w;
1894 gdk_rect.height = h;
1895 gtk_widget_draw( m_wxwindow, &gdk_rect );
1896 }
1897 }
1898 else
1899 {
1900 GdkRectangle gdk_rect;
1901 gdk_rect.x = rect->x;
1902 gdk_rect.y = rect->y;
1903 gdk_rect.width = rect->width;
1904 gdk_rect.height = rect->height;
1905
1906 if (m_wxwindow)
1907 gtk_widget_draw( m_wxwindow, &gdk_rect );
1908 else
1909 gtk_widget_draw( m_widget, &gdk_rect );
1910 }
1911 }
1912
1913 wxRegion wxWindow::GetUpdateRegion() const
1914 {
1915 return m_updateRegion;
1916 }
1917
1918 bool wxWindow::IsExposed( int x, int y) const
1919 {
1920 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1921 }
1922
1923 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
1924 {
1925 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
1926 }
1927
1928 bool wxWindow::IsExposed( const wxPoint& pt ) const
1929 {
1930 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
1931 }
1932
1933 bool wxWindow::IsExposed( const wxRect& rect ) const
1934 {
1935 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
1936 }
1937
1938 void wxWindow::Clear()
1939 {
1940 wxCHECK_RET( m_widget != NULL, "invalid window" );
1941
1942 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
1943 }
1944
1945 wxColour wxWindow::GetBackgroundColour() const
1946 {
1947 return m_backgroundColour;
1948 }
1949
1950 void wxWindow::SetBackgroundColourHelper( GdkWindow *window )
1951 {
1952 if (!m_backgroundColour.Ok()) return;
1953
1954 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
1955 gdk_window_set_background( window, m_backgroundColour.GetColor() );
1956 gdk_window_clear( window );
1957 }
1958
1959 void wxWindow::SetBackgroundColour( const wxColour &colour )
1960 {
1961 wxCHECK_RET( m_widget != NULL, "invalid window" );
1962
1963 m_backgroundColour = colour;
1964
1965 GtkWidget *widget = m_wxwindow == NULL ? m_widget : m_wxwindow;
1966 SetBackgroundColourHelper( widget->window );
1967 }
1968
1969 wxColour wxWindow::GetForegroundColour() const
1970 {
1971 return m_foregroundColour;
1972 }
1973
1974 void wxWindow::SetForegroundColour( const wxColour &colour )
1975 {
1976 m_foregroundColour = colour;
1977 }
1978
1979 bool wxWindow::Validate()
1980 {
1981 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
1982
1983 wxNode *node = GetChildren()->First();
1984 while (node)
1985 {
1986 wxWindow *child = (wxWindow *)node->Data();
1987 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
1988 { return FALSE; }
1989 node = node->Next();
1990 }
1991 return TRUE;
1992 }
1993
1994 bool wxWindow::TransferDataToWindow()
1995 {
1996 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
1997
1998 wxNode *node = GetChildren()->First();
1999 while (node)
2000 {
2001 wxWindow *child = (wxWindow *)node->Data();
2002 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2003 !child->GetValidator()->TransferToWindow() )
2004 {
2005 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2006 return FALSE;
2007 }
2008 node = node->Next();
2009 }
2010 return TRUE;
2011 }
2012
2013 bool wxWindow::TransferDataFromWindow()
2014 {
2015 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2016
2017 wxNode *node = GetChildren()->First();
2018 while (node)
2019 {
2020 wxWindow *child = (wxWindow *)node->Data();
2021 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2022 { return FALSE; }
2023 node = node->Next();
2024 }
2025 return TRUE;
2026 }
2027
2028 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2029 {
2030 m_acceleratorTable = accel;
2031 }
2032
2033 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2034 {
2035 TransferDataToWindow();
2036 }
2037
2038 void wxWindow::InitDialog()
2039 {
2040 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2041
2042 wxInitDialogEvent event(GetId());
2043 event.SetEventObject( this );
2044 GetEventHandler()->ProcessEvent(event);
2045 }
2046
2047 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2048 {
2049 menu->SetInvokingWindow( win );
2050 wxNode *node = menu->m_items.First();
2051 while (node)
2052 {
2053 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2054 if (menuitem->IsSubMenu())
2055 SetInvokingWindow( menuitem->GetSubMenu(), win );
2056 node = node->Next();
2057 }
2058 }
2059
2060 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2061 {
2062 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2063
2064 SetInvokingWindow( menu, this );
2065 gtk_menu_popup(
2066 GTK_MENU(menu->m_menu),
2067 (GtkWidget *)NULL, // parent menu shell
2068 (GtkWidget *)NULL, // parent menu item
2069 (GtkMenuPositionFunc)NULL,
2070 NULL, // client data
2071 0, // button used to activate it
2072 0//gs_timeLastClick // the time of activation
2073 );
2074 return TRUE;
2075 }
2076
2077 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2078 {
2079 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2080
2081 GtkWidget *dnd_widget = GetConnectWidget();
2082
2083 DisconnectDnDWidget( dnd_widget );
2084
2085 if (m_pDropTarget) delete m_pDropTarget;
2086 m_pDropTarget = dropTarget;
2087
2088 ConnectDnDWidget( dnd_widget );
2089 }
2090
2091 wxDropTarget *wxWindow::GetDropTarget() const
2092 {
2093 return m_pDropTarget;
2094 }
2095
2096 void wxWindow::ConnectDnDWidget( GtkWidget *widget )
2097 {
2098 if (!m_pDropTarget) return;
2099
2100 m_pDropTarget->RegisterWidget( widget );
2101
2102 gtk_signal_connect( GTK_OBJECT(widget), "drop_data_available_event",
2103 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2104 }
2105
2106 void wxWindow::DisconnectDnDWidget( GtkWidget *widget )
2107 {
2108 if (!m_pDropTarget) return;
2109
2110 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
2111 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2112
2113 m_pDropTarget->UnregisterWidget( widget );
2114 }
2115
2116 GtkWidget* wxWindow::GetConnectWidget()
2117 {
2118 GtkWidget *connect_widget = m_widget;
2119 if (m_wxwindow) connect_widget = m_wxwindow;
2120
2121 return connect_widget;
2122 }
2123
2124 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2125 {
2126 if (m_wxwindow) return (window == m_wxwindow->window);
2127 return (window == m_widget->window);
2128 }
2129
2130 void wxWindow::SetFont( const wxFont &font )
2131 {
2132 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2133
2134 if (((wxFont*)&font)->Ok())
2135 m_font = font;
2136 else
2137 m_font = *wxSWISS_FONT;
2138
2139 GtkStyle *style = (GtkStyle*) NULL;
2140 if (!m_hasOwnStyle)
2141 {
2142 m_hasOwnStyle = TRUE;
2143 style = gtk_style_copy( gtk_widget_get_style( m_widget ) );
2144 }
2145 else
2146 {
2147 style = gtk_widget_get_style( m_widget );
2148 }
2149
2150 gdk_font_unref( style->font );
2151 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2152
2153 gtk_widget_set_style( m_widget, style );
2154 }
2155
2156 wxFont *wxWindow::GetFont()
2157 {
2158 return &m_font;
2159 }
2160
2161 void wxWindow::SetWindowStyleFlag( long flag )
2162 {
2163 m_windowStyle = flag;
2164 }
2165
2166 long wxWindow::GetWindowStyleFlag() const
2167 {
2168 return m_windowStyle;
2169 }
2170
2171 void wxWindow::CaptureMouse()
2172 {
2173 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2174
2175 wxASSERT_MSG( (g_capturing == FALSE), "CaptureMouse called twice" );
2176
2177 GtkWidget *connect_widget = GetConnectWidget();
2178 gtk_grab_add( connect_widget );
2179 gdk_pointer_grab ( connect_widget->window, FALSE,
2180 (GdkEventMask)
2181 (GDK_BUTTON_PRESS_MASK |
2182 GDK_BUTTON_RELEASE_MASK |
2183 GDK_POINTER_MOTION_MASK),
2184 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2185 g_capturing = TRUE;
2186 }
2187
2188 void wxWindow::ReleaseMouse()
2189 {
2190 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2191
2192 wxASSERT_MSG( (g_capturing == TRUE), "ReleaseMouse called twice" );
2193
2194 GtkWidget *connect_widget = GetConnectWidget();
2195 gtk_grab_remove( connect_widget );
2196 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2197 g_capturing = FALSE;
2198 }
2199
2200 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2201 {
2202 }
2203
2204 wxString wxWindow::GetTitle() const
2205 {
2206 return (wxString&)m_windowName;
2207 }
2208
2209 wxString wxWindow::GetLabel() const
2210 {
2211 return GetTitle();
2212 }
2213
2214 void wxWindow::SetName( const wxString &name )
2215 {
2216 m_windowName = name;
2217 }
2218
2219 wxString wxWindow::GetName() const
2220 {
2221 return (wxString&)m_windowName;
2222 }
2223
2224 bool wxWindow::IsShown() const
2225 {
2226 return m_isShown;
2227 }
2228
2229 bool wxWindow::IsRetained()
2230 {
2231 return FALSE;
2232 }
2233
2234 wxWindow *wxWindow::FindWindow( long id )
2235 {
2236 if (id == m_windowId) return this;
2237 wxNode *node = m_children.First();
2238 while (node)
2239 {
2240 wxWindow *child = (wxWindow*)node->Data();
2241 wxWindow *res = child->FindWindow( id );
2242 if (res) return res;
2243 node = node->Next();
2244 }
2245 return (wxWindow *) NULL;
2246 }
2247
2248 wxWindow *wxWindow::FindWindow( const wxString& name )
2249 {
2250 if (name == m_windowName) return this;
2251 wxNode *node = m_children.First();
2252 while (node)
2253 {
2254 wxWindow *child = (wxWindow*)node->Data();
2255 wxWindow *res = child->FindWindow( name );
2256 if (res) return res;
2257 node = node->Next();
2258 }
2259 return (wxWindow *) NULL;
2260 }
2261
2262 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2263 int range, bool refresh )
2264 {
2265 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2266
2267 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2268
2269 if (!m_wxwindow) return;
2270
2271 if (orient == wxHORIZONTAL)
2272 {
2273 float fpos = (float)pos;
2274 float frange = (float)range;
2275 float fthumb = (float)thumbVisible;
2276
2277 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2278 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2279 {
2280 SetScrollPos( orient, pos, refresh );
2281 return;
2282 }
2283
2284 m_oldHorizontalPos = fpos;
2285
2286 m_hAdjust->lower = 0.0;
2287 m_hAdjust->upper = frange;
2288 m_hAdjust->value = fpos;
2289 m_hAdjust->step_increment = 1.0;
2290 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2291 m_hAdjust->page_size = fthumb;
2292 }
2293 else
2294 {
2295 float fpos = (float)pos;
2296 float frange = (float)range;
2297 float fthumb = (float)thumbVisible;
2298
2299 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2300 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2301 {
2302 SetScrollPos( orient, pos, refresh );
2303 return;
2304 }
2305
2306 m_oldVerticalPos = fpos;
2307
2308 m_vAdjust->lower = 0.0;
2309 m_vAdjust->upper = frange;
2310 m_vAdjust->value = fpos;
2311 m_vAdjust->step_increment = 1.0;
2312 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2313 m_vAdjust->page_size = fthumb;
2314 }
2315
2316 if (m_wxwindow->window)
2317 {
2318 if (orient == wxHORIZONTAL)
2319 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2320 else
2321 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2322
2323 gtk_widget_set_usize( m_widget, m_width, m_height );
2324 }
2325 }
2326
2327 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2328 {
2329 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2330
2331 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2332
2333 if (!m_wxwindow) return;
2334
2335 if (orient == wxHORIZONTAL)
2336 {
2337 float fpos = (float)pos;
2338 m_oldHorizontalPos = fpos;
2339
2340 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2341 m_hAdjust->value = fpos;
2342 }
2343 else
2344 {
2345 float fpos = (float)pos;
2346 m_oldVerticalPos = fpos;
2347 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2348 m_vAdjust->value = fpos;
2349 }
2350
2351 if (!m_isScrolling)
2352 {
2353 if (m_wxwindow->window)
2354 {
2355 if (orient == wxHORIZONTAL)
2356 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2357 else
2358 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2359 }
2360 }
2361 }
2362
2363 int wxWindow::GetScrollThumb( int orient ) const
2364 {
2365 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2366
2367 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2368
2369 if (!m_wxwindow) return 0;
2370
2371 if (orient == wxHORIZONTAL)
2372 return (int)(m_hAdjust->page_size+0.5);
2373 else
2374 return (int)(m_vAdjust->page_size+0.5);
2375 }
2376
2377 int wxWindow::GetScrollPos( int orient ) const
2378 {
2379 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2380
2381 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2382
2383 if (!m_wxwindow) return 0;
2384
2385 if (orient == wxHORIZONTAL)
2386 return (int)(m_hAdjust->value+0.5);
2387 else
2388 return (int)(m_vAdjust->value+0.5);
2389 }
2390
2391 int wxWindow::GetScrollRange( int orient ) const
2392 {
2393 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2394
2395 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2396
2397 if (!m_wxwindow) return 0;
2398
2399 if (orient == wxHORIZONTAL)
2400 return (int)(m_hAdjust->upper+0.5);
2401 else
2402 return (int)(m_vAdjust->upper+0.5);
2403 }
2404
2405 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2406 {
2407 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2408
2409 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2410
2411 if (!m_wxwindow) return;
2412
2413 int cw = 0;
2414 int ch = 0;
2415 GetClientSize( &cw, &ch );
2416
2417 int w = cw - abs(dx);
2418 int h = ch - abs(dy);
2419 if ((h < 0) || (w < 0))
2420 {
2421 Refresh();
2422 return;
2423 }
2424 int s_x = 0;
2425 int s_y = 0;
2426 if (dx < 0) s_x = -dx;
2427 if (dy < 0) s_y = -dy;
2428 int d_x = 0;
2429 int d_y = 0;
2430 if (dx > 0) d_x = dx;
2431 if (dy > 0) d_y = dy;
2432
2433 if (!m_scrollGC)
2434 {
2435 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2436 gdk_gc_set_exposures( m_scrollGC, TRUE );
2437 }
2438
2439 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2440 m_wxwindow->window, s_x, s_y, w, h );
2441
2442 wxRect rect;
2443 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2444 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2445 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2446 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2447
2448 Refresh( TRUE, &rect );
2449 }
2450
2451 //-------------------------------------------------------------------------------------
2452 // Layout
2453 //-------------------------------------------------------------------------------------
2454
2455 wxLayoutConstraints *wxWindow::GetConstraints() const
2456 {
2457 return m_constraints;
2458 }
2459
2460 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2461 {
2462 if (m_constraints)
2463 {
2464 UnsetConstraints(m_constraints);
2465 delete m_constraints;
2466 }
2467 m_constraints = constraints;
2468 if (m_constraints)
2469 {
2470 // Make sure other windows know they're part of a 'meaningful relationship'
2471 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2472 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2473 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2474 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2475 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2476 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2477 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2478 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2479 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2480 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2481 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2482 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2483 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2484 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2485 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2486 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2487 }
2488 ;
2489 }
2490 ;
2491
2492 void wxWindow::SetAutoLayout( bool autoLayout )
2493 {
2494 m_autoLayout = autoLayout;
2495 }
2496
2497 bool wxWindow::GetAutoLayout() const
2498 {
2499 return m_autoLayout;
2500 }
2501
2502 wxSizer *wxWindow::GetSizer() const
2503 {
2504 return m_windowSizer;
2505 }
2506
2507 void wxWindow::SetSizerParent( wxWindow *win )
2508 {
2509 m_sizerParent = win;
2510 }
2511
2512 wxWindow *wxWindow::GetSizerParent() const
2513 {
2514 return m_sizerParent;
2515 }
2516
2517 // This removes any dangling pointers to this window
2518 // in other windows' constraintsInvolvedIn lists.
2519 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2520 {
2521 if (c)
2522 {
2523 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2524 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2525 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2526 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2527 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2528 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2529 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2530 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2531 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2532 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2533 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2534 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2535 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2536 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2537 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2538 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2539 }
2540 }
2541
2542 // Back-pointer to other windows we're involved with, so if we delete
2543 // this window, we must delete any constraints we're involved with.
2544 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2545 {
2546 if (!m_constraintsInvolvedIn)
2547 m_constraintsInvolvedIn = new wxList;
2548 if (!m_constraintsInvolvedIn->Member(otherWin))
2549 m_constraintsInvolvedIn->Append(otherWin);
2550 }
2551
2552 // REMOVE back-pointer to other windows we're involved with.
2553 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2554 {
2555 if (m_constraintsInvolvedIn)
2556 m_constraintsInvolvedIn->DeleteObject(otherWin);
2557 }
2558
2559 // Reset any constraints that mention this window
2560 void wxWindow::DeleteRelatedConstraints()
2561 {
2562 if (m_constraintsInvolvedIn)
2563 {
2564 wxNode *node = m_constraintsInvolvedIn->First();
2565 while (node)
2566 {
2567 wxWindow *win = (wxWindow *)node->Data();
2568 wxNode *next = node->Next();
2569 wxLayoutConstraints *constr = win->GetConstraints();
2570
2571 // Reset any constraints involving this window
2572 if (constr)
2573 {
2574 constr->left.ResetIfWin((wxWindow *)this);
2575 constr->top.ResetIfWin((wxWindow *)this);
2576 constr->right.ResetIfWin((wxWindow *)this);
2577 constr->bottom.ResetIfWin((wxWindow *)this);
2578 constr->width.ResetIfWin((wxWindow *)this);
2579 constr->height.ResetIfWin((wxWindow *)this);
2580 constr->centreX.ResetIfWin((wxWindow *)this);
2581 constr->centreY.ResetIfWin((wxWindow *)this);
2582 }
2583 delete node;
2584 node = next;
2585 }
2586 delete m_constraintsInvolvedIn;
2587 m_constraintsInvolvedIn = (wxList *) NULL;
2588 }
2589 }
2590
2591 void wxWindow::SetSizer(wxSizer *sizer)
2592 {
2593 m_windowSizer = sizer;
2594 if (sizer)
2595 sizer->SetSizerParent((wxWindow *)this);
2596 }
2597
2598 /*
2599 * New version
2600 */
2601
2602 bool wxWindow::Layout()
2603 {
2604 if (GetConstraints())
2605 {
2606 int w, h;
2607 GetClientSize(&w, &h);
2608 GetConstraints()->width.SetValue(w);
2609 GetConstraints()->height.SetValue(h);
2610 }
2611
2612 // If top level (one sizer), evaluate the sizer's constraints.
2613 if (GetSizer())
2614 {
2615 int noChanges;
2616 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2617 GetSizer()->LayoutPhase1(&noChanges);
2618 GetSizer()->LayoutPhase2(&noChanges);
2619 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2620 return TRUE;
2621 }
2622 else
2623 {
2624 // Otherwise, evaluate child constraints
2625 ResetConstraints(); // Mark all constraints as unevaluated
2626 DoPhase(1); // Just one phase need if no sizers involved
2627 DoPhase(2);
2628 SetConstraintSizes(); // Recursively set the real window sizes
2629 }
2630 return TRUE;
2631 }
2632
2633
2634 // Do a phase of evaluating constraints:
2635 // the default behaviour. wxSizers may do a similar
2636 // thing, but also impose their own 'constraints'
2637 // and order the evaluation differently.
2638 bool wxWindow::LayoutPhase1(int *noChanges)
2639 {
2640 wxLayoutConstraints *constr = GetConstraints();
2641 if (constr)
2642 {
2643 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2644 }
2645 else
2646 return TRUE;
2647 }
2648
2649 bool wxWindow::LayoutPhase2(int *noChanges)
2650 {
2651 *noChanges = 0;
2652
2653 // Layout children
2654 DoPhase(1);
2655 DoPhase(2);
2656 return TRUE;
2657 }
2658
2659 // Do a phase of evaluating child constraints
2660 bool wxWindow::DoPhase(int phase)
2661 {
2662 int noIterations = 0;
2663 int maxIterations = 500;
2664 int noChanges = 1;
2665 int noFailures = 0;
2666 wxList succeeded;
2667 while ((noChanges > 0) && (noIterations < maxIterations))
2668 {
2669 noChanges = 0;
2670 noFailures = 0;
2671 wxNode *node = GetChildren()->First();
2672 while (node)
2673 {
2674 wxWindow *child = (wxWindow *)node->Data();
2675 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2676 {
2677 wxLayoutConstraints *constr = child->GetConstraints();
2678 if (constr)
2679 {
2680 if (succeeded.Member(child))
2681 {
2682 }
2683 else
2684 {
2685 int tempNoChanges = 0;
2686 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2687 noChanges += tempNoChanges;
2688 if (success)
2689 {
2690 succeeded.Append(child);
2691 }
2692 }
2693 }
2694 }
2695 node = node->Next();
2696 }
2697 noIterations ++;
2698 }
2699 return TRUE;
2700 }
2701
2702 void wxWindow::ResetConstraints()
2703 {
2704 wxLayoutConstraints *constr = GetConstraints();
2705 if (constr)
2706 {
2707 constr->left.SetDone(FALSE);
2708 constr->top.SetDone(FALSE);
2709 constr->right.SetDone(FALSE);
2710 constr->bottom.SetDone(FALSE);
2711 constr->width.SetDone(FALSE);
2712 constr->height.SetDone(FALSE);
2713 constr->centreX.SetDone(FALSE);
2714 constr->centreY.SetDone(FALSE);
2715 }
2716 wxNode *node = GetChildren()->First();
2717 while (node)
2718 {
2719 wxWindow *win = (wxWindow *)node->Data();
2720 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2721 win->ResetConstraints();
2722 node = node->Next();
2723 }
2724 }
2725
2726 // Need to distinguish between setting the 'fake' size for
2727 // windows and sizers, and setting the real values.
2728 void wxWindow::SetConstraintSizes(bool recurse)
2729 {
2730 wxLayoutConstraints *constr = GetConstraints();
2731 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2732 constr->width.GetDone() && constr->height.GetDone())
2733 {
2734 int x = constr->left.GetValue();
2735 int y = constr->top.GetValue();
2736 int w = constr->width.GetValue();
2737 int h = constr->height.GetValue();
2738
2739 // If we don't want to resize this window, just move it...
2740 if ((constr->width.GetRelationship() != wxAsIs) ||
2741 (constr->height.GetRelationship() != wxAsIs))
2742 {
2743 // Calls Layout() recursively. AAAGH. How can we stop that.
2744 // Simply take Layout() out of non-top level OnSizes.
2745 SizerSetSize(x, y, w, h);
2746 }
2747 else
2748 {
2749 SizerMove(x, y);
2750 }
2751 }
2752 else if (constr)
2753 {
2754 char *windowClass = this->GetClassInfo()->GetClassName();
2755
2756 wxString winName;
2757 if (GetName() == "")
2758 winName = _("unnamed");
2759 else
2760 winName = GetName();
2761 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2762 if (!constr->left.GetDone())
2763 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2764 if (!constr->right.GetDone())
2765 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2766 if (!constr->width.GetDone())
2767 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2768 if (!constr->height.GetDone())
2769 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2770 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2771 }
2772
2773 if (recurse)
2774 {
2775 wxNode *node = GetChildren()->First();
2776 while (node)
2777 {
2778 wxWindow *win = (wxWindow *)node->Data();
2779 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2780 win->SetConstraintSizes();
2781 node = node->Next();
2782 }
2783 }
2784 }
2785
2786 // This assumes that all sizers are 'on' the same
2787 // window, i.e. the parent of this window.
2788 void wxWindow::TransformSizerToActual(int *x, int *y) const
2789 {
2790 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2791 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2792 return;
2793
2794 int xp, yp;
2795 m_sizerParent->GetPosition(&xp, &yp);
2796 m_sizerParent->TransformSizerToActual(&xp, &yp);
2797 *x += xp;
2798 *y += yp;
2799 }
2800
2801 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2802 {
2803 int xx = x;
2804 int yy = y;
2805 TransformSizerToActual(&xx, &yy);
2806 SetSize(xx, yy, w, h);
2807 }
2808
2809 void wxWindow::SizerMove(int x, int y)
2810 {
2811 int xx = x;
2812 int yy = y;
2813 TransformSizerToActual(&xx, &yy);
2814 Move(xx, yy);
2815 }
2816
2817 // Only set the size/position of the constraint (if any)
2818 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2819 {
2820 wxLayoutConstraints *constr = GetConstraints();
2821 if (constr)
2822 {
2823 if (x != -1)
2824 {
2825 constr->left.SetValue(x);
2826 constr->left.SetDone(TRUE);
2827 }
2828 if (y != -1)
2829 {
2830 constr->top.SetValue(y);
2831 constr->top.SetDone(TRUE);
2832 }
2833 if (w != -1)
2834 {
2835 constr->width.SetValue(w);
2836 constr->width.SetDone(TRUE);
2837 }
2838 if (h != -1)
2839 {
2840 constr->height.SetValue(h);
2841 constr->height.SetDone(TRUE);
2842 }
2843 }
2844 }
2845
2846 void wxWindow::MoveConstraint(int x, int y)
2847 {
2848 wxLayoutConstraints *constr = GetConstraints();
2849 if (constr)
2850 {
2851 if (x != -1)
2852 {
2853 constr->left.SetValue(x);
2854 constr->left.SetDone(TRUE);
2855 }
2856 if (y != -1)
2857 {
2858 constr->top.SetValue(y);
2859 constr->top.SetDone(TRUE);
2860 }
2861 }
2862 }
2863
2864 void wxWindow::GetSizeConstraint(int *w, int *h) const
2865 {
2866 wxLayoutConstraints *constr = GetConstraints();
2867 if (constr)
2868 {
2869 *w = constr->width.GetValue();
2870 *h = constr->height.GetValue();
2871 }
2872 else
2873 GetSize(w, h);
2874 }
2875
2876 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2877 {
2878 wxLayoutConstraints *constr = GetConstraints();
2879 if (constr)
2880 {
2881 *w = constr->width.GetValue();
2882 *h = constr->height.GetValue();
2883 }
2884 else
2885 GetClientSize(w, h);
2886 }
2887
2888 void wxWindow::GetPositionConstraint(int *x, int *y) const
2889 {
2890 wxLayoutConstraints *constr = GetConstraints();
2891 if (constr)
2892 {
2893 *x = constr->left.GetValue();
2894 *y = constr->top.GetValue();
2895 }
2896 else
2897 GetPosition(x, y);
2898 }
2899
2900 bool wxWindow::AcceptsFocus() const
2901 {
2902 return IsEnabled() && IsShown();
2903 }
2904
2905 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
2906 {
2907 UpdateWindowUI();
2908 }