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