]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
wxToolTip part II
[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))
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
1262 //-----------------------------------------------------------------------------
1263 // global functions
1264 //-----------------------------------------------------------------------------
1265
1266 wxWindow* wxGetActiveWindow()
1267 {
1268 return g_focusWindow;
1269 }
1270
1271 //-----------------------------------------------------------------------------
1272 // wxWindow
1273 //-----------------------------------------------------------------------------
1274
1275 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
1276
1277 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
1278 EVT_SIZE(wxWindow::OnSize)
1279 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
1280 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
1281 EVT_KEY_DOWN(wxWindow::OnKeyDown)
1282 END_EVENT_TABLE()
1283
1284 wxWindow::wxWindow()
1285 {
1286 m_widget = (GtkWidget *) NULL;
1287 m_wxwindow = (GtkWidget *) NULL;
1288 m_parent = (wxWindow *) NULL;
1289 m_children.DeleteContents( FALSE );
1290
1291 m_x = 0;
1292 m_y = 0;
1293 m_width = 0;
1294 m_height = 0;
1295 m_minWidth = -1;
1296 m_minHeight = -1;
1297 m_maxWidth = -1;
1298 m_maxHeight = -1;
1299
1300 m_retCode = 0;
1301
1302 m_eventHandler = this;
1303 m_windowValidator = (wxValidator *) NULL;
1304
1305 m_windowId = -1;
1306
1307 m_cursor = (wxCursor *) NULL;
1308 m_font = *wxSWISS_FONT;
1309 m_windowStyle = 0;
1310 m_windowName = "noname";
1311
1312 m_constraints = (wxLayoutConstraints *) NULL;
1313 m_constraintsInvolvedIn = (wxList *) NULL;
1314 m_windowSizer = (wxSizer *) NULL;
1315 m_sizerParent = (wxWindow *) NULL;
1316 m_autoLayout = FALSE;
1317
1318 m_sizeSet = FALSE;
1319 m_hasVMT = FALSE;
1320 m_needParent = TRUE;
1321
1322 m_hasScrolling = FALSE;
1323 m_isScrolling = FALSE;
1324 m_hAdjust = (GtkAdjustment*) NULL;
1325 m_vAdjust = (GtkAdjustment*) NULL;
1326 m_oldHorizontalPos = 0.0;
1327 m_oldVerticalPos = 0.0;
1328
1329 m_isShown = FALSE;
1330 m_isEnabled = TRUE;
1331
1332 #if wxUSE_DRAG_AND_DROP
1333 m_dropTarget = (wxDropTarget*) NULL;
1334 #endif
1335 m_resizing = FALSE;
1336 m_scrollGC = (GdkGC*) NULL;
1337 m_widgetStyle = (GtkStyle*) NULL;
1338
1339 m_insertCallback = wxInsertChildInWindow;
1340
1341 m_clientObject = (wxClientData*) NULL;
1342 m_clientData = NULL;
1343
1344 m_isStaticBox = FALSE;
1345 m_acceptsFocus = FALSE;
1346
1347 m_toolTip = (wxToolTip*) NULL;
1348 }
1349
1350 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
1351 const wxPoint &pos, const wxSize &size,
1352 long style, const wxString &name )
1353 {
1354 m_insertCallback = wxInsertChildInWindow;
1355 Create( parent, id, pos, size, style, name );
1356 }
1357
1358 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
1359 const wxPoint &pos, const wxSize &size,
1360 long style, const wxString &name )
1361 {
1362 m_isShown = FALSE;
1363 m_isEnabled = TRUE;
1364 m_needParent = TRUE;
1365
1366 PreCreation( parent, id, pos, size, style, name );
1367
1368 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
1369 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
1370
1371 #ifdef __WXDEBUG__
1372 debug_focus_in( m_widget, "wxWindow::m_widget", name );
1373 #endif
1374
1375 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
1376
1377 #ifdef __WXDEBUG__
1378 debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
1379 debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
1380 #endif
1381
1382 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1383 scroll_class->scrollbar_spacing = 0;
1384
1385 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1386
1387 m_oldHorizontalPos = 0.0;
1388 m_oldVerticalPos = 0.0;
1389
1390 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1391 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
1392
1393 m_wxwindow = gtk_myfixed_new();
1394
1395 #ifdef __WXDEBUG__
1396 debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
1397 #endif
1398
1399 #ifdef NEW_GTK_SCROLL_CODE
1400 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1401 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1402 #else
1403 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1404 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
1405 #endif
1406
1407 #ifdef __WXDEBUG__
1408 debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
1409 #endif
1410
1411 if (m_windowStyle & wxRAISED_BORDER)
1412 {
1413 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1414 }
1415 else if (m_windowStyle & wxSUNKEN_BORDER)
1416 {
1417 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1418 }
1419 else
1420 {
1421 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1422 }
1423
1424 if ((m_windowStyle & wxTAB_TRAVERSAL) != 0)
1425 {
1426 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); /* changed from UNSET */
1427 m_acceptsFocus = FALSE;
1428 }
1429 else
1430 {
1431 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1432 m_acceptsFocus = TRUE;
1433 }
1434
1435 // shut the viewport up
1436 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1437 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1438
1439 // I _really_ don't want scrollbars in the beginning
1440 m_vAdjust->lower = 0.0;
1441 m_vAdjust->upper = 1.0;
1442 m_vAdjust->value = 0.0;
1443 m_vAdjust->step_increment = 1.0;
1444 m_vAdjust->page_increment = 1.0;
1445 m_vAdjust->page_size = 5.0;
1446 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1447 m_hAdjust->lower = 0.0;
1448 m_hAdjust->upper = 1.0;
1449 m_hAdjust->value = 0.0;
1450 m_hAdjust->step_increment = 1.0;
1451 m_hAdjust->page_increment = 1.0;
1452 m_hAdjust->page_size = 5.0;
1453 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1454
1455 // these handlers block mouse events to any window during scrolling
1456 // such as motion events and prevent GTK and wxWindows from fighting
1457 // over where the slider should be
1458
1459 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1460 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1461
1462 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1463 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1464
1465 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1466 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1467
1468 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1469 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1470
1471 // these handers het notified when screen updates are required either when
1472 // scrolling or when the window size (and therefore scrollbar configuration)
1473 // has changed
1474
1475 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1476 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1477 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1478 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1479
1480 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1481 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1482 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1483 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1484
1485 gtk_widget_show( m_wxwindow );
1486
1487 if (m_parent) m_parent->AddChild( this );
1488
1489 (m_parent->m_insertCallback)( m_parent, this );
1490
1491 PostCreation();
1492
1493 Show( TRUE );
1494
1495 return TRUE;
1496 }
1497
1498 wxWindow::~wxWindow()
1499 {
1500 m_hasVMT = FALSE;
1501
1502 #if wxUSE_DRAG_AND_DROP
1503 if (m_dropTarget) delete m_dropTarget;
1504 #endif
1505
1506 if (m_toolTip) delete m_toolTip;
1507
1508 if (m_parent) m_parent->RemoveChild( this );
1509 if (m_widget) Show( FALSE );
1510
1511 DestroyChildren();
1512
1513 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1514
1515 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1516
1517 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1518
1519 if (m_widget) gtk_widget_destroy( m_widget );
1520
1521 if (m_cursor) delete m_cursor;
1522
1523 DeleteRelatedConstraints();
1524 if (m_constraints)
1525 {
1526 // This removes any dangling pointers to this window
1527 // in other windows' constraintsInvolvedIn lists.
1528 UnsetConstraints(m_constraints);
1529 delete m_constraints;
1530 m_constraints = (wxLayoutConstraints *) NULL;
1531 }
1532 if (m_windowSizer)
1533 {
1534 delete m_windowSizer;
1535 m_windowSizer = (wxSizer *) NULL;
1536 }
1537 // If this is a child of a sizer, remove self from parent
1538 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1539
1540 // Just in case the window has been Closed, but
1541 // we're then deleting immediately: don't leave
1542 // dangling pointers.
1543 wxPendingDelete.DeleteObject(this);
1544
1545 // Just in case we've loaded a top-level window via
1546 // wxWindow::LoadNativeDialog but we weren't a dialog
1547 // class
1548 wxTopLevelWindows.DeleteObject(this);
1549
1550 if (m_windowValidator) delete m_windowValidator;
1551
1552 if (m_clientObject) delete m_clientObject;
1553 }
1554
1555 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1556 const wxPoint &pos, const wxSize &size,
1557 long style, const wxString &name )
1558 {
1559 wxASSERT_MSG( (!m_needParent) || (parent), "Need complete parent." );
1560
1561 m_widget = (GtkWidget*) NULL;
1562 m_wxwindow = (GtkWidget*) NULL;
1563 m_hasVMT = FALSE;
1564 m_parent = parent;
1565 m_children.DeleteContents( FALSE );
1566
1567 m_width = size.x;
1568 if (m_width == -1) m_width = 20;
1569 m_height = size.y;
1570 if (m_height == -1) m_height = 20;
1571
1572 m_x = (int)pos.x;
1573 m_y = (int)pos.y;
1574
1575 if (!m_needParent) // some reasonable defaults
1576 {
1577 if (m_x == -1)
1578 {
1579 m_x = (gdk_screen_width () - m_width) / 2;
1580 if (m_x < 10) m_x = 10;
1581 }
1582 if (m_y == -1)
1583 {
1584 m_y = (gdk_screen_height () - m_height) / 2;
1585 if (m_y < 10) m_y = 10;
1586 }
1587 }
1588
1589 m_minWidth = -1;
1590 m_minHeight = -1;
1591 m_maxWidth = -1;
1592 m_maxHeight = -1;
1593
1594 m_retCode = 0;
1595
1596 m_eventHandler = this;
1597
1598 m_windowId = id == -1 ? wxNewId() : id;
1599
1600 m_sizeSet = FALSE;
1601
1602 m_cursor = new wxCursor( wxCURSOR_ARROW );
1603 m_font = *wxSWISS_FONT;
1604 m_backgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
1605 m_foregroundColour = *wxBLACK;
1606 m_windowStyle = style;
1607 m_windowName = name;
1608
1609 m_constraints = (wxLayoutConstraints *) NULL;
1610 m_constraintsInvolvedIn = (wxList *) NULL;
1611 m_windowSizer = (wxSizer *) NULL;
1612 m_sizerParent = (wxWindow *) NULL;
1613 m_autoLayout = FALSE;
1614
1615 m_hasScrolling = FALSE;
1616 m_isScrolling = FALSE;
1617 m_hAdjust = (GtkAdjustment *) NULL;
1618 m_vAdjust = (GtkAdjustment *) NULL;
1619 m_oldHorizontalPos = 0.0;
1620 m_oldVerticalPos = 0.0;
1621
1622 m_isShown = FALSE;
1623 m_isEnabled = TRUE;
1624
1625 #if wxUSE_DRAG_AND_DROP
1626 m_dropTarget = (wxDropTarget *) NULL;
1627 #endif
1628 m_resizing = FALSE;
1629 m_windowValidator = (wxValidator *) NULL;
1630 m_scrollGC = (GdkGC*) NULL;
1631 m_widgetStyle = (GtkStyle*) NULL;
1632
1633 m_clientObject = (wxClientData*)NULL;
1634 m_clientData = NULL;
1635
1636 m_isStaticBox = FALSE;
1637 m_toolTip = (wxToolTip*) NULL;
1638 }
1639
1640 void wxWindow::PostCreation()
1641 {
1642 if (m_wxwindow)
1643 {
1644 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1645 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1646
1647 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1648 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1649 }
1650
1651 ConnectWidget( GetConnectWidget() );
1652
1653 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1654
1655 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1656
1657 SetCursor( *wxSTANDARD_CURSOR );
1658
1659 m_hasVMT = TRUE;
1660 }
1661
1662 void wxWindow::ConnectWidget( GtkWidget *widget )
1663 {
1664 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1665 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1666
1667 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1668 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1669
1670 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1671 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1672
1673 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1674 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1675
1676 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1677 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1678
1679 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1680 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1681
1682 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1683 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1684
1685 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1686 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1687
1688 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1689 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1690 }
1691
1692 bool wxWindow::HasVMT()
1693 {
1694 return m_hasVMT;
1695 }
1696
1697 bool wxWindow::Close( bool force )
1698 {
1699 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1700
1701 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1702 event.SetEventObject(this);
1703 event.SetForce(force);
1704
1705 return GetEventHandler()->ProcessEvent(event);
1706 }
1707
1708 bool wxWindow::Destroy()
1709 {
1710 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1711
1712 m_hasVMT = FALSE;
1713 delete this;
1714 return TRUE;
1715 }
1716
1717 bool wxWindow::DestroyChildren()
1718 {
1719 wxNode *node;
1720 while ((node = m_children.First()) != (wxNode *)NULL)
1721 {
1722 wxWindow *child;
1723 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1724 {
1725 delete child;
1726 if (m_children.Member(child)) delete node;
1727 }
1728 }
1729 return TRUE;
1730 }
1731
1732 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1733 {
1734 // are we to set fonts here ?
1735 }
1736
1737 wxPoint wxWindow::GetClientAreaOrigin() const
1738 {
1739 return wxPoint(0,0);
1740 }
1741
1742 void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1743 {
1744 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1745 {
1746 wxPoint pt(GetParent()->GetClientAreaOrigin());
1747 x += pt.x;
1748 y += pt.y;
1749 }
1750 }
1751
1752 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1753 {
1754 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1755 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
1756
1757 if (m_resizing) return; // I don't like recursions
1758 m_resizing = TRUE;
1759
1760 if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
1761 {
1762 // don't set the size for children of wxNotebook, just take the values.
1763 m_x = x;
1764 m_y = y;
1765 m_width = width;
1766 m_height = height;
1767 }
1768 else
1769 {
1770 int old_width = m_width;
1771 int old_height = m_height;
1772
1773 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1774 {
1775 if (x != -1) m_x = x;
1776 if (y != -1) m_y = y;
1777 if (width != -1) m_width = width;
1778 if (height != -1) m_height = height;
1779 }
1780 else
1781 {
1782 m_x = x;
1783 m_y = y;
1784 m_width = width;
1785 m_height = height;
1786 }
1787
1788 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1789 {
1790 if (width == -1) m_width = 80;
1791 }
1792
1793 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1794 {
1795 if (height == -1) m_height = 26;
1796 }
1797
1798 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1799 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1800 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1801 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
1802
1803 wxPoint pt( m_parent->GetClientAreaOrigin() );
1804 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1805
1806 if ((old_width != m_width) || (old_height != m_height))
1807 gtk_widget_set_usize( m_widget, m_width, m_height );
1808 }
1809
1810 m_sizeSet = TRUE;
1811
1812 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1813 event.SetEventObject( this );
1814 GetEventHandler()->ProcessEvent( event );
1815
1816 m_resizing = FALSE;
1817 }
1818
1819 void wxWindow::OnInternalIdle()
1820 {
1821 UpdateWindowUI();
1822 }
1823
1824 void wxWindow::SetSize( int width, int height )
1825 {
1826 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1827 }
1828
1829 void wxWindow::Move( int x, int y )
1830 {
1831 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1832 }
1833
1834 void wxWindow::GetSize( int *width, int *height ) const
1835 {
1836 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1837
1838 if (width) (*width) = m_width;
1839 if (height) (*height) = m_height;
1840 }
1841
1842 void wxWindow::SetClientSize( int width, int height )
1843 {
1844 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1845
1846 if (!m_wxwindow)
1847 {
1848 SetSize( width, height );
1849 }
1850 else
1851 {
1852 int dw = 0;
1853 int dh = 0;
1854
1855 if (!m_hasScrolling)
1856 {
1857 GtkStyleClass *window_class = m_wxwindow->style->klass;
1858
1859 if ((m_windowStyle & wxRAISED_BORDER) ||
1860 (m_windowStyle & wxSUNKEN_BORDER))
1861 {
1862 dw += 2 * window_class->xthickness;
1863 dh += 2 * window_class->ythickness;
1864 }
1865 }
1866 else
1867 {
1868 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1869 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1870
1871 #ifdef NEW_GTK_SCROLL_CODE
1872 GtkWidget *viewport = scroll_window->child;
1873 #else
1874 GtkWidget *viewport = scroll_window->viewport;
1875 #endif
1876
1877 GtkStyleClass *viewport_class = viewport->style->klass;
1878
1879 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1880 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1881
1882 if ((m_windowStyle & wxRAISED_BORDER) ||
1883 (m_windowStyle & wxSUNKEN_BORDER))
1884 {
1885 dw += 2 * viewport_class->xthickness;
1886 dh += 2 * viewport_class->ythickness;
1887 }
1888
1889 if (scroll_window->vscrollbar_visible)
1890 {
1891 dw += vscrollbar->allocation.width;
1892 dw += scroll_class->scrollbar_spacing;
1893 }
1894
1895 if (scroll_window->hscrollbar_visible)
1896 {
1897 dh += hscrollbar->allocation.height;
1898 dw += scroll_class->scrollbar_spacing;
1899 }
1900 }
1901
1902 SetSize( width+dw, height+dh );
1903 }
1904 }
1905
1906 void wxWindow::GetClientSize( int *width, int *height ) const
1907 {
1908 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1909
1910 if (!m_wxwindow)
1911 {
1912 if (width) (*width) = m_width;
1913 if (height) (*height) = m_height;
1914 }
1915 else
1916 {
1917 int dw = 0;
1918 int dh = 0;
1919
1920 if (!m_hasScrolling)
1921 {
1922 GtkStyleClass *window_class = m_wxwindow->style->klass;
1923
1924 if ((m_windowStyle & wxRAISED_BORDER) ||
1925 (m_windowStyle & wxSUNKEN_BORDER))
1926 {
1927 dw += 2 * window_class->xthickness;
1928 dh += 2 * window_class->ythickness;
1929 }
1930 }
1931 else
1932 {
1933 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1934 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1935
1936 #ifdef NEW_GTK_SCROLL_CODE
1937 GtkWidget *viewport = scroll_window->child;
1938 #else
1939 GtkWidget *viewport = scroll_window->viewport;
1940 #endif
1941
1942 GtkStyleClass *viewport_class = viewport->style->klass;
1943
1944 if ((m_windowStyle & wxRAISED_BORDER) ||
1945 (m_windowStyle & wxSUNKEN_BORDER))
1946 {
1947 dw += 2 * viewport_class->xthickness;
1948 dh += 2 * viewport_class->ythickness;
1949 }
1950
1951 if (scroll_window->vscrollbar_visible)
1952 {
1953 // dw += vscrollbar->allocation.width;
1954 dw += 15; // range.slider_width = 11 + 2*2pts edge
1955 dw += scroll_class->scrollbar_spacing;
1956 }
1957
1958 if (scroll_window->hscrollbar_visible)
1959 {
1960 // dh += hscrollbar->allocation.height;
1961 dh += 15;
1962 dh += scroll_class->scrollbar_spacing;
1963 }
1964 }
1965
1966 if (width) (*width) = m_width - dw;
1967 if (height) (*height) = m_height - dh;
1968 }
1969 }
1970
1971 void wxWindow::GetPosition( int *x, int *y ) const
1972 {
1973 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1974
1975 if (x) (*x) = m_x;
1976 if (y) (*y) = m_y;
1977 }
1978
1979 void wxWindow::ClientToScreen( int *x, int *y )
1980 {
1981 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1982
1983 GdkWindow *source = (GdkWindow *) NULL;
1984 if (m_wxwindow)
1985 source = m_wxwindow->window;
1986 else
1987 source = m_widget->window;
1988
1989 int org_x = 0;
1990 int org_y = 0;
1991 gdk_window_get_origin( source, &org_x, &org_y );
1992
1993 if (!m_wxwindow)
1994 {
1995 if (GTK_WIDGET_NO_WINDOW (m_widget))
1996 {
1997 org_x += m_widget->allocation.x;
1998 org_y += m_widget->allocation.y;
1999 }
2000 }
2001
2002 wxPoint pt(GetClientAreaOrigin());
2003 org_x += pt.x;
2004 org_y += pt.y;
2005
2006 if (x) *x += org_x;
2007 if (y) *y += org_y;
2008 }
2009
2010 void wxWindow::ScreenToClient( int *x, int *y )
2011 {
2012 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2013
2014 GdkWindow *source = (GdkWindow *) NULL;
2015 if (m_wxwindow)
2016 source = m_wxwindow->window;
2017 else
2018 source = m_widget->window;
2019
2020 int org_x = 0;
2021 int org_y = 0;
2022 gdk_window_get_origin( source, &org_x, &org_y );
2023
2024 if (!m_wxwindow)
2025 {
2026 if (GTK_WIDGET_NO_WINDOW (m_widget))
2027 {
2028 org_x += m_widget->allocation.x;
2029 org_y += m_widget->allocation.y;
2030 }
2031 }
2032
2033 wxPoint pt(GetClientAreaOrigin());
2034 org_x -= pt.x;
2035 org_y -= pt.y;
2036
2037 if (x) *x -= org_x;
2038 if (y) *y -= org_y;
2039 }
2040
2041 void wxWindow::Centre( int direction )
2042 {
2043 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2044
2045 int x = m_x;
2046 int y = m_y;
2047
2048 if (m_parent)
2049 {
2050 int p_w = 0;
2051 int p_h = 0;
2052 m_parent->GetSize( &p_w, &p_h );
2053 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
2054 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
2055 }
2056 else
2057 {
2058 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
2059 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
2060 }
2061
2062 Move( x, y );
2063 }
2064
2065 void wxWindow::Fit()
2066 {
2067 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2068
2069 int maxX = 0;
2070 int maxY = 0;
2071 wxNode *node = m_children.First();
2072 while (node)
2073 {
2074 wxWindow *win = (wxWindow *)node->Data();
2075 int wx, wy, ww, wh;
2076 win->GetPosition(&wx, &wy);
2077 win->GetSize(&ww, &wh);
2078 if (wx + ww > maxX) maxX = wx + ww;
2079 if (wy + wh > maxY) maxY = wy + wh;
2080
2081 node = node->Next();
2082 }
2083
2084 SetClientSize(maxX + 7, maxY + 14);
2085 }
2086
2087 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
2088 {
2089 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2090
2091 m_minWidth = minW;
2092 m_minHeight = minH;
2093 m_maxWidth = maxW;
2094 m_maxHeight = maxH;
2095 }
2096
2097 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2098 {
2099 // if (GetAutoLayout()) Layout();
2100 }
2101
2102 bool wxWindow::Show( bool show )
2103 {
2104 wxCHECK_MSG( (m_widget != NULL), FALSE, "invalid window" );
2105
2106 if (show)
2107 gtk_widget_show( m_widget );
2108 else
2109 gtk_widget_hide( m_widget );
2110
2111 m_isShown = show;
2112
2113 return TRUE;
2114 }
2115
2116 void wxWindow::Enable( bool enable )
2117 {
2118 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2119
2120 m_isEnabled = enable;
2121
2122 gtk_widget_set_sensitive( m_widget, enable );
2123 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
2124 }
2125
2126 int wxWindow::GetCharHeight() const
2127 {
2128 wxCHECK_MSG( (m_widget != NULL), 12, "invalid window" );
2129
2130 wxCHECK_MSG( m_font.Ok(), 12, "invalid font" );
2131
2132 GdkFont *font = m_font.GetInternalFont( 1.0 );
2133
2134 return font->ascent + font->descent;
2135 }
2136
2137 int wxWindow::GetCharWidth() const
2138 {
2139 wxCHECK_MSG( (m_widget != NULL), 8, "invalid window" );
2140
2141 wxCHECK_MSG( m_font.Ok(), 8, "invalid font" );
2142
2143 GdkFont *font = m_font.GetInternalFont( 1.0 );
2144
2145 return gdk_string_width( font, "H" );
2146 }
2147
2148 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
2149 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
2150 {
2151 wxFont fontToUse = m_font;
2152 if (theFont) fontToUse = *theFont;
2153
2154 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
2155
2156 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2157 if (x) (*x) = gdk_string_width( font, string );
2158 if (y) (*y) = font->ascent + font->descent;
2159 if (descent) (*descent) = font->descent;
2160 if (externalLeading) (*externalLeading) = 0; // ??
2161 }
2162
2163 void wxWindow::MakeModal( bool modal )
2164 {
2165 return;
2166
2167 // Disable all other windows
2168 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
2169 {
2170 wxNode *node = wxTopLevelWindows.First();
2171 while (node)
2172 {
2173 wxWindow *win = (wxWindow *)node->Data();
2174 if (win != this) win->Enable(!modal);
2175
2176 node = node->Next();
2177 }
2178 }
2179 }
2180
2181 void wxWindow::OnKeyDown( wxKeyEvent &event )
2182 {
2183 event.SetEventType( wxEVT_CHAR );
2184
2185 if (!GetEventHandler()->ProcessEvent( event ))
2186 {
2187 event.Skip();
2188 }
2189 }
2190
2191 void wxWindow::SetFocus()
2192 {
2193 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2194
2195 GtkWidget *connect_widget = GetConnectWidget();
2196 if (connect_widget)
2197 {
2198 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2199 {
2200 gtk_widget_grab_focus (connect_widget);
2201 }
2202 else if (GTK_IS_CONTAINER(connect_widget))
2203 {
2204 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2205 }
2206 else
2207 {
2208 }
2209 }
2210 }
2211
2212 wxWindow *wxWindow::FindFocus()
2213 {
2214 return g_focusWindow;
2215 }
2216
2217 bool wxWindow::AcceptsFocus() const
2218 {
2219 return IsEnabled() && IsShown() && m_acceptsFocus;
2220 }
2221
2222 bool wxWindow::OnClose()
2223 {
2224 return TRUE;
2225 }
2226
2227 void wxWindow::AddChild( wxWindow *child )
2228 {
2229 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2230 wxCHECK_RET( (child != NULL), "invalid child" );
2231
2232 m_children.Append( child );
2233 }
2234
2235 wxWindow *wxWindow::ReParent( wxWindow *newParent )
2236 {
2237 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, "invalid window" );
2238
2239 wxWindow *oldParent = GetParent();
2240
2241 if (oldParent) oldParent->RemoveChild( this );
2242
2243 gtk_widget_unparent( m_widget );
2244
2245 if (newParent)
2246 {
2247 newParent->AddChild( this );
2248 (newParent->m_insertCallback)( newParent, this );
2249 }
2250
2251 return oldParent;
2252 }
2253
2254 void wxWindow::RemoveChild( wxWindow *child )
2255 {
2256 m_children.DeleteObject( child );
2257 child->m_parent = (wxWindow *) NULL;
2258 }
2259
2260 void wxWindow::SetReturnCode( int retCode )
2261 {
2262 m_retCode = retCode;
2263 }
2264
2265 int wxWindow::GetReturnCode()
2266 {
2267 return m_retCode;
2268 }
2269
2270 void wxWindow::Raise()
2271 {
2272 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2273
2274 if (m_widget) gdk_window_raise( m_widget->window );
2275 }
2276
2277 void wxWindow::Lower()
2278 {
2279 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2280
2281 if (m_widget) gdk_window_lower( m_widget->window );
2282 }
2283
2284 wxEvtHandler *wxWindow::GetEventHandler() const
2285 {
2286 return m_eventHandler;
2287 }
2288
2289 void wxWindow::SetEventHandler( wxEvtHandler *handler )
2290 {
2291 m_eventHandler = handler;
2292 }
2293
2294 void wxWindow::PushEventHandler(wxEvtHandler *handler)
2295 {
2296 handler->SetNextHandler(GetEventHandler());
2297 SetEventHandler(handler);
2298 }
2299
2300 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
2301 {
2302 if (GetEventHandler())
2303 {
2304 wxEvtHandler *handlerA = GetEventHandler();
2305 wxEvtHandler *handlerB = handlerA->GetNextHandler();
2306 handlerA->SetNextHandler((wxEvtHandler *) NULL);
2307 SetEventHandler(handlerB);
2308 if (deleteHandler)
2309 {
2310 delete handlerA;
2311 return (wxEvtHandler*) NULL;
2312 }
2313 else
2314 return handlerA;
2315 }
2316 else
2317 return (wxEvtHandler *) NULL;
2318 }
2319
2320 wxValidator *wxWindow::GetValidator()
2321 {
2322 return m_windowValidator;
2323 }
2324
2325 void wxWindow::SetValidator( const wxValidator& validator )
2326 {
2327 if (m_windowValidator) delete m_windowValidator;
2328 m_windowValidator = validator.Clone();
2329 if (m_windowValidator) m_windowValidator->SetWindow(this);
2330 }
2331
2332 void wxWindow::SetClientObject( wxClientData *data )
2333 {
2334 if (m_clientObject) delete m_clientObject;
2335 m_clientObject = data;
2336 }
2337
2338 wxClientData *wxWindow::GetClientObject()
2339 {
2340 return m_clientObject;
2341 }
2342
2343 void wxWindow::SetClientData( void *data )
2344 {
2345 m_clientData = data;
2346 }
2347
2348 void *wxWindow::GetClientData()
2349 {
2350 return m_clientData;
2351 }
2352
2353 bool wxWindow::IsBeingDeleted()
2354 {
2355 return FALSE;
2356 }
2357
2358 void wxWindow::SetId( wxWindowID id )
2359 {
2360 m_windowId = id;
2361 }
2362
2363 wxWindowID wxWindow::GetId() const
2364 {
2365 return m_windowId;
2366 }
2367
2368 void wxWindow::SetCursor( const wxCursor &cursor )
2369 {
2370 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2371
2372 if (cursor.Ok())
2373 {
2374 if (cursor == *m_cursor) return;
2375 *m_cursor = cursor;
2376 }
2377 else
2378 {
2379 *m_cursor = *wxSTANDARD_CURSOR;
2380 }
2381
2382 if ((m_widget) && (m_widget->window))
2383 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
2384
2385 if ((m_wxwindow) && (m_wxwindow->window))
2386 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
2387 }
2388
2389 void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2390 {
2391 // TODO
2392 }
2393
2394 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
2395 {
2396 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2397
2398 if (eraseBackground && m_wxwindow && m_wxwindow->window)
2399 {
2400 if (rect)
2401 {
2402 gdk_window_clear_area( m_wxwindow->window,
2403 rect->x, rect->y,
2404 rect->width,
2405 rect->height );
2406 }
2407 else
2408 {
2409 Clear();
2410 }
2411 }
2412
2413 if (!rect)
2414 {
2415 if (m_wxwindow)
2416 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2417 else
2418 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
2419 }
2420 else
2421 {
2422 GdkRectangle gdk_rect;
2423 gdk_rect.x = rect->x;
2424 gdk_rect.y = rect->y;
2425 gdk_rect.width = rect->width;
2426 gdk_rect.height = rect->height;
2427
2428 if (m_wxwindow)
2429 gtk_widget_draw( m_wxwindow, &gdk_rect );
2430 else
2431 gtk_widget_draw( m_widget, &gdk_rect );
2432 }
2433 }
2434
2435 wxRegion wxWindow::GetUpdateRegion() const
2436 {
2437 return m_updateRegion;
2438 }
2439
2440 bool wxWindow::IsExposed( int x, int y) const
2441 {
2442 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
2443 }
2444
2445 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2446 {
2447 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
2448 }
2449
2450 bool wxWindow::IsExposed( const wxPoint& pt ) const
2451 {
2452 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
2453 }
2454
2455 bool wxWindow::IsExposed( const wxRect& rect ) const
2456 {
2457 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
2458 }
2459
2460 void wxWindow::Clear()
2461 {
2462 wxCHECK_RET( m_widget != NULL, "invalid window" );
2463
2464 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
2465 }
2466
2467 void wxWindow::SetToolTip( const wxString &tip )
2468 {
2469 SetToolTip( new wxToolTip( tip ) );
2470 }
2471
2472 void wxWindow::SetToolTip( wxToolTip *tip )
2473 {
2474 if (m_toolTip) delete m_toolTip;
2475
2476 m_toolTip = tip;
2477
2478 if (m_toolTip) m_toolTip->Create( GetConnectWidget() );
2479 }
2480
2481 wxToolTip& wxWindow::GetToolTip()
2482 {
2483 if (!m_toolTip)
2484 wxLogError( "No tooltip set." );
2485
2486 return *m_toolTip;
2487 }
2488
2489 wxColour wxWindow::GetBackgroundColour() const
2490 {
2491 return m_backgroundColour;
2492 }
2493
2494 void wxWindow::SetBackgroundColour( const wxColour &colour )
2495 {
2496 wxCHECK_RET( m_widget != NULL, "invalid window" );
2497
2498 if (m_backgroundColour == colour) return;
2499
2500 m_backgroundColour = colour;
2501 if (!m_backgroundColour.Ok()) return;
2502
2503 if (m_wxwindow)
2504 {
2505 GdkWindow *window = m_wxwindow->window;
2506 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2507 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2508 gdk_window_clear( window );
2509 }
2510
2511 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2512 if (sysbg.Red() == colour.Red() &&
2513 sysbg.Green() == colour.Green() &&
2514 sysbg.Blue() == colour.Blue())
2515 {
2516 m_backgroundColour = wxNullColour;
2517 ApplyWidgetStyle();
2518 m_backgroundColour = sysbg;
2519 }
2520 else
2521 {
2522 ApplyWidgetStyle();
2523 }
2524 }
2525
2526 wxColour wxWindow::GetForegroundColour() const
2527 {
2528 return m_foregroundColour;
2529 }
2530
2531 void wxWindow::SetForegroundColour( const wxColour &colour )
2532 {
2533 wxCHECK_RET( m_widget != NULL, "invalid window" );
2534
2535 if (m_foregroundColour == colour) return;
2536
2537 m_foregroundColour = colour;
2538 if (!m_foregroundColour.Ok()) return;
2539
2540 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2541 if (sysbg.Red() == colour.Red() &&
2542 sysbg.Green() == colour.Green() &&
2543 sysbg.Blue() == colour.Blue())
2544 {
2545 m_backgroundColour = wxNullColour;
2546 ApplyWidgetStyle();
2547 m_backgroundColour = sysbg;
2548 }
2549 else
2550 {
2551 ApplyWidgetStyle();
2552 }
2553 }
2554
2555 GtkStyle *wxWindow::GetWidgetStyle()
2556 {
2557 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2558
2559 m_widgetStyle =
2560 gtk_style_copy(
2561 gtk_widget_get_style( m_widget ) );
2562
2563 return m_widgetStyle;
2564 }
2565
2566 void wxWindow::SetWidgetStyle()
2567 {
2568 GtkStyle *style = GetWidgetStyle();
2569
2570 gdk_font_unref( style->font );
2571 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2572
2573 if (m_foregroundColour.Ok())
2574 {
2575 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2576 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2577 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2578 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2579 }
2580
2581 if (m_backgroundColour.Ok())
2582 {
2583 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2584 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2585 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2586 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2587 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2588 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2589 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2590 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2591 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2592 }
2593 }
2594
2595 void wxWindow::ApplyWidgetStyle()
2596 {
2597 }
2598
2599 bool wxWindow::Validate()
2600 {
2601 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2602
2603 wxNode *node = m_children.First();
2604 while (node)
2605 {
2606 wxWindow *child = (wxWindow *)node->Data();
2607 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2608 {
2609 return FALSE;
2610 }
2611 node = node->Next();
2612 }
2613 return TRUE;
2614 }
2615
2616 bool wxWindow::TransferDataToWindow()
2617 {
2618 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2619
2620 wxNode *node = m_children.First();
2621 while (node)
2622 {
2623 wxWindow *child = (wxWindow *)node->Data();
2624 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2625 !child->GetValidator()->TransferToWindow() )
2626 {
2627 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2628 return FALSE;
2629 }
2630 node = node->Next();
2631 }
2632 return TRUE;
2633 }
2634
2635 bool wxWindow::TransferDataFromWindow()
2636 {
2637 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2638
2639 wxNode *node = m_children.First();
2640 while (node)
2641 {
2642 wxWindow *child = (wxWindow *)node->Data();
2643 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2644 {
2645 return FALSE;
2646 }
2647 node = node->Next();
2648 }
2649 return TRUE;
2650 }
2651
2652 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2653 {
2654 m_acceleratorTable = accel;
2655 }
2656
2657 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2658 {
2659 TransferDataToWindow();
2660 }
2661
2662 void wxWindow::InitDialog()
2663 {
2664 wxCHECK_RET( m_widget != NULL, "invalid window" );
2665
2666 wxInitDialogEvent event(GetId());
2667 event.SetEventObject( this );
2668 GetEventHandler()->ProcessEvent(event);
2669 }
2670
2671 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2672 {
2673 menu->SetInvokingWindow( win );
2674 wxNode *node = menu->m_items.First();
2675 while (node)
2676 {
2677 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2678 if (menuitem->IsSubMenu())
2679 {
2680 SetInvokingWindow( menuitem->GetSubMenu(), win );
2681 }
2682 node = node->Next();
2683 }
2684 }
2685
2686 static gint gs_pop_x = 0;
2687 static gint gs_pop_y = 0;
2688
2689 static void pop_pos_callback( GtkMenu *menu, gint *x, gint *y, wxWindow *win )
2690 {
2691 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2692 *x = gs_pop_x;
2693 *y = gs_pop_y;
2694 }
2695
2696 bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
2697 {
2698 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2699
2700 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2701
2702 SetInvokingWindow( menu, this );
2703
2704 gs_pop_x = x;
2705 gs_pop_y = y;
2706
2707 gtk_menu_popup(
2708 GTK_MENU(menu->m_menu),
2709 (GtkWidget *) NULL, // parent menu shell
2710 (GtkWidget *) NULL, // parent menu item
2711 (GtkMenuPositionFunc) pop_pos_callback,
2712 (gpointer) this, // client data
2713 0, // button used to activate it
2714 0 //gs_timeLastClick // the time of activation
2715 );
2716 return TRUE;
2717 }
2718
2719 #if wxUSE_DRAG_AND_DROP
2720
2721 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2722 {
2723 wxCHECK_RET( m_widget != NULL, "invalid window" );
2724
2725 GtkWidget *dnd_widget = GetConnectWidget();
2726
2727 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2728
2729 if (m_dropTarget) delete m_dropTarget;
2730 m_dropTarget = dropTarget;
2731
2732 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2733 }
2734
2735 wxDropTarget *wxWindow::GetDropTarget() const
2736 {
2737 return m_dropTarget;
2738 }
2739
2740 #endif
2741
2742 GtkWidget* wxWindow::GetConnectWidget()
2743 {
2744 GtkWidget *connect_widget = m_widget;
2745 if (m_wxwindow) connect_widget = m_wxwindow;
2746
2747 return connect_widget;
2748 }
2749
2750 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2751 {
2752 if (m_wxwindow) return (window == m_wxwindow->window);
2753 return (window == m_widget->window);
2754 }
2755
2756 void wxWindow::SetFont( const wxFont &font )
2757 {
2758 wxCHECK_RET( m_widget != NULL, "invalid window" );
2759
2760 if (((wxFont*)&font)->Ok())
2761 m_font = font;
2762 else
2763 m_font = *wxSWISS_FONT;
2764
2765 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2766 if (sysbg.Red() == m_backgroundColour.Red() &&
2767 sysbg.Green() == m_backgroundColour.Green() &&
2768 sysbg.Blue() == m_backgroundColour.Blue())
2769 {
2770 m_backgroundColour = wxNullColour;
2771 ApplyWidgetStyle();
2772 m_backgroundColour = sysbg;
2773 }
2774 else
2775 {
2776 ApplyWidgetStyle();
2777 }
2778 }
2779
2780 void wxWindow::SetWindowStyleFlag( long flag )
2781 {
2782 m_windowStyle = flag;
2783 }
2784
2785 long wxWindow::GetWindowStyleFlag() const
2786 {
2787 return m_windowStyle;
2788 }
2789
2790 void wxWindow::CaptureMouse()
2791 {
2792 wxCHECK_RET( m_widget != NULL, "invalid window" );
2793
2794 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2795
2796 GtkWidget *connect_widget = GetConnectWidget();
2797 gtk_grab_add( connect_widget );
2798 gdk_pointer_grab( connect_widget->window, FALSE,
2799 (GdkEventMask)
2800 (GDK_BUTTON_PRESS_MASK |
2801 GDK_BUTTON_RELEASE_MASK |
2802 GDK_POINTER_MOTION_MASK),
2803 (GdkWindow *) NULL,
2804 (GdkCursor *) NULL,
2805 GDK_CURRENT_TIME );
2806 g_capturing = TRUE;
2807 }
2808
2809 void wxWindow::ReleaseMouse()
2810 {
2811 wxCHECK_RET( m_widget != NULL, "invalid window" );
2812
2813 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2814
2815 GtkWidget *connect_widget = GetConnectWidget();
2816 gtk_grab_remove( connect_widget );
2817 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2818 g_capturing = FALSE;
2819 }
2820
2821 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2822 {
2823 }
2824
2825 wxString wxWindow::GetTitle() const
2826 {
2827 return (wxString&)m_windowName;
2828 }
2829
2830 wxString wxWindow::GetLabel() const
2831 {
2832 return GetTitle();
2833 }
2834
2835 void wxWindow::SetName( const wxString &name )
2836 {
2837 m_windowName = name;
2838 }
2839
2840 wxString wxWindow::GetName() const
2841 {
2842 return (wxString&)m_windowName;
2843 }
2844
2845 bool wxWindow::IsShown() const
2846 {
2847 return m_isShown;
2848 }
2849
2850 bool wxWindow::IsRetained()
2851 {
2852 return FALSE;
2853 }
2854
2855 wxWindow *wxWindow::FindWindow( long id )
2856 {
2857 if (id == m_windowId) return this;
2858 wxNode *node = m_children.First();
2859 while (node)
2860 {
2861 wxWindow *child = (wxWindow*)node->Data();
2862 wxWindow *res = child->FindWindow( id );
2863 if (res) return res;
2864 node = node->Next();
2865 }
2866 return (wxWindow *) NULL;
2867 }
2868
2869 wxWindow *wxWindow::FindWindow( const wxString& name )
2870 {
2871 if (name == m_windowName) return this;
2872 wxNode *node = m_children.First();
2873 while (node)
2874 {
2875 wxWindow *child = (wxWindow*)node->Data();
2876 wxWindow *res = child->FindWindow( name );
2877 if (res) return res;
2878 node = node->Next();
2879 }
2880 return (wxWindow *) NULL;
2881 }
2882
2883 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2884 int range, bool refresh )
2885 {
2886 wxCHECK_RET( m_widget != NULL, "invalid window" );
2887
2888 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2889
2890 m_hasScrolling = TRUE;
2891
2892 if (orient == wxHORIZONTAL)
2893 {
2894 float fpos = (float)pos;
2895 float frange = (float)range;
2896 float fthumb = (float)thumbVisible;
2897 if (fpos > frange-fthumb) fpos = frange-fthumb;
2898 if (fpos < 0.0) fpos = 0.0;
2899
2900 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2901 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2902 {
2903 SetScrollPos( orient, pos, refresh );
2904 return;
2905 }
2906
2907 m_oldHorizontalPos = fpos;
2908
2909 m_hAdjust->lower = 0.0;
2910 m_hAdjust->upper = frange;
2911 m_hAdjust->value = fpos;
2912 m_hAdjust->step_increment = 1.0;
2913 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2914 m_hAdjust->page_size = fthumb;
2915 }
2916 else
2917 {
2918 float fpos = (float)pos;
2919 float frange = (float)range;
2920 float fthumb = (float)thumbVisible;
2921 if (fpos > frange-fthumb) fpos = frange-fthumb;
2922 if (fpos < 0.0) fpos = 0.0;
2923
2924 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2925 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2926 {
2927 SetScrollPos( orient, pos, refresh );
2928 return;
2929 }
2930
2931 m_oldVerticalPos = fpos;
2932
2933 m_vAdjust->lower = 0.0;
2934 m_vAdjust->upper = frange;
2935 m_vAdjust->value = fpos;
2936 m_vAdjust->step_increment = 1.0;
2937 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2938 m_vAdjust->page_size = fthumb;
2939 }
2940
2941 if (m_wxwindow->window)
2942 {
2943 if (orient == wxHORIZONTAL)
2944 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2945 else
2946 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2947
2948 gtk_widget_set_usize( m_widget, m_width, m_height );
2949 }
2950 }
2951
2952 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2953 {
2954 wxCHECK_RET( m_widget != NULL, "invalid window" );
2955
2956 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2957
2958 if (orient == wxHORIZONTAL)
2959 {
2960 float fpos = (float)pos;
2961 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2962 if (fpos < 0.0) fpos = 0.0;
2963 m_oldHorizontalPos = fpos;
2964
2965 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2966 m_hAdjust->value = fpos;
2967 }
2968 else
2969 {
2970 float fpos = (float)pos;
2971 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2972 if (fpos < 0.0) fpos = 0.0;
2973 m_oldVerticalPos = fpos;
2974
2975 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2976 m_vAdjust->value = fpos;
2977 }
2978
2979 if (!m_isScrolling)
2980 {
2981 if (m_wxwindow->window)
2982 {
2983 if (orient == wxHORIZONTAL)
2984 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2985 else
2986 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2987 }
2988 }
2989 }
2990
2991 int wxWindow::GetScrollThumb( int orient ) const
2992 {
2993 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
2994
2995 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
2996
2997 if (orient == wxHORIZONTAL)
2998 return (int)(m_hAdjust->page_size+0.5);
2999 else
3000 return (int)(m_vAdjust->page_size+0.5);
3001 }
3002
3003 int wxWindow::GetScrollPos( int orient ) const
3004 {
3005 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3006
3007 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3008
3009 if (orient == wxHORIZONTAL)
3010 return (int)(m_hAdjust->value+0.5);
3011 else
3012 return (int)(m_vAdjust->value+0.5);
3013 }
3014
3015 int wxWindow::GetScrollRange( int orient ) const
3016 {
3017 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3018
3019 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3020
3021 if (orient == wxHORIZONTAL)
3022 return (int)(m_hAdjust->upper+0.5);
3023 else
3024 return (int)(m_vAdjust->upper+0.5);
3025 }
3026
3027 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
3028 {
3029 wxCHECK_RET( m_widget != NULL, "invalid window" );
3030
3031 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
3032
3033 int cw = 0;
3034 int ch = 0;
3035 GetClientSize( &cw, &ch );
3036
3037 int w = cw - abs(dx);
3038 int h = ch - abs(dy);
3039 if ((h < 0) || (w < 0))
3040 {
3041 Refresh();
3042 return;
3043 }
3044 int s_x = 0;
3045 int s_y = 0;
3046 if (dx < 0) s_x = -dx;
3047 if (dy < 0) s_y = -dy;
3048 int d_x = 0;
3049 int d_y = 0;
3050 if (dx > 0) d_x = dx;
3051 if (dy > 0) d_y = dy;
3052
3053 if (!m_scrollGC)
3054 {
3055 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3056 gdk_gc_set_exposures( m_scrollGC, TRUE );
3057 }
3058
3059 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3060 m_wxwindow->window, s_x, s_y, w, h );
3061
3062 wxRect rect;
3063 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3064 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3065 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3066 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3067
3068 Refresh( TRUE, &rect );
3069 }
3070
3071 //-------------------------------------------------------------------------------------
3072 // Layout
3073 //-------------------------------------------------------------------------------------
3074
3075 wxLayoutConstraints *wxWindow::GetConstraints() const
3076 {
3077 return m_constraints;
3078 }
3079
3080 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
3081 {
3082 if (m_constraints)
3083 {
3084 UnsetConstraints(m_constraints);
3085 delete m_constraints;
3086 }
3087 m_constraints = constraints;
3088 if (m_constraints)
3089 {
3090 // Make sure other windows know they're part of a 'meaningful relationship'
3091 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3092 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3093 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3094 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3095 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3096 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3097 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3098 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3099 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3100 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3101 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3102 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3103 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3104 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3105 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3106 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3107 }
3108 ;
3109 }
3110 ;
3111
3112 void wxWindow::SetAutoLayout( bool autoLayout )
3113 {
3114 m_autoLayout = autoLayout;
3115 }
3116
3117 bool wxWindow::GetAutoLayout() const
3118 {
3119 return m_autoLayout;
3120 }
3121
3122 wxSizer *wxWindow::GetSizer() const
3123 {
3124 return m_windowSizer;
3125 }
3126
3127 void wxWindow::SetSizerParent( wxWindow *win )
3128 {
3129 m_sizerParent = win;
3130 }
3131
3132 wxWindow *wxWindow::GetSizerParent() const
3133 {
3134 return m_sizerParent;
3135 }
3136
3137 // This removes any dangling pointers to this window
3138 // in other windows' constraintsInvolvedIn lists.
3139 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3140 {
3141 if (c)
3142 {
3143 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3144 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3145 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3146 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3147 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3148 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3149 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3150 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3151 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3152 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3153 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3154 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3155 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3156 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3157 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3158 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3159 }
3160 }
3161
3162 // Back-pointer to other windows we're involved with, so if we delete
3163 // this window, we must delete any constraints we're involved with.
3164 void wxWindow::AddConstraintReference(wxWindow *otherWin)
3165 {
3166 if (!m_constraintsInvolvedIn)
3167 m_constraintsInvolvedIn = new wxList;
3168 if (!m_constraintsInvolvedIn->Member(otherWin))
3169 m_constraintsInvolvedIn->Append(otherWin);
3170 }
3171
3172 // REMOVE back-pointer to other windows we're involved with.
3173 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3174 {
3175 if (m_constraintsInvolvedIn)
3176 m_constraintsInvolvedIn->DeleteObject(otherWin);
3177 }
3178
3179 // Reset any constraints that mention this window
3180 void wxWindow::DeleteRelatedConstraints()
3181 {
3182 if (m_constraintsInvolvedIn)
3183 {
3184 wxNode *node = m_constraintsInvolvedIn->First();
3185 while (node)
3186 {
3187 wxWindow *win = (wxWindow *)node->Data();
3188 wxNode *next = node->Next();
3189 wxLayoutConstraints *constr = win->GetConstraints();
3190
3191 // Reset any constraints involving this window
3192 if (constr)
3193 {
3194 constr->left.ResetIfWin((wxWindow *)this);
3195 constr->top.ResetIfWin((wxWindow *)this);
3196 constr->right.ResetIfWin((wxWindow *)this);
3197 constr->bottom.ResetIfWin((wxWindow *)this);
3198 constr->width.ResetIfWin((wxWindow *)this);
3199 constr->height.ResetIfWin((wxWindow *)this);
3200 constr->centreX.ResetIfWin((wxWindow *)this);
3201 constr->centreY.ResetIfWin((wxWindow *)this);
3202 }
3203 delete node;
3204 node = next;
3205 }
3206 delete m_constraintsInvolvedIn;
3207 m_constraintsInvolvedIn = (wxList *) NULL;
3208 }
3209 }
3210
3211 void wxWindow::SetSizer(wxSizer *sizer)
3212 {
3213 m_windowSizer = sizer;
3214 if (sizer)
3215 sizer->SetSizerParent((wxWindow *)this);
3216 }
3217
3218 /*
3219 * New version
3220 */
3221
3222 bool wxWindow::Layout()
3223 {
3224 if (GetConstraints())
3225 {
3226 int w, h;
3227 GetClientSize(&w, &h);
3228 GetConstraints()->width.SetValue(w);
3229 GetConstraints()->height.SetValue(h);
3230 }
3231
3232 // If top level (one sizer), evaluate the sizer's constraints.
3233 if (GetSizer())
3234 {
3235 int noChanges;
3236 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3237 GetSizer()->LayoutPhase1(&noChanges);
3238 GetSizer()->LayoutPhase2(&noChanges);
3239 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3240 return TRUE;
3241 }
3242 else
3243 {
3244 // Otherwise, evaluate child constraints
3245 ResetConstraints(); // Mark all constraints as unevaluated
3246 DoPhase(1); // Just one phase need if no sizers involved
3247 DoPhase(2);
3248 SetConstraintSizes(); // Recursively set the real window sizes
3249 }
3250 return TRUE;
3251 }
3252
3253
3254 // Do a phase of evaluating constraints:
3255 // the default behaviour. wxSizers may do a similar
3256 // thing, but also impose their own 'constraints'
3257 // and order the evaluation differently.
3258 bool wxWindow::LayoutPhase1(int *noChanges)
3259 {
3260 wxLayoutConstraints *constr = GetConstraints();
3261 if (constr)
3262 {
3263 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3264 }
3265 else
3266 return TRUE;
3267 }
3268
3269 bool wxWindow::LayoutPhase2(int *noChanges)
3270 {
3271 *noChanges = 0;
3272
3273 // Layout children
3274 DoPhase(1);
3275 DoPhase(2);
3276 return TRUE;
3277 }
3278
3279 // Do a phase of evaluating child constraints
3280 bool wxWindow::DoPhase(int phase)
3281 {
3282 int noIterations = 0;
3283 int maxIterations = 500;
3284 int noChanges = 1;
3285 int noFailures = 0;
3286 wxList succeeded;
3287 while ((noChanges > 0) && (noIterations < maxIterations))
3288 {
3289 noChanges = 0;
3290 noFailures = 0;
3291 wxNode *node = m_children.First();
3292 while (node)
3293 {
3294 wxWindow *child = (wxWindow *)node->Data();
3295 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3296 {
3297 wxLayoutConstraints *constr = child->GetConstraints();
3298 if (constr)
3299 {
3300 if (succeeded.Member(child))
3301 {
3302 }
3303 else
3304 {
3305 int tempNoChanges = 0;
3306 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3307 noChanges += tempNoChanges;
3308 if (success)
3309 {
3310 succeeded.Append(child);
3311 }
3312 }
3313 }
3314 }
3315 node = node->Next();
3316 }
3317 noIterations ++;
3318 }
3319 return TRUE;
3320 }
3321
3322 void wxWindow::ResetConstraints()
3323 {
3324 wxLayoutConstraints *constr = GetConstraints();
3325 if (constr)
3326 {
3327 constr->left.SetDone(FALSE);
3328 constr->top.SetDone(FALSE);
3329 constr->right.SetDone(FALSE);
3330 constr->bottom.SetDone(FALSE);
3331 constr->width.SetDone(FALSE);
3332 constr->height.SetDone(FALSE);
3333 constr->centreX.SetDone(FALSE);
3334 constr->centreY.SetDone(FALSE);
3335 }
3336 wxNode *node = m_children.First();
3337 while (node)
3338 {
3339 wxWindow *win = (wxWindow *)node->Data();
3340 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3341 win->ResetConstraints();
3342 node = node->Next();
3343 }
3344 }
3345
3346 // Need to distinguish between setting the 'fake' size for
3347 // windows and sizers, and setting the real values.
3348 void wxWindow::SetConstraintSizes(bool recurse)
3349 {
3350 wxLayoutConstraints *constr = GetConstraints();
3351 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3352 constr->width.GetDone() && constr->height.GetDone())
3353 {
3354 int x = constr->left.GetValue();
3355 int y = constr->top.GetValue();
3356 int w = constr->width.GetValue();
3357 int h = constr->height.GetValue();
3358
3359 // If we don't want to resize this window, just move it...
3360 if ((constr->width.GetRelationship() != wxAsIs) ||
3361 (constr->height.GetRelationship() != wxAsIs))
3362 {
3363 // Calls Layout() recursively. AAAGH. How can we stop that.
3364 // Simply take Layout() out of non-top level OnSizes.
3365 SizerSetSize(x, y, w, h);
3366 }
3367 else
3368 {
3369 SizerMove(x, y);
3370 }
3371 }
3372 else if (constr)
3373 {
3374 char *windowClass = this->GetClassInfo()->GetClassName();
3375
3376 wxString winName;
3377 if (GetName() == "")
3378 winName = "unnamed";
3379 else
3380 winName = GetName();
3381 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3382 (const char *)windowClass,
3383 (const char *)winName);
3384 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3385 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3386 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3387 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3388 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3389 }
3390
3391 if (recurse)
3392 {
3393 wxNode *node = m_children.First();
3394 while (node)
3395 {
3396 wxWindow *win = (wxWindow *)node->Data();
3397 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3398 win->SetConstraintSizes();
3399 node = node->Next();
3400 }
3401 }
3402 }
3403
3404 // This assumes that all sizers are 'on' the same
3405 // window, i.e. the parent of this window.
3406 void wxWindow::TransformSizerToActual(int *x, int *y) const
3407 {
3408 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
3409 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
3410 return;
3411
3412 int xp, yp;
3413 m_sizerParent->GetPosition(&xp, &yp);
3414 m_sizerParent->TransformSizerToActual(&xp, &yp);
3415 *x += xp;
3416 *y += yp;
3417 }
3418
3419 void wxWindow::SizerSetSize(int x, int y, int w, int h)
3420 {
3421 int xx = x;
3422 int yy = y;
3423 TransformSizerToActual(&xx, &yy);
3424 SetSize(xx, yy, w, h);
3425 }
3426
3427 void wxWindow::SizerMove(int x, int y)
3428 {
3429 int xx = x;
3430 int yy = y;
3431 TransformSizerToActual(&xx, &yy);
3432 Move(xx, yy);
3433 }
3434
3435 // Only set the size/position of the constraint (if any)
3436 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
3437 {
3438 wxLayoutConstraints *constr = GetConstraints();
3439 if (constr)
3440 {
3441 if (x != -1)
3442 {
3443 constr->left.SetValue(x);
3444 constr->left.SetDone(TRUE);
3445 }
3446 if (y != -1)
3447 {
3448 constr->top.SetValue(y);
3449 constr->top.SetDone(TRUE);
3450 }
3451 if (w != -1)
3452 {
3453 constr->width.SetValue(w);
3454 constr->width.SetDone(TRUE);
3455 }
3456 if (h != -1)
3457 {
3458 constr->height.SetValue(h);
3459 constr->height.SetDone(TRUE);
3460 }
3461 }
3462 }
3463
3464 void wxWindow::MoveConstraint(int x, int y)
3465 {
3466 wxLayoutConstraints *constr = GetConstraints();
3467 if (constr)
3468 {
3469 if (x != -1)
3470 {
3471 constr->left.SetValue(x);
3472 constr->left.SetDone(TRUE);
3473 }
3474 if (y != -1)
3475 {
3476 constr->top.SetValue(y);
3477 constr->top.SetDone(TRUE);
3478 }
3479 }
3480 }
3481
3482 void wxWindow::GetSizeConstraint(int *w, int *h) const
3483 {
3484 wxLayoutConstraints *constr = GetConstraints();
3485 if (constr)
3486 {
3487 *w = constr->width.GetValue();
3488 *h = constr->height.GetValue();
3489 }
3490 else
3491 GetSize(w, h);
3492 }
3493
3494 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3495 {
3496 wxLayoutConstraints *constr = GetConstraints();
3497 if (constr)
3498 {
3499 *w = constr->width.GetValue();
3500 *h = constr->height.GetValue();
3501 }
3502 else
3503 GetClientSize(w, h);
3504 }
3505
3506 void wxWindow::GetPositionConstraint(int *x, int *y) const
3507 {
3508 wxLayoutConstraints *constr = GetConstraints();
3509 if (constr)
3510 {
3511 *x = constr->left.GetValue();
3512 *y = constr->top.GetValue();
3513 }
3514 else
3515 GetPosition(x, y);
3516 }
3517