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