]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/window.cpp
wxTopLevelWindows is now a wxWindowList, better compatibility with the old
[wxWidgets.git] / src / gtk1 / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: window.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "window.h"
13 #endif
14
15 #include "wx/defs.h"
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/layout.h"
21 #include "wx/utils.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24
25 #if wxUSE_DRAG_AND_DROP
26 #include "wx/dnd.h"
27 #endif
28
29 #if wxUSE_TOOLTIPS
30 #include "wx/tooltip.h"
31 #endif
32
33 #include "wx/menu.h"
34 #include "wx/statusbr.h"
35 #include "wx/intl.h"
36 #include "wx/settings.h"
37 #include "wx/log.h"
38
39 #include <math.h>
40
41 #include "gdk/gdk.h"
42 #include "gtk/gtk.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
46
47 //-----------------------------------------------------------------------------
48 // documentation on internals
49 //-----------------------------------------------------------------------------
50
51 /*
52 I have been asked several times about writing some documentation about
53 the GTK port of wxWindows, especially its internal structures. Obviously,
54 you cannot understand wxGTK without knowing a little about the GTK, but
55 some more information about what the wxWindow, which is the base class
56 for all other window classes, does seems required as well.
57
58 What does wxWindow do? It contains the common interface for the following
59 jobs of its descendants:
60
61 1) Define the rudimentary behaviour common to all window classes, such as
62 resizing, intercepting user input (so as to make it possible to use these
63 events for special purposes in a derived class), window names etc.
64
65 2) Provide the possibility to contain and manage children, if the derived
66 class is allowed to contain children, which holds true for those window
67 classes which do not display a native GTK widget. To name them, these
68 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
69 work classes are a special case and are handled a bit differently from
70 the rest. The same holds true for the wxNotebook class.
71
72 3) Provide the possibility to draw into a client area of a window. This,
73 too, only holds true for classes that do not display a native GTK widget
74 as above.
75
76 4) Provide the entire mechanism for scrolling widgets. This actual inter-
77 face for this is usually in wxScrolledWindow, but the GTK implementation
78 is in this class.
79
80 5) A multitude of helper or extra methods for special purposes, such as
81 Drag'n'Drop, managing validators etc.
82
83 Normally one might expect, that one wxWindows window would always correspond
84 to one GTK widget. Under GTK, there is no such allround widget that has all
85 the functionality. Moreover, the GTK defines a client area as a different
86 widget from the actual widget you are handling. Last but not least some
87 special classes (e.g. wxFrame) handle different categories of widgets and
88 still have the possibility to draw something in the client area.
89 It was therefore required to write a special purpose GTK widget, that would
90 represent a client area in the sense of wxWindows capable to do the jobs
91 2), 3) and 4). I have written this class and it resides in win_gtk.c of
92 this directory.
93
94 All windows must have a widget, with which they interact with other under-
95 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
96 thw wxWindow class has a member variable called m_widget which holds a
97 pointer to this widget. When the window class represents a GTK native widget,
98 this is (in most cases) the only GTK widget the class manages. E.g. the
99 wxStatitText class handles only a GtkLabel widget a pointer to which you
100 can find in m_widget (defined in wxWindow)
101
102 When the class has a client area for drawing into and for containing children
103 it has to handle the client area widget (of the type GtkMyFixed, defined in
104 win_gtk.c), but there could be any number of widgets, handled by a class
105 The common rule for all windows is only, that the widget that interacts with
106 the rest of GTK must be referenced in m_widget and all other widgets must be
107 children of this widget on the GTK level. The top-most widget, which also
108 represents the client area, must be in the m_wxwindow field and must be of
109 the type GtkMyFixed.
110
111 As I said, the window classes that display a GTK native widget only have
112 one widget, so in the case of e.g. the wxButton class m_widget holds a
113 pointer to a GtkButton widget. But windows with client areas (for drawing
114 and children) have a m_widget field that is a pointer to a GtkScrolled-
115 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
116 one is (in the GTK sense) a child of the GtkScrolledWindow.
117
118 If the m_wxwindow field is set, then all input to this widget is inter-
119 cepted and sent to the wxWindows class. If not, all input to the widget
120 that gets pointed to by m_widget gets intercepted and sent to the class.
121
122 */
123
124 //-------------------------------------------------------------------------
125 // conditional compilation
126 //-------------------------------------------------------------------------
127
128 #if (GTK_MINOR_VERSION == 1)
129 #if (GTK_MICRO_VERSION >= 5)
130 #define NEW_GTK_SCROLL_CODE
131 #endif
132 #endif
133
134 //-----------------------------------------------------------------------------
135 // (debug)
136 //-----------------------------------------------------------------------------
137
138 #ifdef __WXDEBUG__
139
140 static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
141 GdkEvent *WXUNUSED(event),
142 const char *name )
143 {
144 printf( "FOCUS NOW AT: " );
145 printf( name );
146 printf( "\n" );
147
148 return FALSE;
149 }
150
151 void debug_focus_in( GtkWidget* widget, const char* name, const char *window )
152 {
153 return;
154
155 wxString tmp = name;
156 tmp += " FROM ";
157 tmp += window;
158
159 char *s = new char[tmp.Length()+1];
160
161 strcpy( s, WXSTRINGCAST tmp );
162
163 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
164 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
165 }
166
167 #endif
168
169 //-----------------------------------------------------------------------------
170 // data
171 //-----------------------------------------------------------------------------
172
173 extern wxList wxPendingDelete;
174 extern bool g_blockEventsOnDrag;
175 extern bool g_blockEventsOnScroll;
176 static bool g_capturing = FALSE;
177 static wxWindow *g_focusWindow = (wxWindow*) NULL;
178
179 // hack: we need something to pass to gtk_menu_popup, so we store the time of
180 // the last click here
181 static guint32 gs_timeLastClick = 0;
182
183 //-----------------------------------------------------------------------------
184 // "expose_event" (of m_wxwindow, not of m_widget)
185 //-----------------------------------------------------------------------------
186
187 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
188 {
189 if (!win->HasVMT()) return;
190
191 win->m_updateRegion.Union( gdk_event->area.x,
192 gdk_event->area.y,
193 gdk_event->area.width,
194 gdk_event->area.height );
195
196 if (gdk_event->count > 0) return;
197
198 /*
199 printf( "OnExpose from " );
200 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
201 printf( win->GetClassInfo()->GetClassName() );
202 printf( ".\n" );
203 */
204
205 wxPaintEvent event( win->GetId() );
206 event.SetEventObject( win );
207 win->GetEventHandler()->ProcessEvent( event );
208
209 win->m_updateRegion.Clear();
210 }
211
212 //-----------------------------------------------------------------------------
213 // "draw" (of m_wxwindow, not of m_widget)
214 //-----------------------------------------------------------------------------
215
216 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
217 {
218 if (!win->HasVMT()) return;
219
220 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
221
222 wxPaintEvent event( win->GetId() );
223 event.SetEventObject( win );
224 win->GetEventHandler()->ProcessEvent( event );
225
226 win->m_updateRegion.Clear();
227 }
228
229 //-----------------------------------------------------------------------------
230 // "key_press_event" from any window
231 //-----------------------------------------------------------------------------
232
233 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
234 {
235 if (!win->HasVMT()) return FALSE;
236 if (g_blockEventsOnDrag) return FALSE;
237
238 /*
239 printf( "OnKeyPress from " );
240 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
241 printf( win->GetClassInfo()->GetClassName() );
242 printf( ".\n" );
243 */
244
245 long key_code = 0;
246 switch (gdk_event->keyval)
247 {
248 case GDK_BackSpace: key_code = WXK_BACK; break;
249 case GDK_ISO_Left_Tab:
250 case GDK_KP_Tab:
251 case GDK_Tab: key_code = WXK_TAB; break;
252 case GDK_Linefeed: key_code = WXK_RETURN; break;
253 case GDK_Clear: key_code = WXK_CLEAR; break;
254 case GDK_Return: key_code = WXK_RETURN; break;
255 case GDK_Pause: key_code = WXK_PAUSE; break;
256 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
257 case GDK_Escape: key_code = WXK_ESCAPE; break;
258 case GDK_Delete: key_code = WXK_DELETE; break;
259 case GDK_Home: key_code = WXK_HOME; break;
260 case GDK_Left: key_code = WXK_LEFT; break;
261 case GDK_Up: key_code = WXK_UP; break;
262 case GDK_Right: key_code = WXK_RIGHT; break;
263 case GDK_Down: key_code = WXK_DOWN; break;
264 case GDK_Prior: key_code = WXK_PRIOR; break;
265 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
266 case GDK_Next: key_code = WXK_NEXT; break;
267 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
268 case GDK_End: key_code = WXK_END; break;
269 case GDK_Begin: key_code = WXK_HOME; break;
270 case GDK_Select: key_code = WXK_SELECT; break;
271 case GDK_Print: key_code = WXK_PRINT; break;
272 case GDK_Execute: key_code = WXK_EXECUTE; break;
273 case GDK_Insert: key_code = WXK_INSERT; break;
274 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
275 case GDK_KP_Enter: key_code = WXK_RETURN; break;
276 case GDK_KP_Home: key_code = WXK_HOME; break;
277 case GDK_KP_Left: key_code = WXK_LEFT; break;
278 case GDK_KP_Up: key_code = WXK_UP; break;
279 case GDK_KP_Right: key_code = WXK_RIGHT; break;
280 case GDK_KP_Down: key_code = WXK_DOWN; break;
281 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
282 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
283 case GDK_KP_Next: key_code = WXK_NEXT; break;
284 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
285 case GDK_KP_End: key_code = WXK_END; break;
286 case GDK_KP_Begin: key_code = WXK_HOME; break;
287 case GDK_KP_Insert: key_code = WXK_INSERT; break;
288 case GDK_KP_Delete: key_code = WXK_DELETE; break;
289 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
290 case GDK_KP_Add: key_code = WXK_ADD; break;
291 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
292 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
293 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
294 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
295 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
296 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
297 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
298 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
299 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
300 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
301 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
302 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
303 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
304 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
305 case GDK_F1: key_code = WXK_F1; break;
306 case GDK_F2: key_code = WXK_F2; break;
307 case GDK_F3: key_code = WXK_F3; break;
308 case GDK_F4: key_code = WXK_F4; break;
309 case GDK_F5: key_code = WXK_F5; break;
310 case GDK_F6: key_code = WXK_F6; break;
311 case GDK_F7: key_code = WXK_F7; break;
312 case GDK_F8: key_code = WXK_F8; break;
313 case GDK_F9: key_code = WXK_F9; break;
314 case GDK_F10: key_code = WXK_F10; break;
315 case GDK_F11: key_code = WXK_F11; break;
316 case GDK_F12: key_code = WXK_F12; break;
317 default:
318 {
319 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
320 key_code = gdk_event->keyval;
321 }
322 }
323
324 if (!key_code) return FALSE;
325
326 wxKeyEvent event( wxEVT_KEY_DOWN );
327 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
328 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
329 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
330 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
331 event.m_keyCode = key_code;
332 event.m_x = 0;
333 event.m_y = 0;
334 event.SetEventObject( win );
335
336 bool ret = win->GetEventHandler()->ProcessEvent( event );
337
338 if (!ret)
339 {
340 wxWindow *ancestor = win;
341 while (ancestor)
342 {
343 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
344 if (command != -1)
345 {
346 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
347 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
348 break;
349 }
350 ancestor = ancestor->GetParent();
351 }
352 }
353
354 // win is a control: tab can be propagated up
355 if ( (!ret) &&
356 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
357 ((win->m_windowStyle & wxTE_PROCESS_TAB) == 0))
358 {
359 wxNavigationKeyEvent new_event;
360 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
361 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
362 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
363 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
364 new_event.SetCurrentFocus( win );
365 ret = win->GetEventHandler()->ProcessEvent( new_event );
366 }
367
368 if ( (!ret) &&
369 (gdk_event->keyval == GDK_Escape) )
370 {
371 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
372 new_event.SetEventObject( win );
373 ret = win->GetEventHandler()->ProcessEvent( new_event );
374 }
375
376 /*
377 Damn, I forgot why this didn't work, but it didn't work.
378
379 // win is a panel: up can be propagated to the panel
380 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
381 (gdk_event->keyval == GDK_Up))
382 {
383 win->m_parent->SetFocus();
384 ret = TRUE;
385 }
386
387 // win is a panel: left/right can be propagated to the panel
388 if ((!ret) && (win->m_wxwindow) &&
389 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
390 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
391 {
392 wxNavigationKeyEvent new_event;
393 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
394 new_event.SetCurrentFocus( win );
395 ret = win->GetEventHandler()->ProcessEvent( new_event );
396 }
397 */
398
399 if (ret)
400 {
401 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
402 }
403
404 return ret;
405 }
406
407 //-----------------------------------------------------------------------------
408 // "key_release_event" from any window
409 //-----------------------------------------------------------------------------
410
411 static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
412 {
413 if (!win->HasVMT()) return FALSE;
414 if (g_blockEventsOnDrag) return FALSE;
415
416 /*
417 printf( "OnKeyRelease from " );
418 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
419 printf( win->GetClassInfo()->GetClassName() );
420 printf( ".\n" );
421 */
422
423 long key_code = 0;
424 switch (gdk_event->keyval)
425 {
426 case GDK_BackSpace: key_code = WXK_BACK; break;
427 case GDK_ISO_Left_Tab:
428 case GDK_KP_Tab:
429 case GDK_Tab: key_code = WXK_TAB; break;
430 case GDK_Linefeed: key_code = WXK_RETURN; break;
431 case GDK_Clear: key_code = WXK_CLEAR; break;
432 case GDK_Return: key_code = WXK_RETURN; break;
433 case GDK_Pause: key_code = WXK_PAUSE; break;
434 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
435 case GDK_Escape: key_code = WXK_ESCAPE; break;
436 case GDK_Delete: key_code = WXK_DELETE; break;
437 case GDK_Home: key_code = WXK_HOME; break;
438 case GDK_Left: key_code = WXK_LEFT; break;
439 case GDK_Up: key_code = WXK_UP; break;
440 case GDK_Right: key_code = WXK_RIGHT; break;
441 case GDK_Down: key_code = WXK_DOWN; break;
442 case GDK_Prior: key_code = WXK_PRIOR; break;
443 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
444 case GDK_Next: key_code = WXK_NEXT; break;
445 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
446 case GDK_End: key_code = WXK_END; break;
447 case GDK_Begin: key_code = WXK_HOME; break;
448 case GDK_Select: key_code = WXK_SELECT; break;
449 case GDK_Print: key_code = WXK_PRINT; break;
450 case GDK_Execute: key_code = WXK_EXECUTE; break;
451 case GDK_Insert: key_code = WXK_INSERT; break;
452 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
453 case GDK_KP_Enter: key_code = WXK_RETURN; break;
454 case GDK_KP_Home: key_code = WXK_HOME; break;
455 case GDK_KP_Left: key_code = WXK_LEFT; break;
456 case GDK_KP_Up: key_code = WXK_UP; break;
457 case GDK_KP_Right: key_code = WXK_RIGHT; break;
458 case GDK_KP_Down: key_code = WXK_DOWN; break;
459 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
460 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
461 case GDK_KP_Next: key_code = WXK_NEXT; break;
462 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
463 case GDK_KP_End: key_code = WXK_END; break;
464 case GDK_KP_Begin: key_code = WXK_HOME; break;
465 case GDK_KP_Insert: key_code = WXK_INSERT; break;
466 case GDK_KP_Delete: key_code = WXK_DELETE; break;
467 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
468 case GDK_KP_Add: key_code = WXK_ADD; break;
469 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
470 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
471 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
472 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
473 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
474 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
475 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
476 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
477 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
478 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
479 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
480 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
481 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
482 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
483 case GDK_F1: key_code = WXK_F1; break;
484 case GDK_F2: key_code = WXK_F2; break;
485 case GDK_F3: key_code = WXK_F3; break;
486 case GDK_F4: key_code = WXK_F4; break;
487 case GDK_F5: key_code = WXK_F5; break;
488 case GDK_F6: key_code = WXK_F6; break;
489 case GDK_F7: key_code = WXK_F7; break;
490 case GDK_F8: key_code = WXK_F8; break;
491 case GDK_F9: key_code = WXK_F9; break;
492 case GDK_F10: key_code = WXK_F10; break;
493 case GDK_F11: key_code = WXK_F11; break;
494 case GDK_F12: key_code = WXK_F12; break;
495 default:
496 {
497 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
498 key_code = gdk_event->keyval;
499 }
500 }
501
502 if (!key_code) return FALSE;
503
504 wxKeyEvent event( wxEVT_KEY_UP );
505 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
506 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
507 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
508 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
509 event.m_keyCode = key_code;
510 event.m_x = 0;
511 event.m_y = 0;
512 event.SetEventObject( win );
513
514 bool ret = win->GetEventHandler()->ProcessEvent( event );
515
516 if (ret)
517 {
518 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
519 }
520
521 return ret;
522 }
523
524 //-----------------------------------------------------------------------------
525 // "button_press_event"
526 //-----------------------------------------------------------------------------
527
528 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
529 {
530 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
531
532 if (g_blockEventsOnDrag) return TRUE;
533 if (g_blockEventsOnScroll) return TRUE;
534
535 if (win->m_wxwindow)
536 {
537 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
538 {
539 gtk_widget_grab_focus (win->m_wxwindow);
540
541 /*
542 printf( "GrabFocus from " );
543 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
544 printf( win->GetClassInfo()->GetClassName() );
545 printf( ".\n" );
546 */
547
548 }
549 }
550
551 if (!win->HasVMT()) return TRUE;
552
553 /*
554 printf( "OnButtonPress from " );
555 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
556 printf( win->GetClassInfo()->GetClassName() );
557 printf( ".\n" );
558 */
559
560 wxEventType event_type = wxEVT_LEFT_DOWN;
561
562 if (gdk_event->button == 1)
563 {
564 switch (gdk_event->type)
565 {
566 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
567 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
568 default: break;
569 }
570 }
571 else if (gdk_event->button == 2)
572 {
573 switch (gdk_event->type)
574 {
575 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
576 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
577 default: break;
578 }
579 }
580 else if (gdk_event->button == 3)
581 {
582 switch (gdk_event->type)
583 {
584 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
585 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
586 default: break;
587 }
588 }
589
590 wxMouseEvent event( event_type );
591 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
592 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
593 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
594 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
595 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
596 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
597 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
598
599 event.m_x = (long)gdk_event->x;
600 event.m_y = (long)gdk_event->y;
601
602 // Some control don't have their own X window and thus cannot get
603 // any events.
604
605 if (!g_capturing)
606 {
607 wxNode *node = win->GetChildren().First();
608 while (node)
609 {
610 wxWindow *child = (wxWindow*)node->Data();
611
612 if (child->m_isStaticBox)
613 {
614 // wxStaticBox is transparent in the box itself
615 int x = event.m_x;
616 int y = event.m_y;
617 int xx1 = child->m_x;
618 int yy1 = child->m_y;
619 int xx2 = child->m_x + child->m_width;
620 int yy2 = child->m_x + child->m_height;
621
622 // left
623 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
624 // right
625 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
626 // top
627 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
628 // bottom
629 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
630 {
631 win = child;
632 event.m_x -= child->m_x;
633 event.m_y -= child->m_y;
634 break;
635 }
636
637 }
638 else
639 {
640 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
641 (child->m_x <= event.m_x) &&
642 (child->m_y <= event.m_y) &&
643 (child->m_x+child->m_width >= event.m_x) &&
644 (child->m_y+child->m_height >= event.m_y))
645 {
646 win = child;
647 event.m_x -= child->m_x;
648 event.m_y -= child->m_y;
649 break;
650 }
651 }
652 node = node->Next();
653 }
654 }
655
656 wxPoint pt(win->GetClientAreaOrigin());
657 event.m_x -= pt.x;
658 event.m_y -= pt.y;
659
660 event.SetEventObject( win );
661
662 gs_timeLastClick = gdk_event->time;
663
664 if (win->GetEventHandler()->ProcessEvent( event ))
665 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
666
667 return TRUE;
668 }
669
670 //-----------------------------------------------------------------------------
671 // "button_release_event"
672 //-----------------------------------------------------------------------------
673
674 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
675 {
676 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
677
678 if (g_blockEventsOnDrag) return TRUE;
679 if (g_blockEventsOnScroll) return TRUE;
680
681 if (!win->HasVMT()) return TRUE;
682
683 /*
684 printf( "OnButtonRelease from " );
685 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
686 printf( win->GetClassInfo()->GetClassName() );
687 printf( ".\n" );
688 */
689
690 wxEventType event_type = wxEVT_NULL;
691
692 switch (gdk_event->button)
693 {
694 case 1: event_type = wxEVT_LEFT_UP; break;
695 case 2: event_type = wxEVT_MIDDLE_UP; break;
696 case 3: event_type = wxEVT_RIGHT_UP; break;
697 }
698
699 wxMouseEvent event( event_type );
700 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
701 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
702 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
703 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
704 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
705 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
706 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
707 event.m_x = (long)gdk_event->x;
708 event.m_y = (long)gdk_event->y;
709
710 // Some control don't have their own X window and thus cannot get
711 // any events.
712
713 if (!g_capturing)
714 {
715 wxNode *node = win->GetChildren().First();
716 while (node)
717 {
718 wxWindow *child = (wxWindow*)node->Data();
719
720 if (child->m_isStaticBox)
721 {
722 // wxStaticBox is transparent in the box itself
723 int x = event.m_x;
724 int y = event.m_y;
725 int xx1 = child->m_x;
726 int yy1 = child->m_y;
727 int xx2 = child->m_x + child->m_width;
728 int yy2 = child->m_x + child->m_height;
729
730 // left
731 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
732 // right
733 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
734 // top
735 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
736 // bottom
737 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
738 {
739 win = child;
740 event.m_x -= child->m_x;
741 event.m_y -= child->m_y;
742 break;
743 }
744
745 }
746 else
747 {
748 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
749 (child->m_x <= event.m_x) &&
750 (child->m_y <= event.m_y) &&
751 (child->m_x+child->m_width >= event.m_x) &&
752 (child->m_y+child->m_height >= event.m_y))
753 {
754 win = child;
755 event.m_x -= child->m_x;
756 event.m_y -= child->m_y;
757 break;
758 }
759 }
760 node = node->Next();
761 }
762 }
763
764 wxPoint pt(win->GetClientAreaOrigin());
765 event.m_x -= pt.x;
766 event.m_y -= pt.y;
767
768 event.SetEventObject( win );
769
770 if (win->GetEventHandler()->ProcessEvent( event ))
771 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
772
773 return TRUE;
774 }
775
776 //-----------------------------------------------------------------------------
777 // "motion_notify_event"
778 //-----------------------------------------------------------------------------
779
780 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
781 {
782 if (gdk_event->is_hint)
783 {
784 int x = 0;
785 int y = 0;
786 GdkModifierType state;
787 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
788 gdk_event->x = x;
789 gdk_event->y = y;
790 gdk_event->state = state;
791 }
792
793 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
794
795 if (g_blockEventsOnDrag) return TRUE;
796 if (g_blockEventsOnScroll) return TRUE;
797
798 if (!win->HasVMT()) return TRUE;
799
800 /*
801 printf( "OnMotion from " );
802 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
803 printf( win->GetClassInfo()->GetClassName() );
804 printf( ".\n" );
805 */
806
807 wxMouseEvent event( wxEVT_MOTION );
808 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
809 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
810 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
811 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
812 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
813 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
814 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
815
816 event.m_x = (long)gdk_event->x;
817 event.m_y = (long)gdk_event->y;
818
819 // Some control don't have their own X window and thus cannot get
820 // any events.
821
822 if (!g_capturing)
823 {
824 wxNode *node = win->GetChildren().First();
825 while (node)
826 {
827 wxWindow *child = (wxWindow*)node->Data();
828
829 if (child->m_isStaticBox)
830 {
831 // wxStaticBox is transparent in the box itself
832 int x = event.m_x;
833 int y = event.m_y;
834 int xx1 = child->m_x;
835 int yy1 = child->m_y;
836 int xx2 = child->m_x + child->m_width;
837 int yy2 = child->m_x + child->m_height;
838
839 // left
840 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
841 // right
842 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
843 // top
844 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
845 // bottom
846 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
847 {
848 win = child;
849 event.m_x -= child->m_x;
850 event.m_y -= child->m_y;
851 break;
852 }
853
854 }
855 else
856 {
857 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
858 (child->m_x <= event.m_x) &&
859 (child->m_y <= event.m_y) &&
860 (child->m_x+child->m_width >= event.m_x) &&
861 (child->m_y+child->m_height >= event.m_y))
862 {
863 win = child;
864 event.m_x -= child->m_x;
865 event.m_y -= child->m_y;
866 break;
867 }
868 }
869 node = node->Next();
870 }
871 }
872
873 wxPoint pt(win->GetClientAreaOrigin());
874 event.m_x -= pt.x;
875 event.m_y -= pt.y;
876
877 event.SetEventObject( win );
878
879 if (win->GetEventHandler()->ProcessEvent( event ))
880 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
881
882 return TRUE;
883 }
884
885 //-----------------------------------------------------------------------------
886 // "focus_in_event"
887 //-----------------------------------------------------------------------------
888
889 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
890 {
891 if (g_blockEventsOnDrag) return TRUE;
892
893 g_focusWindow = win;
894
895 if (win->m_wxwindow)
896 {
897 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
898 {
899 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
900 /*
901 printf( "SetFocus flag from " );
902 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
903 printf( win->GetClassInfo()->GetClassName() );
904 printf( ".\n" );
905 */
906 }
907 }
908
909 if (!win->HasVMT()) return TRUE;
910
911 /*
912 printf( "OnSetFocus from " );
913 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
914 printf( win->GetClassInfo()->GetClassName() );
915 printf( " " );
916 printf( WXSTRINGCAST win->GetLabel() );
917 printf( ".\n" );
918 */
919
920 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
921 event.SetEventObject( win );
922
923 if (win->GetEventHandler()->ProcessEvent( event ))
924 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
925
926 return TRUE;
927 }
928
929 //-----------------------------------------------------------------------------
930 // "focus_out_event"
931 //-----------------------------------------------------------------------------
932
933 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
934 {
935 if (g_blockEventsOnDrag) return TRUE;
936 if (win->m_wxwindow)
937 {
938 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
939 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
940 }
941
942 if (!win->HasVMT()) return TRUE;
943
944 /*
945 printf( "OnKillFocus from " );
946 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
947 printf( win->GetClassInfo()->GetClassName() );
948 printf( ".\n" );
949 */
950
951 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
952 event.SetEventObject( win );
953
954 if (win->GetEventHandler()->ProcessEvent( event ))
955 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
956
957 return TRUE;
958 }
959
960 //-----------------------------------------------------------------------------
961 // "enter_notify_event"
962 //-----------------------------------------------------------------------------
963
964 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
965 {
966 if (g_blockEventsOnDrag) return TRUE;
967
968 if ((widget->window) && (win->m_cursor))
969 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
970
971 if (widget->window != gdk_event->window) return TRUE;
972
973 if (!win->HasVMT()) return TRUE;
974
975 /*
976 printf( "OnEnter from " );
977 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
978 printf( win->GetClassInfo()->GetClassName() );
979 printf( ".\n" );
980 */
981
982 wxMouseEvent event( wxEVT_ENTER_WINDOW );
983 event.SetEventObject( win );
984
985 int x = 0;
986 int y = 0;
987 GdkModifierType state = (GdkModifierType)0;
988
989 gdk_window_get_pointer( widget->window, &x, &y, &state );
990
991 event.m_shiftDown = (state & GDK_SHIFT_MASK);
992 event.m_controlDown = (state & GDK_CONTROL_MASK);
993 event.m_altDown = (state & GDK_MOD1_MASK);
994 event.m_metaDown = (state & GDK_MOD2_MASK);
995 event.m_leftDown = (state & GDK_BUTTON1_MASK);
996 event.m_middleDown = (state & GDK_BUTTON2_MASK);
997 event.m_rightDown = (state & GDK_BUTTON3_MASK);
998
999 event.m_x = (long)x;
1000 event.m_y = (long)y;
1001
1002 wxPoint pt(win->GetClientAreaOrigin());
1003 event.m_x -= pt.x;
1004 event.m_y -= pt.y;
1005
1006 if (win->GetEventHandler()->ProcessEvent( event ))
1007 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
1008
1009 return TRUE;
1010 }
1011
1012 //-----------------------------------------------------------------------------
1013 // "leave_notify_event"
1014 //-----------------------------------------------------------------------------
1015
1016 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1017 {
1018 if (g_blockEventsOnDrag) return TRUE;
1019
1020 if ((widget->window) && (win->m_cursor))
1021 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
1022
1023 if (widget->window != gdk_event->window) return TRUE;
1024
1025 if (!win->HasVMT()) return TRUE;
1026
1027 /*
1028 printf( "OnLeave from " );
1029 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1030 printf( win->GetClassInfo()->GetClassName() );
1031 printf( ".\n" );
1032 */
1033
1034 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
1035 event.SetEventObject( win );
1036
1037 int x = 0;
1038 int y = 0;
1039 GdkModifierType state = (GdkModifierType)0;
1040
1041 gdk_window_get_pointer( widget->window, &x, &y, &state );
1042
1043 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1044 event.m_controlDown = (state & GDK_CONTROL_MASK);
1045 event.m_altDown = (state & GDK_MOD1_MASK);
1046 event.m_metaDown = (state & GDK_MOD2_MASK);
1047 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1048 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1049 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1050
1051 event.m_x = (long)x;
1052 event.m_y = (long)y;
1053
1054 wxPoint pt(win->GetClientAreaOrigin());
1055 event.m_x -= pt.x;
1056 event.m_y -= pt.y;
1057
1058 if (win->GetEventHandler()->ProcessEvent( event ))
1059 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
1060
1061 return TRUE;
1062 }
1063
1064 //-----------------------------------------------------------------------------
1065 // "value_changed" from m_vAdjust
1066 //-----------------------------------------------------------------------------
1067
1068 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1069 {
1070 if (g_blockEventsOnDrag) return;
1071
1072 /*
1073 printf( "OnVScroll from " );
1074 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1075 printf( win->GetClassInfo()->GetClassName() );
1076 printf( ".\n" );
1077 */
1078
1079 if (!win->HasVMT()) return;
1080
1081 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
1082 if (fabs(diff) < 0.2) return;
1083 win->m_oldVerticalPos = win->m_vAdjust->value;
1084
1085 wxEventType command = wxEVT_NULL;
1086
1087 float line_step = win->m_vAdjust->step_increment;
1088 float page_step = win->m_vAdjust->page_increment;
1089
1090 if (win->m_isScrolling)
1091 {
1092 command = wxEVT_SCROLL_THUMBTRACK;
1093 }
1094 else
1095 {
1096 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1097 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
1098 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1099 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1100 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1101 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1102 else command = wxEVT_SCROLL_THUMBTRACK;
1103 }
1104
1105 int value = (int)(win->m_vAdjust->value+0.5);
1106
1107 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1108 event.SetEventObject( win );
1109 win->GetEventHandler()->ProcessEvent( event );
1110 }
1111
1112 //-----------------------------------------------------------------------------
1113 // "value_changed" from m_hAdjust
1114 //-----------------------------------------------------------------------------
1115
1116 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1117 {
1118 if (g_blockEventsOnDrag) return;
1119
1120 /*
1121 printf( "OnHScroll from " );
1122 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1123 printf( win->GetClassInfo()->GetClassName() );
1124 printf( ".\n" );
1125 */
1126
1127 if (!win->HasVMT()) return;
1128
1129 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
1130 if (fabs(diff) < 0.2) return;
1131 win->m_oldHorizontalPos = win->m_hAdjust->value;
1132
1133 wxEventType command = wxEVT_NULL;
1134
1135 float line_step = win->m_hAdjust->step_increment;
1136 float page_step = win->m_hAdjust->page_increment;
1137
1138 if (win->m_isScrolling)
1139 {
1140 command = wxEVT_SCROLL_THUMBTRACK;
1141 }
1142 else
1143 {
1144 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1145 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
1146 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1147 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1148 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1149 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1150 else command = wxEVT_SCROLL_THUMBTRACK;
1151 }
1152
1153 int value = (int)(win->m_hAdjust->value+0.5);
1154
1155 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1156 event.SetEventObject( win );
1157 win->GetEventHandler()->ProcessEvent( event );
1158 }
1159
1160 //-----------------------------------------------------------------------------
1161 // "changed" from m_vAdjust
1162 //-----------------------------------------------------------------------------
1163
1164 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1165 {
1166 if (g_blockEventsOnDrag) return;
1167
1168 /*
1169 printf( "OnVScroll change from " );
1170 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1171 printf( win->GetClassInfo()->GetClassName() );
1172 printf( ".\n" );
1173 */
1174
1175 if (!win->HasVMT()) return;
1176
1177 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1178 int value = (int)(win->m_vAdjust->value+0.5);
1179
1180 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1181 event.SetEventObject( win );
1182 win->GetEventHandler()->ProcessEvent( event );
1183 }
1184
1185 //-----------------------------------------------------------------------------
1186 // "changed" from m_hAdjust
1187 //-----------------------------------------------------------------------------
1188
1189 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
1190 {
1191 if (g_blockEventsOnDrag) return;
1192
1193 /*
1194 printf( "OnHScroll change from " );
1195 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1196 printf( win->GetClassInfo()->GetClassName() );
1197 printf( ".\n" );
1198 */
1199
1200 if (!win->HasVMT()) return;
1201
1202 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1203 int value = (int)(win->m_hAdjust->value+0.5);
1204
1205 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1206 event.SetEventObject( win );
1207 win->GetEventHandler()->ProcessEvent( event );
1208 }
1209
1210 //-----------------------------------------------------------------------------
1211 // "button_press_event" from scrollbar
1212 //-----------------------------------------------------------------------------
1213
1214 static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1215 GdkEventButton *WXUNUSED(gdk_event),
1216 wxWindow *win )
1217 {
1218 // don't test here as we can release the mouse while being over
1219 // a different window then the slider
1220 //
1221 // if (gdk_event->window != widget->slider) return FALSE;
1222
1223 win->m_isScrolling = TRUE;
1224 g_blockEventsOnScroll = TRUE;
1225
1226 return FALSE;
1227 }
1228
1229 //-----------------------------------------------------------------------------
1230 // "button_release_event" from scrollbar
1231 //-----------------------------------------------------------------------------
1232
1233 static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1234 GdkEventButton *WXUNUSED(gdk_event),
1235 wxWindow *win )
1236 {
1237
1238 // don't test here as we can release the mouse while being over
1239 // a different window then the slider
1240 //
1241 // if (gdk_event->window != widget->slider) return FALSE;
1242
1243 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
1244
1245 if (widget == GTK_RANGE(s_window->vscrollbar))
1246 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
1247 else
1248 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
1249
1250 win->m_isScrolling = FALSE;
1251 g_blockEventsOnScroll = FALSE;
1252
1253 return FALSE;
1254 }
1255
1256 //-----------------------------------------------------------------------------
1257 // InsertChild for wxWindow.
1258 //-----------------------------------------------------------------------------
1259
1260 /* Callback for wxWindow. This very strange beast has to be used because
1261 * C++ has no virtual methods in a constructor. We have to emulate a
1262 * virtual function here as wxNotebook requires a different way to insert
1263 * a child in it. I had opted for creating a wxNotebookPage window class
1264 * which would have made this superfluous (such in the MDI window system),
1265 * but no-one was listening to me... */
1266
1267 static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1268 {
1269 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1270 GTK_WIDGET(child->m_widget),
1271 child->m_x,
1272 child->m_y );
1273
1274 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
1275 child->m_width,
1276 child->m_height );
1277
1278 if (wxIS_KIND_OF(parent,wxFrame))
1279 {
1280 parent->m_sizeSet = FALSE;
1281 }
1282
1283 if (parent->m_windowStyle & wxTAB_TRAVERSAL)
1284 {
1285 /* we now allow a window to get the focus as long as it
1286 doesn't have any children. */
1287 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
1288 }
1289 }
1290
1291 //-----------------------------------------------------------------------------
1292 // global functions
1293 //-----------------------------------------------------------------------------
1294
1295 wxWindow* wxGetActiveWindow()
1296 {
1297 return g_focusWindow;
1298 }
1299
1300 //-----------------------------------------------------------------------------
1301 // wxWindow
1302 //-----------------------------------------------------------------------------
1303
1304 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
1305
1306 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
1307 EVT_SIZE(wxWindow::OnSize)
1308 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
1309 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
1310 EVT_KEY_DOWN(wxWindow::OnKeyDown)
1311 END_EVENT_TABLE()
1312
1313 void wxWindow::Init()
1314 {
1315 m_isWindow = TRUE;
1316
1317 m_widget = (GtkWidget *) NULL;
1318 m_wxwindow = (GtkWidget *) NULL;
1319 m_parent = (wxWindow *) NULL;
1320 m_children.DeleteContents( FALSE );
1321
1322 m_x = 0;
1323 m_y = 0;
1324 m_width = 0;
1325 m_height = 0;
1326 m_minWidth = -1;
1327 m_minHeight = -1;
1328 m_maxWidth = -1;
1329 m_maxHeight = -1;
1330
1331 m_retCode = 0;
1332
1333 m_eventHandler = this;
1334 m_windowValidator = (wxValidator *) NULL;
1335
1336 m_windowId = -1;
1337
1338 m_cursor = (wxCursor *) NULL;
1339 m_font = *wxSWISS_FONT;
1340 m_windowStyle = 0;
1341 m_windowName = "noname";
1342
1343 m_constraints = (wxLayoutConstraints *) NULL;
1344 m_constraintsInvolvedIn = (wxList *) NULL;
1345 m_windowSizer = (wxSizer *) NULL;
1346 m_sizerParent = (wxWindow *) NULL;
1347 m_autoLayout = FALSE;
1348
1349 m_sizeSet = FALSE;
1350 m_hasVMT = FALSE;
1351 m_needParent = TRUE;
1352
1353 m_hasScrolling = FALSE;
1354 m_isScrolling = FALSE;
1355 m_hAdjust = (GtkAdjustment*) NULL;
1356 m_vAdjust = (GtkAdjustment*) NULL;
1357 m_oldHorizontalPos = 0.0;
1358 m_oldVerticalPos = 0.0;
1359
1360 m_isShown = FALSE;
1361 m_isEnabled = TRUE;
1362
1363 #if wxUSE_DRAG_AND_DROP
1364 m_dropTarget = (wxDropTarget*) NULL;
1365 #endif
1366 m_resizing = FALSE;
1367 m_scrollGC = (GdkGC*) NULL;
1368 m_widgetStyle = (GtkStyle*) NULL;
1369
1370 m_insertCallback = wxInsertChildInWindow;
1371
1372 m_clientObject = (wxClientData*) NULL;
1373 m_clientData = NULL;
1374
1375 m_isStaticBox = FALSE;
1376 m_acceptsFocus = FALSE;
1377
1378 #if wxUSE_TOOLTIPS
1379 m_toolTip = (wxToolTip*) NULL;
1380 #endif // wxUSE_TOOLTIPS
1381 }
1382
1383 wxWindow::wxWindow()
1384 {
1385 Init();
1386 }
1387
1388 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
1389 const wxPoint &pos, const wxSize &size,
1390 long style, const wxString &name )
1391 {
1392 Init();
1393
1394 Create( parent, id, pos, size, style, name );
1395 }
1396
1397 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
1398 const wxPoint &pos, const wxSize &size,
1399 long style, const wxString &name )
1400 {
1401 wxASSERT_MSG( m_isWindow, "Init() must have been called before!" );
1402
1403 PreCreation( parent, id, pos, size, style, name );
1404
1405 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
1406 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
1407
1408 #ifdef __WXDEBUG__
1409 debug_focus_in( m_widget, "wxWindow::m_widget", name );
1410 #endif
1411
1412 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
1413
1414 #ifdef __WXDEBUG__
1415 debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
1416 debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
1417 #endif
1418
1419 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1420 scroll_class->scrollbar_spacing = 0;
1421
1422 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1423
1424 m_oldHorizontalPos = 0.0;
1425 m_oldVerticalPos = 0.0;
1426
1427 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1428 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
1429
1430 m_wxwindow = gtk_myfixed_new();
1431
1432 #ifdef __WXDEBUG__
1433 debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
1434 #endif
1435
1436 #ifdef NEW_GTK_SCROLL_CODE
1437 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1438 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1439 #else
1440 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1441 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
1442 #endif
1443
1444 #ifdef __WXDEBUG__
1445 debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
1446 #endif
1447
1448 if (m_windowStyle & wxRAISED_BORDER)
1449 {
1450 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1451 }
1452 else if (m_windowStyle & wxSUNKEN_BORDER)
1453 {
1454 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1455 }
1456 else
1457 {
1458 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1459 }
1460
1461 if (m_windowStyle & wxTAB_TRAVERSAL)
1462 {
1463 /* we now allow a window to get the focus as long as it
1464 doesn't have any children. */
1465 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1466 m_acceptsFocus = FALSE;
1467 }
1468 else
1469 {
1470 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1471 m_acceptsFocus = TRUE;
1472 }
1473
1474 // shut the viewport up
1475 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1476 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1477
1478 // I _really_ don't want scrollbars in the beginning
1479 m_vAdjust->lower = 0.0;
1480 m_vAdjust->upper = 1.0;
1481 m_vAdjust->value = 0.0;
1482 m_vAdjust->step_increment = 1.0;
1483 m_vAdjust->page_increment = 1.0;
1484 m_vAdjust->page_size = 5.0;
1485 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1486 m_hAdjust->lower = 0.0;
1487 m_hAdjust->upper = 1.0;
1488 m_hAdjust->value = 0.0;
1489 m_hAdjust->step_increment = 1.0;
1490 m_hAdjust->page_increment = 1.0;
1491 m_hAdjust->page_size = 5.0;
1492 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1493
1494 // these handlers block mouse events to any window during scrolling
1495 // such as motion events and prevent GTK and wxWindows from fighting
1496 // over where the slider should be
1497
1498 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1499 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1500
1501 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1502 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1503
1504 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1505 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1506
1507 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1508 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1509
1510 // these handers het notified when screen updates are required either when
1511 // scrolling or when the window size (and therefore scrollbar configuration)
1512 // has changed
1513
1514 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1515 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1516 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1517 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1518
1519 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1520 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1521 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1522 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1523
1524 gtk_widget_show( m_wxwindow );
1525
1526 if (m_parent) m_parent->AddChild( this );
1527
1528 (m_parent->m_insertCallback)( m_parent, this );
1529
1530 PostCreation();
1531
1532 Show( TRUE );
1533
1534 return TRUE;
1535 }
1536
1537 wxWindow::~wxWindow()
1538 {
1539 m_hasVMT = FALSE;
1540
1541 #if wxUSE_DRAG_AND_DROP
1542 if (m_dropTarget)
1543 {
1544 delete m_dropTarget;
1545 m_dropTarget = (wxDropTarget*) NULL;
1546 }
1547 #endif
1548
1549 #if wxUSE_TOOLTIPS
1550 if (m_toolTip)
1551 {
1552 delete m_toolTip;
1553 m_toolTip = (wxToolTip*) NULL;
1554 }
1555 #endif // wxUSE_TOOLTIPS
1556
1557 if (m_widget) Show( FALSE );
1558
1559 DestroyChildren();
1560
1561 if (m_parent) m_parent->RemoveChild( this );
1562
1563 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1564
1565 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1566
1567 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1568
1569 if (m_widget) gtk_widget_destroy( m_widget );
1570
1571 if (m_cursor) delete m_cursor;
1572
1573 DeleteRelatedConstraints();
1574 if (m_constraints)
1575 {
1576 /* This removes any dangling pointers to this window
1577 * in other windows' constraintsInvolvedIn lists. */
1578 UnsetConstraints(m_constraints);
1579 delete m_constraints;
1580 m_constraints = (wxLayoutConstraints *) NULL;
1581 }
1582
1583 if (m_windowSizer)
1584 {
1585 delete m_windowSizer;
1586 m_windowSizer = (wxSizer *) NULL;
1587 }
1588 /* If this is a child of a sizer, remove self from parent */
1589 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1590
1591 /* Just in case the window has been Closed, but
1592 * we're then deleting immediately: don't leave
1593 * dangling pointers. */
1594 wxPendingDelete.DeleteObject(this);
1595
1596 /* Just in case we've loaded a top-level window via
1597 * wxWindow::LoadNativeDialog but we weren't a dialog
1598 * class */
1599 wxTopLevelWindows.DeleteObject(this);
1600
1601 if (m_windowValidator) delete m_windowValidator;
1602
1603 if (m_clientObject) delete m_clientObject;
1604 }
1605
1606 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1607 const wxPoint &pos, const wxSize &size,
1608 long style, const wxString &name )
1609 {
1610 wxASSERT_MSG( (!m_needParent) || (parent), "Need complete parent." );
1611
1612 m_widget = (GtkWidget*) NULL;
1613 m_wxwindow = (GtkWidget*) NULL;
1614 m_hasVMT = FALSE;
1615 m_parent = parent;
1616 m_children.DeleteContents( FALSE );
1617
1618 m_width = size.x;
1619 if (m_width == -1) m_width = 20;
1620 m_height = size.y;
1621 if (m_height == -1) m_height = 20;
1622
1623 m_x = (int)pos.x;
1624 m_y = (int)pos.y;
1625
1626 if (!m_needParent) /* some reasonable defaults */
1627 {
1628 if (m_x == -1)
1629 {
1630 m_x = (gdk_screen_width () - m_width) / 2;
1631 if (m_x < 10) m_x = 10;
1632 }
1633 if (m_y == -1)
1634 {
1635 m_y = (gdk_screen_height () - m_height) / 2;
1636 if (m_y < 10) m_y = 10;
1637 }
1638 }
1639
1640 m_minWidth = -1;
1641 m_minHeight = -1;
1642 m_maxWidth = -1;
1643 m_maxHeight = -1;
1644
1645 m_retCode = 0;
1646
1647 m_eventHandler = this;
1648
1649 m_windowId = id == -1 ? wxNewId() : id;
1650
1651 m_sizeSet = FALSE;
1652
1653 m_cursor = new wxCursor( wxCURSOR_ARROW );
1654 m_font = *wxSWISS_FONT;
1655 m_backgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
1656 m_foregroundColour = *wxBLACK;
1657 m_windowStyle = style;
1658 m_windowName = name;
1659
1660 m_constraints = (wxLayoutConstraints *) NULL;
1661 m_constraintsInvolvedIn = (wxList *) NULL;
1662 m_windowSizer = (wxSizer *) NULL;
1663 m_sizerParent = (wxWindow *) NULL;
1664 m_autoLayout = FALSE;
1665
1666 m_hasScrolling = FALSE;
1667 m_isScrolling = FALSE;
1668 m_hAdjust = (GtkAdjustment *) NULL;
1669 m_vAdjust = (GtkAdjustment *) NULL;
1670 m_oldHorizontalPos = 0.0;
1671 m_oldVerticalPos = 0.0;
1672
1673 m_isShown = FALSE;
1674 m_isEnabled = TRUE;
1675
1676 #if wxUSE_DRAG_AND_DROP
1677 m_dropTarget = (wxDropTarget *) NULL;
1678 #endif
1679 m_resizing = FALSE;
1680 m_windowValidator = (wxValidator *) NULL;
1681 m_scrollGC = (GdkGC*) NULL;
1682 m_widgetStyle = (GtkStyle*) NULL;
1683
1684 m_clientObject = (wxClientData*)NULL;
1685 m_clientData = NULL;
1686
1687 m_isStaticBox = FALSE;
1688
1689 #if wxUSE_TOOLTIPS
1690 m_toolTip = (wxToolTip*) NULL;
1691 #endif // wxUSE_TOOLTIPS
1692 }
1693
1694 void wxWindow::PostCreation()
1695 {
1696 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1697
1698 if (m_wxwindow)
1699 {
1700 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1701 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1702
1703 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1704 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1705 }
1706
1707 ConnectWidget( GetConnectWidget() );
1708
1709 /* we force the creation of wxFrame and wxDialog in the respective code */
1710 if (m_parent) gtk_widget_realize( m_widget );
1711
1712 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1713
1714 SetCursor( *wxSTANDARD_CURSOR );
1715
1716 m_hasVMT = TRUE;
1717 }
1718
1719 void wxWindow::ConnectWidget( GtkWidget *widget )
1720 {
1721 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1722 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1723
1724 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1725 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1726
1727 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1728 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1729
1730 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1731 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1732
1733 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1734 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1735
1736 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1737 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1738
1739 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1740 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1741
1742 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1743 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1744
1745 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1746 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1747 }
1748
1749 bool wxWindow::HasVMT()
1750 {
1751 return m_hasVMT;
1752 }
1753
1754 bool wxWindow::Close( bool force )
1755 {
1756 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1757
1758 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1759 event.SetEventObject(this);
1760 event.SetCanVeto(!force);
1761
1762 /* return FALSE if window wasn't closed because the application vetoed the
1763 * close event */
1764 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
1765 }
1766
1767 bool wxWindow::Destroy()
1768 {
1769 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1770
1771 m_hasVMT = FALSE;
1772 delete this;
1773 return TRUE;
1774 }
1775
1776 bool wxWindow::DestroyChildren()
1777 {
1778 wxNode *node;
1779 while ((node = m_children.First()) != (wxNode *)NULL)
1780 {
1781 wxWindow *child;
1782 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1783 {
1784 delete child;
1785 if (m_children.Member(child)) delete node;
1786 }
1787 }
1788 return TRUE;
1789 }
1790
1791 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1792 {
1793 // are we to set fonts here ?
1794 }
1795
1796 wxPoint wxWindow::GetClientAreaOrigin() const
1797 {
1798 return wxPoint(0,0);
1799 }
1800
1801 void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1802 {
1803 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1804 {
1805 wxPoint pt(GetParent()->GetClientAreaOrigin());
1806 x += pt.x;
1807 y += pt.y;
1808 }
1809 }
1810
1811 void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
1812 {
1813 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1814 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
1815
1816 if (m_resizing) return; /* I don't like recursions */
1817 m_resizing = TRUE;
1818
1819 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
1820 {
1821 /* don't set the size for children of wxNotebook, just take the values. */
1822 m_x = x;
1823 m_y = y;
1824 m_width = width;
1825 m_height = height;
1826 }
1827 else
1828 {
1829 int old_width = m_width;
1830 int old_height = m_height;
1831
1832 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1833 {
1834 if (x != -1) m_x = x;
1835 if (y != -1) m_y = y;
1836 if (width != -1) m_width = width;
1837 if (height != -1) m_height = height;
1838 }
1839 else
1840 {
1841 m_x = x;
1842 m_y = y;
1843 m_width = width;
1844 m_height = height;
1845 }
1846
1847 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1848 {
1849 if (width == -1) m_width = 80;
1850 }
1851
1852 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1853 {
1854 if (height == -1) m_height = 26;
1855 }
1856
1857 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1858 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1859 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1860 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
1861
1862 if (GTK_WIDGET_HAS_DEFAULT(m_widget))
1863 {
1864 /* the default button has a border around it */
1865 int border = 5;
1866
1867 wxPoint pt( m_parent->GetClientAreaOrigin() );
1868 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x-border, m_y+pt.y-border );
1869
1870 gtk_widget_set_usize( m_widget, m_width+2*border, m_height+2*border );
1871 }
1872 else
1873 {
1874 wxPoint pt( m_parent->GetClientAreaOrigin() );
1875 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1876
1877 if ((old_width != m_width) || (old_height != m_height))
1878 gtk_widget_set_usize( m_widget, m_width, m_height );
1879 }
1880 }
1881
1882 m_sizeSet = TRUE;
1883
1884 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1885 event.SetEventObject( this );
1886 GetEventHandler()->ProcessEvent( event );
1887
1888 m_resizing = FALSE;
1889 }
1890
1891 void wxWindow::OnInternalIdle()
1892 {
1893 UpdateWindowUI();
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::DoSetClientSize( 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->GetItems().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 (m_font == font) return;
2841
2842 if (((wxFont*)&font)->Ok())
2843 m_font = font;
2844 else
2845 m_font = *wxSWISS_FONT;
2846
2847 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2848 if (sysbg.Red() == m_backgroundColour.Red() &&
2849 sysbg.Green() == m_backgroundColour.Green() &&
2850 sysbg.Blue() == m_backgroundColour.Blue())
2851 {
2852 m_backgroundColour = wxNullColour;
2853 ApplyWidgetStyle();
2854 m_backgroundColour = sysbg;
2855 }
2856 else
2857 {
2858 ApplyWidgetStyle();
2859 }
2860 }
2861
2862 void wxWindow::SetWindowStyleFlag( long flag )
2863 {
2864 m_windowStyle = flag;
2865 }
2866
2867 long wxWindow::GetWindowStyleFlag() const
2868 {
2869 return m_windowStyle;
2870 }
2871
2872 void wxWindow::CaptureMouse()
2873 {
2874 wxCHECK_RET( m_widget != NULL, "invalid window" );
2875
2876 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2877
2878 GtkWidget *connect_widget = GetConnectWidget();
2879 gtk_grab_add( connect_widget );
2880 gdk_pointer_grab( connect_widget->window, FALSE,
2881 (GdkEventMask)
2882 (GDK_BUTTON_PRESS_MASK |
2883 GDK_BUTTON_RELEASE_MASK |
2884 GDK_POINTER_MOTION_MASK),
2885 (GdkWindow *) NULL,
2886 (GdkCursor *) NULL,
2887 GDK_CURRENT_TIME );
2888 g_capturing = TRUE;
2889 }
2890
2891 void wxWindow::ReleaseMouse()
2892 {
2893 wxCHECK_RET( m_widget != NULL, "invalid window" );
2894
2895 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2896
2897 GtkWidget *connect_widget = GetConnectWidget();
2898 gtk_grab_remove( connect_widget );
2899 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2900 g_capturing = FALSE;
2901 }
2902
2903 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2904 {
2905 }
2906
2907 wxString wxWindow::GetTitle() const
2908 {
2909 return (wxString&)m_windowName;
2910 }
2911
2912 wxString wxWindow::GetLabel() const
2913 {
2914 return GetTitle();
2915 }
2916
2917 void wxWindow::SetName( const wxString &name )
2918 {
2919 m_windowName = name;
2920 }
2921
2922 wxString wxWindow::GetName() const
2923 {
2924 return (wxString&)m_windowName;
2925 }
2926
2927 bool wxWindow::IsShown() const
2928 {
2929 return m_isShown;
2930 }
2931
2932 bool wxWindow::IsRetained()
2933 {
2934 return FALSE;
2935 }
2936
2937 wxWindow *wxWindow::FindWindow( long id )
2938 {
2939 if (id == m_windowId) return this;
2940 wxNode *node = m_children.First();
2941 while (node)
2942 {
2943 wxWindow *child = (wxWindow*)node->Data();
2944 wxWindow *res = child->FindWindow( id );
2945 if (res) return res;
2946 node = node->Next();
2947 }
2948 return (wxWindow *) NULL;
2949 }
2950
2951 wxWindow *wxWindow::FindWindow( const wxString& name )
2952 {
2953 if (name == m_windowName) return this;
2954 wxNode *node = m_children.First();
2955 while (node)
2956 {
2957 wxWindow *child = (wxWindow*)node->Data();
2958 wxWindow *res = child->FindWindow( name );
2959 if (res) return res;
2960 node = node->Next();
2961 }
2962 return (wxWindow *) NULL;
2963 }
2964
2965 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2966 int range, bool refresh )
2967 {
2968 wxCHECK_RET( m_widget != NULL, "invalid window" );
2969
2970 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2971
2972 m_hasScrolling = TRUE;
2973
2974 if (orient == wxHORIZONTAL)
2975 {
2976 float fpos = (float)pos;
2977 float frange = (float)range;
2978 float fthumb = (float)thumbVisible;
2979 if (fpos > frange-fthumb) fpos = frange-fthumb;
2980 if (fpos < 0.0) fpos = 0.0;
2981
2982 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2983 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2984 {
2985 SetScrollPos( orient, pos, refresh );
2986 return;
2987 }
2988
2989 m_oldHorizontalPos = fpos;
2990
2991 m_hAdjust->lower = 0.0;
2992 m_hAdjust->upper = frange;
2993 m_hAdjust->value = fpos;
2994 m_hAdjust->step_increment = 1.0;
2995 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2996 m_hAdjust->page_size = fthumb;
2997 }
2998 else
2999 {
3000 float fpos = (float)pos;
3001 float frange = (float)range;
3002 float fthumb = (float)thumbVisible;
3003 if (fpos > frange-fthumb) fpos = frange-fthumb;
3004 if (fpos < 0.0) fpos = 0.0;
3005
3006 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3007 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3008 {
3009 SetScrollPos( orient, pos, refresh );
3010 return;
3011 }
3012
3013 m_oldVerticalPos = fpos;
3014
3015 m_vAdjust->lower = 0.0;
3016 m_vAdjust->upper = frange;
3017 m_vAdjust->value = fpos;
3018 m_vAdjust->step_increment = 1.0;
3019 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3020 m_vAdjust->page_size = fthumb;
3021 }
3022
3023 if (m_wxwindow->window)
3024 {
3025 if (orient == wxHORIZONTAL)
3026 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3027 else
3028 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
3029
3030 gtk_widget_set_usize( m_widget, m_width, m_height );
3031 }
3032 }
3033
3034 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
3035 {
3036 wxCHECK_RET( m_widget != NULL, "invalid window" );
3037
3038 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
3039
3040 if (orient == wxHORIZONTAL)
3041 {
3042 float fpos = (float)pos;
3043 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3044 if (fpos < 0.0) fpos = 0.0;
3045 m_oldHorizontalPos = fpos;
3046
3047 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3048 m_hAdjust->value = fpos;
3049 }
3050 else
3051 {
3052 float fpos = (float)pos;
3053 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3054 if (fpos < 0.0) fpos = 0.0;
3055 m_oldVerticalPos = fpos;
3056
3057 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3058 m_vAdjust->value = fpos;
3059 }
3060
3061 if (!m_isScrolling)
3062 {
3063 if (m_wxwindow->window)
3064 {
3065 if (orient == wxHORIZONTAL)
3066 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3067 else
3068 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3069 }
3070 }
3071 }
3072
3073 int wxWindow::GetScrollThumb( int orient ) const
3074 {
3075 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3076
3077 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3078
3079 if (orient == wxHORIZONTAL)
3080 return (int)(m_hAdjust->page_size+0.5);
3081 else
3082 return (int)(m_vAdjust->page_size+0.5);
3083 }
3084
3085 int wxWindow::GetScrollPos( int orient ) const
3086 {
3087 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3088
3089 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3090
3091 if (orient == wxHORIZONTAL)
3092 return (int)(m_hAdjust->value+0.5);
3093 else
3094 return (int)(m_vAdjust->value+0.5);
3095 }
3096
3097 int wxWindow::GetScrollRange( int orient ) const
3098 {
3099 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3100
3101 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3102
3103 if (orient == wxHORIZONTAL)
3104 return (int)(m_hAdjust->upper+0.5);
3105 else
3106 return (int)(m_vAdjust->upper+0.5);
3107 }
3108
3109 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
3110 {
3111 wxCHECK_RET( m_widget != NULL, "invalid window" );
3112
3113 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
3114
3115 int cw = 0;
3116 int ch = 0;
3117 GetClientSize( &cw, &ch );
3118
3119 int w = cw - abs(dx);
3120 int h = ch - abs(dy);
3121 if ((h < 0) || (w < 0))
3122 {
3123 Refresh();
3124 return;
3125 }
3126 int s_x = 0;
3127 int s_y = 0;
3128 if (dx < 0) s_x = -dx;
3129 if (dy < 0) s_y = -dy;
3130 int d_x = 0;
3131 int d_y = 0;
3132 if (dx > 0) d_x = dx;
3133 if (dy > 0) d_y = dy;
3134
3135 if (!m_scrollGC)
3136 {
3137 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3138 gdk_gc_set_exposures( m_scrollGC, TRUE );
3139 }
3140
3141 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3142 m_wxwindow->window, s_x, s_y, w, h );
3143
3144 wxRect rect;
3145 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3146 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3147 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3148 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3149
3150 Refresh( TRUE, &rect );
3151 }
3152
3153 //-------------------------------------------------------------------------------------
3154 // Layout
3155 //-------------------------------------------------------------------------------------
3156
3157 wxLayoutConstraints *wxWindow::GetConstraints() const
3158 {
3159 return m_constraints;
3160 }
3161
3162 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
3163 {
3164 if (m_constraints)
3165 {
3166 UnsetConstraints(m_constraints);
3167 delete m_constraints;
3168 }
3169 m_constraints = constraints;
3170 if (m_constraints)
3171 {
3172 // Make sure other windows know they're part of a 'meaningful relationship'
3173 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3174 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3175 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3176 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3177 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3178 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3179 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3180 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3181 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3182 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3183 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3184 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3185 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3186 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3187 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3188 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3189 }
3190 ;
3191 }
3192 ;
3193
3194 void wxWindow::SetAutoLayout( bool autoLayout )
3195 {
3196 m_autoLayout = autoLayout;
3197 }
3198
3199 bool wxWindow::GetAutoLayout() const
3200 {
3201 return m_autoLayout;
3202 }
3203
3204 wxSizer *wxWindow::GetSizer() const
3205 {
3206 return m_windowSizer;
3207 }
3208
3209 void wxWindow::SetSizerParent( wxWindow *win )
3210 {
3211 m_sizerParent = win;
3212 }
3213
3214 wxWindow *wxWindow::GetSizerParent() const
3215 {
3216 return m_sizerParent;
3217 }
3218
3219 // This removes any dangling pointers to this window
3220 // in other windows' constraintsInvolvedIn lists.
3221 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3222 {
3223 if (c)
3224 {
3225 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3226 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3227 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3228 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3229 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3230 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3231 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3232 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3233 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3234 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3235 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3236 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3237 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3238 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3239 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3240 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3241 }
3242 }
3243
3244 // Back-pointer to other windows we're involved with, so if we delete
3245 // this window, we must delete any constraints we're involved with.
3246 void wxWindow::AddConstraintReference(wxWindow *otherWin)
3247 {
3248 if (!m_constraintsInvolvedIn)
3249 m_constraintsInvolvedIn = new wxList;
3250 if (!m_constraintsInvolvedIn->Member(otherWin))
3251 m_constraintsInvolvedIn->Append(otherWin);
3252 }
3253
3254 // REMOVE back-pointer to other windows we're involved with.
3255 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3256 {
3257 if (m_constraintsInvolvedIn)
3258 m_constraintsInvolvedIn->DeleteObject(otherWin);
3259 }
3260
3261 // Reset any constraints that mention this window
3262 void wxWindow::DeleteRelatedConstraints()
3263 {
3264 if (m_constraintsInvolvedIn)
3265 {
3266 wxNode *node = m_constraintsInvolvedIn->First();
3267 while (node)
3268 {
3269 wxWindow *win = (wxWindow *)node->Data();
3270 wxNode *next = node->Next();
3271 wxLayoutConstraints *constr = win->GetConstraints();
3272
3273 // Reset any constraints involving this window
3274 if (constr)
3275 {
3276 constr->left.ResetIfWin((wxWindow *)this);
3277 constr->top.ResetIfWin((wxWindow *)this);
3278 constr->right.ResetIfWin((wxWindow *)this);
3279 constr->bottom.ResetIfWin((wxWindow *)this);
3280 constr->width.ResetIfWin((wxWindow *)this);
3281 constr->height.ResetIfWin((wxWindow *)this);
3282 constr->centreX.ResetIfWin((wxWindow *)this);
3283 constr->centreY.ResetIfWin((wxWindow *)this);
3284 }
3285 delete node;
3286 node = next;
3287 }
3288 delete m_constraintsInvolvedIn;
3289 m_constraintsInvolvedIn = (wxList *) NULL;
3290 }
3291 }
3292
3293 void wxWindow::SetSizer(wxSizer *sizer)
3294 {
3295 m_windowSizer = sizer;
3296 if (sizer)
3297 sizer->SetSizerParent((wxWindow *)this);
3298 }
3299
3300 /*
3301 * New version
3302 */
3303
3304 bool wxWindow::Layout()
3305 {
3306 if (GetConstraints())
3307 {
3308 int w, h;
3309 GetClientSize(&w, &h);
3310 GetConstraints()->width.SetValue(w);
3311 GetConstraints()->height.SetValue(h);
3312 }
3313
3314 // If top level (one sizer), evaluate the sizer's constraints.
3315 if (GetSizer())
3316 {
3317 int noChanges;
3318 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3319 GetSizer()->LayoutPhase1(&noChanges);
3320 GetSizer()->LayoutPhase2(&noChanges);
3321 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3322 return TRUE;
3323 }
3324 else
3325 {
3326 // Otherwise, evaluate child constraints
3327 ResetConstraints(); // Mark all constraints as unevaluated
3328 DoPhase(1); // Just one phase need if no sizers involved
3329 DoPhase(2);
3330 SetConstraintSizes(); // Recursively set the real window sizes
3331 }
3332 return TRUE;
3333 }
3334
3335
3336 // Do a phase of evaluating constraints:
3337 // the default behaviour. wxSizers may do a similar
3338 // thing, but also impose their own 'constraints'
3339 // and order the evaluation differently.
3340 bool wxWindow::LayoutPhase1(int *noChanges)
3341 {
3342 wxLayoutConstraints *constr = GetConstraints();
3343 if (constr)
3344 {
3345 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3346 }
3347 else
3348 return TRUE;
3349 }
3350
3351 bool wxWindow::LayoutPhase2(int *noChanges)
3352 {
3353 *noChanges = 0;
3354
3355 // Layout children
3356 DoPhase(1);
3357 DoPhase(2);
3358 return TRUE;
3359 }
3360
3361 // Do a phase of evaluating child constraints
3362 bool wxWindow::DoPhase(int phase)
3363 {
3364 int noIterations = 0;
3365 int maxIterations = 500;
3366 int noChanges = 1;
3367 int noFailures = 0;
3368 wxList succeeded;
3369 while ((noChanges > 0) && (noIterations < maxIterations))
3370 {
3371 noChanges = 0;
3372 noFailures = 0;
3373 wxNode *node = m_children.First();
3374 while (node)
3375 {
3376 wxWindow *child = (wxWindow *)node->Data();
3377 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3378 {
3379 wxLayoutConstraints *constr = child->GetConstraints();
3380 if (constr)
3381 {
3382 if (succeeded.Member(child))
3383 {
3384 }
3385 else
3386 {
3387 int tempNoChanges = 0;
3388 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3389 noChanges += tempNoChanges;
3390 if (success)
3391 {
3392 succeeded.Append(child);
3393 }
3394 }
3395 }
3396 }
3397 node = node->Next();
3398 }
3399 noIterations ++;
3400 }
3401 return TRUE;
3402 }
3403
3404 void wxWindow::ResetConstraints()
3405 {
3406 wxLayoutConstraints *constr = GetConstraints();
3407 if (constr)
3408 {
3409 constr->left.SetDone(FALSE);
3410 constr->top.SetDone(FALSE);
3411 constr->right.SetDone(FALSE);
3412 constr->bottom.SetDone(FALSE);
3413 constr->width.SetDone(FALSE);
3414 constr->height.SetDone(FALSE);
3415 constr->centreX.SetDone(FALSE);
3416 constr->centreY.SetDone(FALSE);
3417 }
3418 wxNode *node = m_children.First();
3419 while (node)
3420 {
3421 wxWindow *win = (wxWindow *)node->Data();
3422 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3423 win->ResetConstraints();
3424 node = node->Next();
3425 }
3426 }
3427
3428 // Need to distinguish between setting the 'fake' size for
3429 // windows and sizers, and setting the real values.
3430 void wxWindow::SetConstraintSizes(bool recurse)
3431 {
3432 wxLayoutConstraints *constr = GetConstraints();
3433 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3434 constr->width.GetDone() && constr->height.GetDone())
3435 {
3436 int x = constr->left.GetValue();
3437 int y = constr->top.GetValue();
3438 int w = constr->width.GetValue();
3439 int h = constr->height.GetValue();
3440
3441 // If we don't want to resize this window, just move it...
3442 if ((constr->width.GetRelationship() != wxAsIs) ||
3443 (constr->height.GetRelationship() != wxAsIs))
3444 {
3445 // Calls Layout() recursively. AAAGH. How can we stop that.
3446 // Simply take Layout() out of non-top level OnSizes.
3447 SizerSetSize(x, y, w, h);
3448 }
3449 else
3450 {
3451 SizerMove(x, y);
3452 }
3453 }
3454 else if (constr)
3455 {
3456 char *windowClass = this->GetClassInfo()->GetClassName();
3457
3458 wxString winName;
3459 if (GetName() == "")
3460 winName = "unnamed";
3461 else
3462 winName = GetName();
3463 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3464 (const char *)windowClass,
3465 (const char *)winName);
3466 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3467 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3468 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3469 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3470 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3471 }
3472
3473 if (recurse)
3474 {
3475 wxNode *node = m_children.First();
3476 while (node)
3477 {
3478 wxWindow *win = (wxWindow *)node->Data();
3479 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3480 win->SetConstraintSizes();
3481 node = node->Next();
3482 }
3483 }
3484 }
3485
3486 // This assumes that all sizers are 'on' the same
3487 // window, i.e. the parent of this window.
3488 void wxWindow::TransformSizerToActual(int *x, int *y) const
3489 {
3490 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
3491 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
3492 return;
3493
3494 int xp, yp;
3495 m_sizerParent->GetPosition(&xp, &yp);
3496 m_sizerParent->TransformSizerToActual(&xp, &yp);
3497 *x += xp;
3498 *y += yp;
3499 }
3500
3501 void wxWindow::SizerSetSize(int x, int y, int w, int h)
3502 {
3503 int xx = x;
3504 int yy = y;
3505 TransformSizerToActual(&xx, &yy);
3506 SetSize(xx, yy, w, h);
3507 }
3508
3509 void wxWindow::SizerMove(int x, int y)
3510 {
3511 int xx = x;
3512 int yy = y;
3513 TransformSizerToActual(&xx, &yy);
3514 Move(xx, yy);
3515 }
3516
3517 // Only set the size/position of the constraint (if any)
3518 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
3519 {
3520 wxLayoutConstraints *constr = GetConstraints();
3521 if (constr)
3522 {
3523 if (x != -1)
3524 {
3525 constr->left.SetValue(x);
3526 constr->left.SetDone(TRUE);
3527 }
3528 if (y != -1)
3529 {
3530 constr->top.SetValue(y);
3531 constr->top.SetDone(TRUE);
3532 }
3533 if (w != -1)
3534 {
3535 constr->width.SetValue(w);
3536 constr->width.SetDone(TRUE);
3537 }
3538 if (h != -1)
3539 {
3540 constr->height.SetValue(h);
3541 constr->height.SetDone(TRUE);
3542 }
3543 }
3544 }
3545
3546 void wxWindow::MoveConstraint(int x, int y)
3547 {
3548 wxLayoutConstraints *constr = GetConstraints();
3549 if (constr)
3550 {
3551 if (x != -1)
3552 {
3553 constr->left.SetValue(x);
3554 constr->left.SetDone(TRUE);
3555 }
3556 if (y != -1)
3557 {
3558 constr->top.SetValue(y);
3559 constr->top.SetDone(TRUE);
3560 }
3561 }
3562 }
3563
3564 void wxWindow::GetSizeConstraint(int *w, int *h) const
3565 {
3566 wxLayoutConstraints *constr = GetConstraints();
3567 if (constr)
3568 {
3569 *w = constr->width.GetValue();
3570 *h = constr->height.GetValue();
3571 }
3572 else
3573 GetSize(w, h);
3574 }
3575
3576 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3577 {
3578 wxLayoutConstraints *constr = GetConstraints();
3579 if (constr)
3580 {
3581 *w = constr->width.GetValue();
3582 *h = constr->height.GetValue();
3583 }
3584 else
3585 GetClientSize(w, h);
3586 }
3587
3588 void wxWindow::GetPositionConstraint(int *x, int *y) const
3589 {
3590 wxLayoutConstraints *constr = GetConstraints();
3591 if (constr)
3592 {
3593 *x = constr->left.GetValue();
3594 *y = constr->top.GetValue();
3595 }
3596 else
3597 GetPosition(x, y);
3598 }
3599