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