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