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