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