]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
refresh added when the item text or image is changed so it's redrawn
[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);
1719 event.SetForce(force);
c801d85f 1720
43a18898 1721 return GetEventHandler()->ProcessEvent(event);
362c6693 1722}
c801d85f 1723
68dda785 1724bool wxWindow::Destroy()
c801d85f 1725{
43a18898 1726 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1727
43a18898
RR
1728 m_hasVMT = FALSE;
1729 delete this;
1730 return TRUE;
362c6693 1731}
c801d85f 1732
68dda785 1733bool wxWindow::DestroyChildren()
c801d85f 1734{
db1b4961
RR
1735 wxNode *node;
1736 while ((node = m_children.First()) != (wxNode *)NULL)
c801d85f 1737 {
db1b4961
RR
1738 wxWindow *child;
1739 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
43a18898 1740 {
db1b4961
RR
1741 delete child;
1742 if (m_children.Member(child)) delete node;
43a18898 1743 }
362c6693 1744 }
43a18898 1745 return TRUE;
362c6693 1746}
c801d85f
KB
1747
1748void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1749{
43a18898 1750 // are we to set fonts here ?
362c6693 1751}
c801d85f 1752
6ca41e57
RR
1753wxPoint wxWindow::GetClientAreaOrigin() const
1754{
43a18898 1755 return wxPoint(0,0);
6ca41e57
RR
1756}
1757
1758void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1759{
43a18898
RR
1760 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1761 {
1762 wxPoint pt(GetParent()->GetClientAreaOrigin());
8bbe427f 1763 x += pt.x;
43a18898
RR
1764 y += pt.y;
1765 }
6ca41e57
RR
1766}
1767
debe6624 1768void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1769{
fb1585ae
RR
1770 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1771 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
8bbe427f 1772
fb1585ae
RR
1773 if (m_resizing) return; // I don't like recursions
1774 m_resizing = TRUE;
47d67540 1775
ba4e3652 1776 if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
fb1585ae 1777 {
ba4e3652 1778 // don't set the size for children of wxNotebook, just take the values.
fb1585ae
RR
1779 m_x = x;
1780 m_y = y;
1781 m_width = width;
ba4e3652 1782 m_height = height;
fb1585ae 1783 }
ba4e3652 1784 else
fb1585ae 1785 {
ba4e3652
RR
1786 int old_width = m_width;
1787 int old_height = m_height;
8bbe427f 1788
ba4e3652
RR
1789 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1790 {
1791 if (x != -1) m_x = x;
1792 if (y != -1) m_y = y;
1793 if (width != -1) m_width = width;
1794 if (height != -1) m_height = height;
1795 }
1796 else
1797 {
1798 m_x = x;
1799 m_y = y;
1800 m_width = width;
1801 m_height = height;
1802 }
47d67540 1803
ba4e3652
RR
1804 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1805 {
1806 if (width == -1) m_width = 80;
1807 }
1808
1809 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1810 {
1811 if (height == -1) m_height = 26;
1812 }
8bbe427f 1813
ba4e3652
RR
1814 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1815 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
1816 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1817 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 1818
ba4e3652
RR
1819 wxPoint pt( m_parent->GetClientAreaOrigin() );
1820 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
8bbe427f 1821
ba4e3652
RR
1822 if ((old_width != m_width) || (old_height != m_height))
1823 gtk_widget_set_usize( m_widget, m_width, m_height );
1824 }
8bbe427f 1825
fb1585ae 1826 m_sizeSet = TRUE;
47d67540 1827
fb1585ae
RR
1828 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1829 event.SetEventObject( this );
ba4e3652 1830 GetEventHandler()->ProcessEvent( event );
47d67540 1831
fb1585ae 1832 m_resizing = FALSE;
362c6693 1833}
c801d85f 1834
9390a202
RR
1835void wxWindow::OnInternalIdle()
1836{
1837 UpdateWindowUI();
1838}
1839
debe6624 1840void wxWindow::SetSize( int width, int height )
c801d85f 1841{
fb1585ae 1842 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
362c6693 1843}
c801d85f 1844
debe6624 1845void wxWindow::Move( int x, int y )
c801d85f 1846{
fb1585ae 1847 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
362c6693 1848}
c801d85f
KB
1849
1850void wxWindow::GetSize( int *width, int *height ) const
1851{
1ecc4d80 1852 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1853
fb1585ae
RR
1854 if (width) (*width) = m_width;
1855 if (height) (*height) = m_height;
362c6693 1856}
c801d85f 1857
debe6624 1858void wxWindow::SetClientSize( int width, int height )
c801d85f 1859{
1ecc4d80 1860 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1861
1ecc4d80 1862 if (!m_wxwindow)
c801d85f 1863 {
1ecc4d80 1864 SetSize( width, height );
c801d85f
KB
1865 }
1866 else
1867 {
1ecc4d80
RR
1868 int dw = 0;
1869 int dh = 0;
1870
1871 if (!m_hasScrolling)
1872 {
1873 GtkStyleClass *window_class = m_wxwindow->style->klass;
1874
1875 if ((m_windowStyle & wxRAISED_BORDER) ||
1876 (m_windowStyle & wxSUNKEN_BORDER))
1877 {
1878 dw += 2 * window_class->xthickness;
1879 dh += 2 * window_class->ythickness;
1880 }
1881 }
1882 else
1883 {
1884 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1885 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1886
38c7b3d3 1887#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1888 GtkWidget *viewport = scroll_window->child;
8bbe427f 1889#else
1ecc4d80 1890 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1891#endif
1892
1ecc4d80
RR
1893 GtkStyleClass *viewport_class = viewport->style->klass;
1894
1895 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1896 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1897
1898 if ((m_windowStyle & wxRAISED_BORDER) ||
1899 (m_windowStyle & wxSUNKEN_BORDER))
1900 {
1901 dw += 2 * viewport_class->xthickness;
1902 dh += 2 * viewport_class->ythickness;
1903 }
47d67540 1904
1ecc4d80
RR
1905 if (scroll_window->vscrollbar_visible)
1906 {
1907 dw += vscrollbar->allocation.width;
1908 dw += scroll_class->scrollbar_spacing;
1909 }
1910
1911 if (scroll_window->hscrollbar_visible)
1912 {
1913 dh += hscrollbar->allocation.height;
1914 dw += scroll_class->scrollbar_spacing;
1915 }
1916 }
1917
1918 SetSize( width+dw, height+dh );
1919 }
362c6693 1920}
c801d85f
KB
1921
1922void wxWindow::GetClientSize( int *width, int *height ) const
1923{
1ecc4d80 1924 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1925
1ecc4d80
RR
1926 if (!m_wxwindow)
1927 {
1928 if (width) (*width) = m_width;
1929 if (height) (*height) = m_height;
c801d85f
KB
1930 }
1931 else
1932 {
1ecc4d80
RR
1933 int dw = 0;
1934 int dh = 0;
1935
1936 if (!m_hasScrolling)
1937 {
1938 GtkStyleClass *window_class = m_wxwindow->style->klass;
1939
1940 if ((m_windowStyle & wxRAISED_BORDER) ||
1941 (m_windowStyle & wxSUNKEN_BORDER))
1942 {
1943 dw += 2 * window_class->xthickness;
1944 dh += 2 * window_class->ythickness;
1945 }
1946 }
1947 else
1948 {
1949 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1950 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1951
38c7b3d3 1952#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1953 GtkWidget *viewport = scroll_window->child;
8bbe427f 1954#else
1ecc4d80 1955 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1956#endif
1957
1ecc4d80
RR
1958 GtkStyleClass *viewport_class = viewport->style->klass;
1959
1960 if ((m_windowStyle & wxRAISED_BORDER) ||
1961 (m_windowStyle & wxSUNKEN_BORDER))
1962 {
1963 dw += 2 * viewport_class->xthickness;
1964 dh += 2 * viewport_class->ythickness;
1965 }
1966
1967 if (scroll_window->vscrollbar_visible)
1968 {
1969// dw += vscrollbar->allocation.width;
1970 dw += 15; // range.slider_width = 11 + 2*2pts edge
1971 dw += scroll_class->scrollbar_spacing;
1972 }
1973
1974 if (scroll_window->hscrollbar_visible)
1975 {
1976// dh += hscrollbar->allocation.height;
1977 dh += 15;
1978 dh += scroll_class->scrollbar_spacing;
1979 }
1980 }
47d67540 1981
1ecc4d80
RR
1982 if (width) (*width) = m_width - dw;
1983 if (height) (*height) = m_height - dh;
1984 }
362c6693 1985}
c801d85f
KB
1986
1987void wxWindow::GetPosition( int *x, int *y ) const
1988{
1ecc4d80 1989 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1990
43a18898
RR
1991 if (x) (*x) = m_x;
1992 if (y) (*y) = m_y;
362c6693 1993}
c801d85f
KB
1994
1995void wxWindow::ClientToScreen( int *x, int *y )
1996{
1ecc4d80 1997 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1998
43a18898
RR
1999 GdkWindow *source = (GdkWindow *) NULL;
2000 if (m_wxwindow)
2001 source = m_wxwindow->window;
2002 else
2003 source = m_widget->window;
47d67540 2004
43a18898
RR
2005 int org_x = 0;
2006 int org_y = 0;
2007 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2008
43a18898 2009 if (!m_wxwindow)
c801d85f 2010 {
43a18898
RR
2011 if (GTK_WIDGET_NO_WINDOW (m_widget))
2012 {
2013 org_x += m_widget->allocation.x;
2014 org_y += m_widget->allocation.y;
2015 }
362c6693 2016 }
47d67540 2017
43a18898
RR
2018 wxPoint pt(GetClientAreaOrigin());
2019 org_x += pt.x;
2020 org_y += pt.y;
8bbe427f 2021
43a18898
RR
2022 if (x) *x += org_x;
2023 if (y) *y += org_y;
362c6693 2024}
c801d85f
KB
2025
2026void wxWindow::ScreenToClient( int *x, int *y )
2027{
1ecc4d80 2028 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2029
1ecc4d80
RR
2030 GdkWindow *source = (GdkWindow *) NULL;
2031 if (m_wxwindow)
2032 source = m_wxwindow->window;
2033 else
2034 source = m_widget->window;
47d67540 2035
1ecc4d80
RR
2036 int org_x = 0;
2037 int org_y = 0;
2038 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2039
1ecc4d80 2040 if (!m_wxwindow)
c801d85f 2041 {
1ecc4d80
RR
2042 if (GTK_WIDGET_NO_WINDOW (m_widget))
2043 {
2044 org_x += m_widget->allocation.x;
2045 org_y += m_widget->allocation.y;
2046 }
362c6693 2047 }
47d67540 2048
1ecc4d80
RR
2049 wxPoint pt(GetClientAreaOrigin());
2050 org_x -= pt.x;
2051 org_y -= pt.y;
8bbe427f 2052
1ecc4d80
RR
2053 if (x) *x -= org_x;
2054 if (y) *y -= org_y;
362c6693 2055}
c801d85f 2056
debe6624 2057void wxWindow::Centre( int direction )
c801d85f 2058{
1ecc4d80 2059 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2060
1ecc4d80
RR
2061 int x = m_x;
2062 int y = m_y;
8bbe427f 2063
1ecc4d80
RR
2064 if (m_parent)
2065 {
2066 int p_w = 0;
2067 int p_h = 0;
2068 m_parent->GetSize( &p_w, &p_h );
2069 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
2070 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
2071 }
2072 else
2073 {
2074 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
2075 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
2076 }
8bbe427f 2077
1ecc4d80 2078 Move( x, y );
362c6693 2079}
c801d85f 2080
68dda785 2081void wxWindow::Fit()
c801d85f 2082{
1ecc4d80 2083 wxCHECK_RET( (m_widget != NULL), "invalid window" );
5e0aa05a 2084
1ecc4d80
RR
2085 int maxX = 0;
2086 int maxY = 0;
2087 wxNode *node = m_children.First();
2088 while (node)
2089 {
2090 wxWindow *win = (wxWindow *)node->Data();
2091 int wx, wy, ww, wh;
2092 win->GetPosition(&wx, &wy);
2093 win->GetSize(&ww, &wh);
2094 if (wx + ww > maxX) maxX = wx + ww;
2095 if (wy + wh > maxY) maxY = wy + wh;
2096
2097 node = node->Next();
2098 }
ff8bfdbb 2099
1ecc4d80 2100 SetClientSize(maxX + 7, maxY + 14);
362c6693 2101}
c801d85f 2102
2f2aa628
RR
2103void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
2104{
1ecc4d80 2105 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2106
1ecc4d80
RR
2107 m_minWidth = minW;
2108 m_minHeight = minH;
2109 m_maxWidth = maxW;
2110 m_maxHeight = maxH;
2f2aa628
RR
2111}
2112
c801d85f
KB
2113void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2114{
f04371f0 2115// if (GetAutoLayout()) Layout();
362c6693 2116}
c801d85f 2117
debe6624 2118bool wxWindow::Show( bool show )
c801d85f 2119{
1ecc4d80 2120 wxCHECK_MSG( (m_widget != NULL), FALSE, "invalid window" );
47d67540 2121
1ecc4d80
RR
2122 if (show)
2123 gtk_widget_show( m_widget );
2124 else
2125 gtk_widget_hide( m_widget );
ff8bfdbb 2126
1ecc4d80 2127 m_isShown = show;
ff8bfdbb 2128
1ecc4d80 2129 return TRUE;
362c6693 2130}
c801d85f 2131
debe6624 2132void wxWindow::Enable( bool enable )
c801d85f 2133{
1ecc4d80 2134 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2135
1ecc4d80 2136 m_isEnabled = enable;
ff8bfdbb 2137
1ecc4d80
RR
2138 gtk_widget_set_sensitive( m_widget, enable );
2139 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
362c6693 2140}
c801d85f 2141
68dda785 2142int wxWindow::GetCharHeight() const
c33c4050 2143{
1ecc4d80 2144 wxCHECK_MSG( (m_widget != NULL), 12, "invalid window" );
47d67540 2145
1ecc4d80 2146 wxCHECK_MSG( m_font.Ok(), 12, "invalid font" );
47d67540 2147
1ecc4d80 2148 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2149
1ecc4d80 2150 return font->ascent + font->descent;
c33c4050
RR
2151}
2152
68dda785 2153int wxWindow::GetCharWidth() const
c33c4050 2154{
1ecc4d80 2155 wxCHECK_MSG( (m_widget != NULL), 8, "invalid window" );
47d67540 2156
1ecc4d80 2157 wxCHECK_MSG( m_font.Ok(), 8, "invalid font" );
47d67540 2158
463c1fa1 2159 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2160
463c1fa1 2161 return gdk_string_width( font, "H" );
c33c4050
RR
2162}
2163
2164void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
2165 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
2166{
463c1fa1
RR
2167 wxFont fontToUse = m_font;
2168 if (theFont) fontToUse = *theFont;
47d67540 2169
1ecc4d80 2170 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
47d67540 2171
463c1fa1
RR
2172 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2173 if (x) (*x) = gdk_string_width( font, string );
2174 if (y) (*y) = font->ascent + font->descent;
2175 if (descent) (*descent) = font->descent;
2176 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2177}
2178
debe6624 2179void wxWindow::MakeModal( bool modal )
c801d85f 2180{
1ecc4d80 2181 return;
ff8bfdbb 2182
1ecc4d80
RR
2183 // Disable all other windows
2184 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
c801d85f 2185 {
1ecc4d80
RR
2186 wxNode *node = wxTopLevelWindows.First();
2187 while (node)
2188 {
2189 wxWindow *win = (wxWindow *)node->Data();
2190 if (win != this) win->Enable(!modal);
c801d85f 2191
1ecc4d80
RR
2192 node = node->Next();
2193 }
c801d85f 2194 }
c801d85f
KB
2195}
2196
b666df2c
RR
2197void wxWindow::OnKeyDown( wxKeyEvent &event )
2198{
2199 event.SetEventType( wxEVT_CHAR );
ff8bfdbb 2200
b666df2c
RR
2201 if (!GetEventHandler()->ProcessEvent( event ))
2202 {
2203 event.Skip();
2204 }
2205}
2206
68dda785 2207void wxWindow::SetFocus()
c801d85f 2208{
1ecc4d80 2209 wxCHECK_RET( (m_widget != NULL), "invalid window" );
ff8bfdbb 2210
463c1fa1
RR
2211 GtkWidget *connect_widget = GetConnectWidget();
2212 if (connect_widget)
c801d85f 2213 {
b292e2f5 2214 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2215 {
2216 gtk_widget_grab_focus (connect_widget);
2217 }
ff8bfdbb
VZ
2218 else if (GTK_IS_CONTAINER(connect_widget))
2219 {
2220 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2221 }
2222 else
2223 {
2224 }
362c6693 2225 }
362c6693 2226}
c801d85f 2227
b292e2f5
RR
2228wxWindow *wxWindow::FindFocus()
2229{
2230 return g_focusWindow;
2231}
2232
2233bool wxWindow::AcceptsFocus() const
2234{
2235 return IsEnabled() && IsShown() && m_acceptsFocus;
2236}
2237
68dda785 2238bool wxWindow::OnClose()
c801d85f 2239{
463c1fa1 2240 return TRUE;
362c6693 2241}
c801d85f
KB
2242
2243void wxWindow::AddChild( wxWindow *child )
2244{
1ecc4d80
RR
2245 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2246 wxCHECK_RET( (child != NULL), "invalid child" );
47d67540 2247
463c1fa1 2248 m_children.Append( child );
362c6693 2249}
c801d85f 2250
463c1fa1
RR
2251wxWindow *wxWindow::ReParent( wxWindow *newParent )
2252{
1ecc4d80 2253 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, "invalid window" );
ff8bfdbb 2254
1ecc4d80 2255 wxWindow *oldParent = GetParent();
8bbe427f 2256
1ecc4d80 2257 if (oldParent) oldParent->RemoveChild( this );
8bbe427f 2258
1ecc4d80 2259 gtk_widget_unparent( m_widget );
8bbe427f 2260
1ecc4d80
RR
2261 if (newParent)
2262 {
2263 newParent->AddChild( this );
2264 (newParent->m_insertCallback)( newParent, this );
2265 }
8bbe427f 2266
1ecc4d80 2267 return oldParent;
362c6693 2268}
c801d85f
KB
2269
2270void wxWindow::RemoveChild( wxWindow *child )
2271{
db1b4961 2272 m_children.DeleteObject( child );
463c1fa1 2273 child->m_parent = (wxWindow *) NULL;
362c6693 2274}
c801d85f
KB
2275
2276void wxWindow::SetReturnCode( int retCode )
2277{
463c1fa1 2278 m_retCode = retCode;
362c6693 2279}
c801d85f 2280
68dda785 2281int wxWindow::GetReturnCode()
c801d85f 2282{
463c1fa1 2283 return m_retCode;
362c6693 2284}
c801d85f 2285
68dda785 2286void wxWindow::Raise()
362c6693 2287{
1ecc4d80 2288 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2289
463c1fa1 2290 if (m_widget) gdk_window_raise( m_widget->window );
362c6693
RR
2291}
2292
68dda785 2293void wxWindow::Lower()
362c6693 2294{
1ecc4d80 2295 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2296
463c1fa1 2297 if (m_widget) gdk_window_lower( m_widget->window );
362c6693 2298}
c801d85f 2299
8bbe427f 2300wxEvtHandler *wxWindow::GetEventHandler() const
c801d85f 2301{
463c1fa1 2302 return m_eventHandler;
362c6693 2303}
c801d85f 2304
86b29a61 2305void wxWindow::SetEventHandler( wxEvtHandler *handler )
c801d85f 2306{
463c1fa1 2307 m_eventHandler = handler;
362c6693 2308}
c801d85f 2309
86b29a61
RR
2310void wxWindow::PushEventHandler(wxEvtHandler *handler)
2311{
463c1fa1
RR
2312 handler->SetNextHandler(GetEventHandler());
2313 SetEventHandler(handler);
86b29a61
RR
2314}
2315
2316wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
2317{
463c1fa1 2318 if (GetEventHandler())
e55ad60e 2319 {
463c1fa1
RR
2320 wxEvtHandler *handlerA = GetEventHandler();
2321 wxEvtHandler *handlerB = handlerA->GetNextHandler();
2322 handlerA->SetNextHandler((wxEvtHandler *) NULL);
2323 SetEventHandler(handlerB);
2324 if (deleteHandler)
2325 {
2326 delete handlerA;
2327 return (wxEvtHandler*) NULL;
2328 }
2329 else
2330 return handlerA;
2331 }
2332 else
2333 return (wxEvtHandler *) NULL;
86b29a61
RR
2334}
2335
68dda785 2336wxValidator *wxWindow::GetValidator()
c801d85f 2337{
463c1fa1 2338 return m_windowValidator;
362c6693 2339}
c801d85f 2340
6de97a3b 2341void wxWindow::SetValidator( const wxValidator& validator )
c801d85f 2342{
1ecc4d80
RR
2343 if (m_windowValidator) delete m_windowValidator;
2344 m_windowValidator = validator.Clone();
2345 if (m_windowValidator) m_windowValidator->SetWindow(this);
362c6693 2346}
c801d85f 2347
fd0eed64
RR
2348void wxWindow::SetClientObject( wxClientData *data )
2349{
1ecc4d80
RR
2350 if (m_clientObject) delete m_clientObject;
2351 m_clientObject = data;
fd0eed64
RR
2352}
2353
2354wxClientData *wxWindow::GetClientObject()
2355{
1ecc4d80 2356 return m_clientObject;
fd0eed64
RR
2357}
2358
2359void wxWindow::SetClientData( void *data )
2360{
1ecc4d80 2361 m_clientData = data;
fd0eed64
RR
2362}
2363
2364void *wxWindow::GetClientData()
2365{
1ecc4d80 2366 return m_clientData;
fd0eed64
RR
2367}
2368
68dda785 2369bool wxWindow::IsBeingDeleted()
c801d85f 2370{
1ecc4d80 2371 return FALSE;
362c6693 2372}
c801d85f
KB
2373
2374void wxWindow::SetId( wxWindowID id )
2375{
1ecc4d80 2376 m_windowId = id;
362c6693 2377}
c801d85f 2378
8bbe427f 2379wxWindowID wxWindow::GetId() const
c801d85f 2380{
1ecc4d80 2381 return m_windowId;
362c6693 2382}
c801d85f
KB
2383
2384void wxWindow::SetCursor( const wxCursor &cursor )
2385{
1ecc4d80 2386 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2387
1ecc4d80
RR
2388 if (cursor.Ok())
2389 {
2390 if (cursor == *m_cursor) return;
2391 *m_cursor = cursor;
2392 }
2393 else
2394 {
2395 *m_cursor = *wxSTANDARD_CURSOR;
2396 }
a3622daa 2397
1ecc4d80
RR
2398 if ((m_widget) && (m_widget->window))
2399 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
47d67540 2400
1ecc4d80
RR
2401 if ((m_wxwindow) && (m_wxwindow->window))
2402 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
362c6693 2403}
c801d85f 2404
4f22cf8d
RR
2405void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2406{
2407 // TODO
2408}
2409
debe6624 2410void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2411{
139adb6a 2412 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2413
139adb6a 2414 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2415 {
139adb6a
RR
2416 if (rect)
2417 {
2418 gdk_window_clear_area( m_wxwindow->window,
2419 rect->x, rect->y,
2420 rect->width,
2421 rect->height );
2422 }
2423 else
2424 {
1ecc4d80 2425 Clear();
139adb6a
RR
2426 }
2427 }
ff8bfdbb 2428
139adb6a
RR
2429 if (!rect)
2430 {
2431 if (m_wxwindow)
2432 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2433 else
139adb6a 2434 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2435 }
c801d85f 2436 else
139adb6a
RR
2437 {
2438 GdkRectangle gdk_rect;
2439 gdk_rect.x = rect->x;
2440 gdk_rect.y = rect->y;
2441 gdk_rect.width = rect->width;
2442 gdk_rect.height = rect->height;
2443
2444 if (m_wxwindow)
2445 gtk_widget_draw( m_wxwindow, &gdk_rect );
2446 else
2447 gtk_widget_draw( m_widget, &gdk_rect );
2448 }
362c6693 2449}
c801d85f 2450
8429bec1
RR
2451wxRegion wxWindow::GetUpdateRegion() const
2452{
2453 return m_updateRegion;
2454}
2455
2456bool wxWindow::IsExposed( int x, int y) const
c801d85f 2457{
1ecc4d80 2458 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
362c6693 2459}
c801d85f 2460
8429bec1
RR
2461bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2462{
1ecc4d80 2463 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
8429bec1
RR
2464}
2465
2466bool wxWindow::IsExposed( const wxPoint& pt ) const
2467{
1ecc4d80 2468 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
8429bec1
RR
2469}
2470
2471bool wxWindow::IsExposed( const wxRect& rect ) const
c801d85f 2472{
1ecc4d80 2473 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
362c6693 2474}
c801d85f 2475
68dda785 2476void wxWindow::Clear()
c801d85f 2477{
3bc755fc 2478 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2479
3bc755fc 2480 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
362c6693 2481}
c801d85f 2482
ff8bfdbb 2483#if wxUSE_TOOLTIPS
b1170810
RR
2484void wxWindow::SetToolTip( const wxString &tip )
2485{
301cd871
RR
2486 if (m_toolTip)
2487 {
2488 m_toolTip->SetTip( tip );
2489 }
2490 else
2491 {
ff8bfdbb 2492 SetToolTip( new wxToolTip( tip ) );
301cd871 2493 }
ff8bfdbb
VZ
2494
2495 // setting empty tooltip text does not remove the tooltip any more for
2496 // wxMSW compatibility - use SetToolTip((wxToolTip *)NULL) for this
b1170810
RR
2497}
2498
2499void wxWindow::SetToolTip( wxToolTip *tip )
2500{
301cd871
RR
2501 if (m_toolTip)
2502 {
2503 m_toolTip->SetTip( (char*) NULL );
2504 delete m_toolTip;
2505 }
ff8bfdbb 2506
b1170810 2507 m_toolTip = tip;
ff8bfdbb
VZ
2508
2509 if (m_toolTip)
2510 m_toolTip->Apply( this );
b1170810
RR
2511}
2512
301cd871 2513void wxWindow::ApplyToolTip( GtkTooltips *tips, const char *tip )
b1170810 2514{
301cd871
RR
2515 gtk_tooltips_set_tip( tips, GetConnectWidget(), tip, (gchar*) NULL );
2516}
ff8bfdbb 2517#endif // wxUSE_TOOLTIPS
b1170810 2518
68dda785 2519wxColour wxWindow::GetBackgroundColour() const
c801d85f 2520{
3bc755fc 2521 return m_backgroundColour;
362c6693 2522}
c801d85f
KB
2523
2524void wxWindow::SetBackgroundColour( const wxColour &colour )
2525{
3bc755fc 2526 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2527
3bc755fc 2528 if (m_backgroundColour == colour) return;
8bbe427f 2529
3bc755fc
RR
2530 m_backgroundColour = colour;
2531 if (!m_backgroundColour.Ok()) return;
8bbe427f 2532
3bc755fc
RR
2533 if (m_wxwindow)
2534 {
2535 GdkWindow *window = m_wxwindow->window;
2536 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2537 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2538 gdk_window_clear( window );
2539 }
8bbe427f 2540
ae0bdb01 2541 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2542 if (sysbg.Red() == colour.Red() &&
2543 sysbg.Green() == colour.Green() &&
ae0bdb01
RR
2544 sysbg.Blue() == colour.Blue())
2545 {
2546 m_backgroundColour = wxNullColour;
2547 ApplyWidgetStyle();
ff8bfdbb
VZ
2548 m_backgroundColour = sysbg;
2549 }
ae0bdb01
RR
2550 else
2551 {
2552 ApplyWidgetStyle();
2553 }
362c6693 2554}
c801d85f 2555
68dda785 2556wxColour wxWindow::GetForegroundColour() const
6de97a3b 2557{
3bc755fc 2558 return m_foregroundColour;
6de97a3b
RR
2559}
2560
2561void wxWindow::SetForegroundColour( const wxColour &colour )
2562{
3bc755fc 2563 wxCHECK_RET( m_widget != NULL, "invalid window" );
a81258be 2564
3bc755fc 2565 if (m_foregroundColour == colour) return;
8bbe427f 2566
3bc755fc
RR
2567 m_foregroundColour = colour;
2568 if (!m_foregroundColour.Ok()) return;
8bbe427f 2569
ae0bdb01 2570 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2571 if (sysbg.Red() == colour.Red() &&
2572 sysbg.Green() == colour.Green() &&
ae0bdb01
RR
2573 sysbg.Blue() == colour.Blue())
2574 {
2575 m_backgroundColour = wxNullColour;
2576 ApplyWidgetStyle();
ff8bfdbb
VZ
2577 m_backgroundColour = sysbg;
2578 }
ae0bdb01
RR
2579 else
2580 {
2581 ApplyWidgetStyle();
2582 }
58614078
RR
2583}
2584
2585GtkStyle *wxWindow::GetWidgetStyle()
2586{
1ecc4d80 2587 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2588
1ecc4d80
RR
2589 m_widgetStyle =
2590 gtk_style_copy(
2591 gtk_widget_get_style( m_widget ) );
8bbe427f 2592
1ecc4d80 2593 return m_widgetStyle;
58614078
RR
2594}
2595
2596void wxWindow::SetWidgetStyle()
2597{
1ecc4d80
RR
2598 GtkStyle *style = GetWidgetStyle();
2599
2600 gdk_font_unref( style->font );
2601 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2602
2603 if (m_foregroundColour.Ok())
2604 {
2605 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2606 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2607 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2608 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2609 }
2610
2611 if (m_backgroundColour.Ok())
2612 {
2613 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2614 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2615 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2616 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2617 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2618 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2619 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2620 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2621 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2622 }
a81258be
RR
2623}
2624
58614078 2625void wxWindow::ApplyWidgetStyle()
a81258be 2626{
6de97a3b
RR
2627}
2628
68dda785 2629bool wxWindow::Validate()
c801d85f 2630{
1ecc4d80 2631 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2632
1ecc4d80
RR
2633 wxNode *node = m_children.First();
2634 while (node)
2635 {
2636 wxWindow *child = (wxWindow *)node->Data();
2637 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
ff8bfdbb
VZ
2638 {
2639 return FALSE;
2640 }
1ecc4d80
RR
2641 node = node->Next();
2642 }
2643 return TRUE;
362c6693 2644}
c801d85f 2645
68dda785 2646bool wxWindow::TransferDataToWindow()
c801d85f 2647{
1ecc4d80 2648 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2649
1ecc4d80
RR
2650 wxNode *node = m_children.First();
2651 while (node)
c801d85f 2652 {
1ecc4d80
RR
2653 wxWindow *child = (wxWindow *)node->Data();
2654 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2655 !child->GetValidator()->TransferToWindow() )
2656 {
2657 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2658 return FALSE;
2659 }
2660 node = node->Next();
362c6693 2661 }
1ecc4d80 2662 return TRUE;
362c6693 2663}
c801d85f 2664
68dda785 2665bool wxWindow::TransferDataFromWindow()
c801d85f 2666{
1ecc4d80 2667 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2668
1ecc4d80
RR
2669 wxNode *node = m_children.First();
2670 while (node)
2671 {
2672 wxWindow *child = (wxWindow *)node->Data();
2673 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
ff8bfdbb
VZ
2674 {
2675 return FALSE;
2676 }
1ecc4d80
RR
2677 node = node->Next();
2678 }
2679 return TRUE;
362c6693 2680}
c801d85f 2681
bcf1fa6b
RR
2682void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2683{
1ecc4d80 2684 m_acceleratorTable = accel;
bcf1fa6b
RR
2685}
2686
c801d85f
KB
2687void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2688{
1ecc4d80 2689 TransferDataToWindow();
362c6693 2690}
c801d85f 2691
68dda785 2692void wxWindow::InitDialog()
c801d85f 2693{
1ecc4d80 2694 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2695
1ecc4d80
RR
2696 wxInitDialogEvent event(GetId());
2697 event.SetEventObject( this );
2698 GetEventHandler()->ProcessEvent(event);
362c6693 2699}
c801d85f 2700
30dea054
RR
2701static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2702{
1ecc4d80
RR
2703 menu->SetInvokingWindow( win );
2704 wxNode *node = menu->m_items.First();
2705 while (node)
2706 {
2707 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2708 if (menuitem->IsSubMenu())
2709 {
ff8bfdbb
VZ
2710 SetInvokingWindow( menuitem->GetSubMenu(), win );
2711 }
1ecc4d80
RR
2712 node = node->Next();
2713 }
362c6693 2714}
30dea054 2715
0c77152e
RR
2716static gint gs_pop_x = 0;
2717static gint gs_pop_y = 0;
2718
2719static void pop_pos_callback( GtkMenu *menu, gint *x, gint *y, wxWindow *win )
2720{
2721 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2722 *x = gs_pop_x;
2723 *y = gs_pop_y;
2724}
2725
2726bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
30dea054 2727{
1ecc4d80 2728 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2729
1ecc4d80 2730 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
8bbe427f 2731
1ecc4d80 2732 SetInvokingWindow( menu, this );
ff8bfdbb 2733
0c77152e
RR
2734 gs_pop_x = x;
2735 gs_pop_y = y;
ff8bfdbb 2736
1ecc4d80 2737 gtk_menu_popup(
47d67540 2738 GTK_MENU(menu->m_menu),
0c77152e
RR
2739 (GtkWidget *) NULL, // parent menu shell
2740 (GtkWidget *) NULL, // parent menu item
2741 (GtkMenuPositionFunc) pop_pos_callback,
2742 (gpointer) this, // client data
2743 0, // button used to activate it
2744 0 //gs_timeLastClick // the time of activation
47d67540 2745 );
1ecc4d80 2746 return TRUE;
30dea054
RR
2747}
2748
06cfab17 2749#if wxUSE_DRAG_AND_DROP
ac57418f 2750
c801d85f
KB
2751void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2752{
1ecc4d80 2753 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2754
1ecc4d80 2755 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2756
1ecc4d80 2757 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2758
1ecc4d80
RR
2759 if (m_dropTarget) delete m_dropTarget;
2760 m_dropTarget = dropTarget;
47d67540 2761
1ecc4d80 2762 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2763}
c801d85f
KB
2764
2765wxDropTarget *wxWindow::GetDropTarget() const
2766{
1ecc4d80 2767 return m_dropTarget;
362c6693 2768}
c801d85f 2769
ac57418f
RR
2770#endif
2771
68dda785 2772GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2773{
1ecc4d80
RR
2774 GtkWidget *connect_widget = m_widget;
2775 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2776
1ecc4d80 2777 return connect_widget;
e3e65dac 2778}
47d67540 2779
903f689b
RR
2780bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2781{
1ecc4d80
RR
2782 if (m_wxwindow) return (window == m_wxwindow->window);
2783 return (window == m_widget->window);
903f689b
RR
2784}
2785
c801d85f
KB
2786void wxWindow::SetFont( const wxFont &font )
2787{
1ecc4d80 2788 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2789
1ecc4d80
RR
2790 if (((wxFont*)&font)->Ok())
2791 m_font = font;
2792 else
2793 m_font = *wxSWISS_FONT;
c801d85f 2794
ae0bdb01 2795 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ff8bfdbb
VZ
2796 if (sysbg.Red() == m_backgroundColour.Red() &&
2797 sysbg.Green() == m_backgroundColour.Green() &&
ae0bdb01
RR
2798 sysbg.Blue() == m_backgroundColour.Blue())
2799 {
2800 m_backgroundColour = wxNullColour;
2801 ApplyWidgetStyle();
ff8bfdbb
VZ
2802 m_backgroundColour = sysbg;
2803 }
ae0bdb01
RR
2804 else
2805 {
2806 ApplyWidgetStyle();
2807 }
362c6693 2808}
c801d85f
KB
2809
2810void wxWindow::SetWindowStyleFlag( long flag )
2811{
1ecc4d80 2812 m_windowStyle = flag;
362c6693 2813}
c801d85f 2814
68dda785 2815long wxWindow::GetWindowStyleFlag() const
c801d85f 2816{
1ecc4d80 2817 return m_windowStyle;
362c6693 2818}
c801d85f 2819
68dda785 2820void wxWindow::CaptureMouse()
c801d85f 2821{
1ecc4d80 2822 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2823
1ecc4d80 2824 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
47d67540 2825
1ecc4d80
RR
2826 GtkWidget *connect_widget = GetConnectWidget();
2827 gtk_grab_add( connect_widget );
2828 gdk_pointer_grab( connect_widget->window, FALSE,
2829 (GdkEventMask)
2830 (GDK_BUTTON_PRESS_MASK |
2831 GDK_BUTTON_RELEASE_MASK |
2832 GDK_POINTER_MOTION_MASK),
ff8bfdbb
VZ
2833 (GdkWindow *) NULL,
2834 (GdkCursor *) NULL,
2835 GDK_CURRENT_TIME );
1ecc4d80 2836 g_capturing = TRUE;
362c6693 2837}
c801d85f 2838
68dda785 2839void wxWindow::ReleaseMouse()
c801d85f 2840{
1ecc4d80 2841 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2842
1ecc4d80 2843 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
47d67540 2844
1ecc4d80
RR
2845 GtkWidget *connect_widget = GetConnectWidget();
2846 gtk_grab_remove( connect_widget );
2847 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2848 g_capturing = FALSE;
362c6693 2849}
c801d85f
KB
2850
2851void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2852{
362c6693 2853}
c801d85f 2854
68dda785 2855wxString wxWindow::GetTitle() const
c801d85f 2856{
1ecc4d80 2857 return (wxString&)m_windowName;
362c6693 2858}
c801d85f 2859
68dda785 2860wxString wxWindow::GetLabel() const
c801d85f 2861{
1ecc4d80 2862 return GetTitle();
362c6693 2863}
c801d85f
KB
2864
2865void wxWindow::SetName( const wxString &name )
2866{
1ecc4d80 2867 m_windowName = name;
362c6693 2868}
c801d85f 2869
68dda785 2870wxString wxWindow::GetName() const
c801d85f 2871{
1ecc4d80 2872 return (wxString&)m_windowName;
362c6693 2873}
c801d85f 2874
68dda785 2875bool wxWindow::IsShown() const
c801d85f 2876{
1ecc4d80 2877 return m_isShown;
362c6693 2878}
c801d85f 2879
68dda785 2880bool wxWindow::IsRetained()
c801d85f 2881{
1ecc4d80 2882 return FALSE;
362c6693 2883}
c801d85f 2884
debe6624 2885wxWindow *wxWindow::FindWindow( long id )
c801d85f 2886{
1ecc4d80
RR
2887 if (id == m_windowId) return this;
2888 wxNode *node = m_children.First();
2889 while (node)
2890 {
2891 wxWindow *child = (wxWindow*)node->Data();
2892 wxWindow *res = child->FindWindow( id );
2893 if (res) return res;
2894 node = node->Next();
2895 }
2896 return (wxWindow *) NULL;
362c6693 2897}
c801d85f
KB
2898
2899wxWindow *wxWindow::FindWindow( const wxString& name )
2900{
1ecc4d80
RR
2901 if (name == m_windowName) return this;
2902 wxNode *node = m_children.First();
2903 while (node)
2904 {
2905 wxWindow *child = (wxWindow*)node->Data();
2906 wxWindow *res = child->FindWindow( name );
2907 if (res) return res;
2908 node = node->Next();
2909 }
2910 return (wxWindow *) NULL;
362c6693 2911}
c801d85f 2912
debe6624 2913void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2914 int range, bool refresh )
c801d85f 2915{
1ecc4d80 2916 wxCHECK_RET( m_widget != NULL, "invalid window" );
8bbe427f 2917
1ecc4d80 2918 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f 2919
1ecc4d80 2920 m_hasScrolling = TRUE;
47d67540 2921
1ecc4d80 2922 if (orient == wxHORIZONTAL)
cb43b372 2923 {
1ecc4d80
RR
2924 float fpos = (float)pos;
2925 float frange = (float)range;
2926 float fthumb = (float)thumbVisible;
2927 if (fpos > frange-fthumb) fpos = frange-fthumb;
2928 if (fpos < 0.0) fpos = 0.0;
2929
2930 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2931 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2932 {
2933 SetScrollPos( orient, pos, refresh );
2934 return;
2935 }
47d67540 2936
1ecc4d80 2937 m_oldHorizontalPos = fpos;
47d67540 2938
1ecc4d80
RR
2939 m_hAdjust->lower = 0.0;
2940 m_hAdjust->upper = frange;
2941 m_hAdjust->value = fpos;
2942 m_hAdjust->step_increment = 1.0;
2943 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2944 m_hAdjust->page_size = fthumb;
cb43b372 2945 }
1ecc4d80
RR
2946 else
2947 {
2948 float fpos = (float)pos;
2949 float frange = (float)range;
2950 float fthumb = (float)thumbVisible;
2951 if (fpos > frange-fthumb) fpos = frange-fthumb;
2952 if (fpos < 0.0) fpos = 0.0;
2953
2954 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2955 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2956 {
2957 SetScrollPos( orient, pos, refresh );
2958 return;
2959 }
47d67540 2960
1ecc4d80 2961 m_oldVerticalPos = fpos;
47d67540 2962
1ecc4d80
RR
2963 m_vAdjust->lower = 0.0;
2964 m_vAdjust->upper = frange;
2965 m_vAdjust->value = fpos;
2966 m_vAdjust->step_increment = 1.0;
2967 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2968 m_vAdjust->page_size = fthumb;
2969 }
47d67540 2970
1ecc4d80
RR
2971 if (m_wxwindow->window)
2972 {
2973 if (orient == wxHORIZONTAL)
2974 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2975 else
2976 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
47d67540 2977
1ecc4d80
RR
2978 gtk_widget_set_usize( m_widget, m_width, m_height );
2979 }
362c6693 2980}
c801d85f 2981
debe6624 2982void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 2983{
1ecc4d80
RR
2984 wxCHECK_RET( m_widget != NULL, "invalid window" );
2985
2986 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2987
2988 if (orient == wxHORIZONTAL)
2989 {
2990 float fpos = (float)pos;
2991 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2992 if (fpos < 0.0) fpos = 0.0;
2993 m_oldHorizontalPos = fpos;
2994
2995 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2996 m_hAdjust->value = fpos;
2997 }
2998 else
2999 {
3000 float fpos = (float)pos;
3001 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3002 if (fpos < 0.0) fpos = 0.0;
3003 m_oldVerticalPos = fpos;
ff8bfdbb 3004
1ecc4d80
RR
3005 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3006 m_vAdjust->value = fpos;
3007 }
47d67540 3008
1ecc4d80 3009 if (!m_isScrolling)
47d67540 3010 {
1ecc4d80
RR
3011 if (m_wxwindow->window)
3012 {
3013 if (orient == wxHORIZONTAL)
3014 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3015 else
3016 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3017 }
cb43b372 3018 }
362c6693 3019}
c801d85f 3020
debe6624 3021int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3022{
1ecc4d80 3023 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3024
1ecc4d80 3025 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
47d67540 3026
1ecc4d80
RR
3027 if (orient == wxHORIZONTAL)
3028 return (int)(m_hAdjust->page_size+0.5);
3029 else
3030 return (int)(m_vAdjust->page_size+0.5);
362c6693 3031}
c801d85f 3032
debe6624 3033int wxWindow::GetScrollPos( int orient ) const
c801d85f 3034{
1ecc4d80 3035 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3036
1ecc4d80 3037 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 3038
1ecc4d80
RR
3039 if (orient == wxHORIZONTAL)
3040 return (int)(m_hAdjust->value+0.5);
3041 else
3042 return (int)(m_vAdjust->value+0.5);
362c6693 3043}
c801d85f 3044
debe6624 3045int wxWindow::GetScrollRange( int orient ) const
c801d85f 3046{
1ecc4d80 3047 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 3048
1ecc4d80 3049 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 3050
1ecc4d80
RR
3051 if (orient == wxHORIZONTAL)
3052 return (int)(m_hAdjust->upper+0.5);
3053 else
3054 return (int)(m_vAdjust->upper+0.5);
362c6693 3055}
c801d85f 3056
debe6624 3057void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3058{
1ecc4d80 3059 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 3060
1ecc4d80 3061 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f
KB
3062
3063 int cw = 0;
3064 int ch = 0;
3065 GetClientSize( &cw, &ch );
47d67540 3066
c801d85f
KB
3067 int w = cw - abs(dx);
3068 int h = ch - abs(dy);
3069 if ((h < 0) || (w < 0))
3070 {
1ecc4d80
RR
3071 Refresh();
3072 return;
362c6693 3073 }
c801d85f
KB
3074 int s_x = 0;
3075 int s_y = 0;
3076 if (dx < 0) s_x = -dx;
3077 if (dy < 0) s_y = -dy;
3078 int d_x = 0;
3079 int d_y = 0;
3080 if (dx > 0) d_x = dx;
3081 if (dy > 0) d_y = dy;
8bbe427f 3082
32e9da8b
RR
3083 if (!m_scrollGC)
3084 {
1ecc4d80
RR
3085 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3086 gdk_gc_set_exposures( m_scrollGC, TRUE );
32e9da8b 3087 }
8bbe427f 3088
32e9da8b 3089 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
1ecc4d80 3090 m_wxwindow->window, s_x, s_y, w, h );
47d67540 3091
c801d85f
KB
3092 wxRect rect;
3093 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3094 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3095 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3096 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
47d67540 3097
c801d85f 3098 Refresh( TRUE, &rect );
362c6693 3099}
c801d85f
KB
3100
3101//-------------------------------------------------------------------------------------
3102// Layout
3103//-------------------------------------------------------------------------------------
3104
68dda785 3105wxLayoutConstraints *wxWindow::GetConstraints() const
c801d85f
KB
3106{
3107 return m_constraints;
362c6693 3108}
c801d85f
KB
3109
3110void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
3111{
3112 if (m_constraints)
3113 {
3114 UnsetConstraints(m_constraints);
3115 delete m_constraints;
3116 }
3117 m_constraints = constraints;
3118 if (m_constraints)
3119 {
3120 // Make sure other windows know they're part of a 'meaningful relationship'
3121 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3122 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3123 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3124 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3125 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3126 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3127 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3128 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3129 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3130 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3131 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3132 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3133 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3134 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3135 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3136 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3137 }
3138;
3139}
3140;
3141
debe6624 3142void wxWindow::SetAutoLayout( bool autoLayout )
c801d85f
KB
3143{
3144 m_autoLayout = autoLayout;
362c6693 3145}
c801d85f 3146
68dda785 3147bool wxWindow::GetAutoLayout() const
c801d85f
KB
3148{
3149 return m_autoLayout;
362c6693 3150}
c801d85f 3151
68dda785 3152wxSizer *wxWindow::GetSizer() const
c801d85f
KB
3153{
3154 return m_windowSizer;
362c6693 3155}
c801d85f
KB
3156
3157void wxWindow::SetSizerParent( wxWindow *win )
3158{
3159 m_sizerParent = win;
362c6693 3160}
c801d85f 3161
68dda785 3162wxWindow *wxWindow::GetSizerParent() const
c801d85f
KB
3163{
3164 return m_sizerParent;
362c6693 3165}
c801d85f
KB
3166
3167// This removes any dangling pointers to this window
3168// in other windows' constraintsInvolvedIn lists.
3169void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3170{
3171 if (c)
3172 {
3173 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3174 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3175 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3176 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3177 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3178 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3179 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3180 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3181 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3182 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3183 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3184 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3185 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3186 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3187 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3188 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3189 }
3190}
3191
3192// Back-pointer to other windows we're involved with, so if we delete
3193// this window, we must delete any constraints we're involved with.
3194void wxWindow::AddConstraintReference(wxWindow *otherWin)
3195{
3196 if (!m_constraintsInvolvedIn)
3197 m_constraintsInvolvedIn = new wxList;
3198 if (!m_constraintsInvolvedIn->Member(otherWin))
3199 m_constraintsInvolvedIn->Append(otherWin);
3200}
3201
3202// REMOVE back-pointer to other windows we're involved with.
3203void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3204{
3205 if (m_constraintsInvolvedIn)
3206 m_constraintsInvolvedIn->DeleteObject(otherWin);
3207}
3208
3209// Reset any constraints that mention this window
68dda785 3210void wxWindow::DeleteRelatedConstraints()
c801d85f
KB
3211{
3212 if (m_constraintsInvolvedIn)
3213 {
3214 wxNode *node = m_constraintsInvolvedIn->First();
3215 while (node)
3216 {
3217 wxWindow *win = (wxWindow *)node->Data();
3218 wxNode *next = node->Next();
3219 wxLayoutConstraints *constr = win->GetConstraints();
3220
3221 // Reset any constraints involving this window
3222 if (constr)
3223 {
3224 constr->left.ResetIfWin((wxWindow *)this);
3225 constr->top.ResetIfWin((wxWindow *)this);
3226 constr->right.ResetIfWin((wxWindow *)this);
3227 constr->bottom.ResetIfWin((wxWindow *)this);
3228 constr->width.ResetIfWin((wxWindow *)this);
3229 constr->height.ResetIfWin((wxWindow *)this);
3230 constr->centreX.ResetIfWin((wxWindow *)this);
3231 constr->centreY.ResetIfWin((wxWindow *)this);
3232 }
3233 delete node;
3234 node = next;
3235 }
3236 delete m_constraintsInvolvedIn;
c67daf87 3237 m_constraintsInvolvedIn = (wxList *) NULL;
c801d85f
KB
3238 }
3239}
3240
3241void wxWindow::SetSizer(wxSizer *sizer)
3242{
3243 m_windowSizer = sizer;
3244 if (sizer)
3245 sizer->SetSizerParent((wxWindow *)this);
3246}
3247
3248/*
3249 * New version
3250 */
3251
68dda785 3252bool wxWindow::Layout()
c801d85f
KB
3253{
3254 if (GetConstraints())
3255 {
3256 int w, h;
3257 GetClientSize(&w, &h);
3258 GetConstraints()->width.SetValue(w);
3259 GetConstraints()->height.SetValue(h);
3260 }
47d67540 3261
c801d85f
KB
3262 // If top level (one sizer), evaluate the sizer's constraints.
3263 if (GetSizer())
3264 {
3265 int noChanges;
3266 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3267 GetSizer()->LayoutPhase1(&noChanges);
3268 GetSizer()->LayoutPhase2(&noChanges);
3269 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3270 return TRUE;
3271 }
3272 else
3273 {
3274 // Otherwise, evaluate child constraints
3275 ResetConstraints(); // Mark all constraints as unevaluated
3276 DoPhase(1); // Just one phase need if no sizers involved
3277 DoPhase(2);
3278 SetConstraintSizes(); // Recursively set the real window sizes
3279 }
3280 return TRUE;
3281}
3282
3283
3284// Do a phase of evaluating constraints:
3285// the default behaviour. wxSizers may do a similar
3286// thing, but also impose their own 'constraints'
3287// and order the evaluation differently.
3288bool wxWindow::LayoutPhase1(int *noChanges)
3289{
3290 wxLayoutConstraints *constr = GetConstraints();
3291 if (constr)
3292 {
3293 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3294 }
3295 else
3296 return TRUE;
3297}
3298
3299bool wxWindow::LayoutPhase2(int *noChanges)
3300{
3301 *noChanges = 0;
47d67540 3302
c801d85f
KB
3303 // Layout children
3304 DoPhase(1);
3305 DoPhase(2);
3306 return TRUE;
3307}
3308
3309// Do a phase of evaluating child constraints
debe6624 3310bool wxWindow::DoPhase(int phase)
c801d85f
KB
3311{
3312 int noIterations = 0;
3313 int maxIterations = 500;
3314 int noChanges = 1;
3315 int noFailures = 0;
3316 wxList succeeded;
3317 while ((noChanges > 0) && (noIterations < maxIterations))
3318 {
3319 noChanges = 0;
3320 noFailures = 0;
8bbe427f 3321 wxNode *node = m_children.First();
c801d85f
KB
3322 while (node)
3323 {
3324 wxWindow *child = (wxWindow *)node->Data();
3325 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3326 {
3327 wxLayoutConstraints *constr = child->GetConstraints();
3328 if (constr)
3329 {
3330 if (succeeded.Member(child))
3331 {
3332 }
3333 else
3334 {
3335 int tempNoChanges = 0;
3336 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3337 noChanges += tempNoChanges;
3338 if (success)
3339 {
3340 succeeded.Append(child);
3341 }
3342 }
3343 }
3344 }
3345 node = node->Next();
3346 }
3347 noIterations ++;
3348 }
3349 return TRUE;
3350}
3351
68dda785 3352void wxWindow::ResetConstraints()
c801d85f
KB
3353{
3354 wxLayoutConstraints *constr = GetConstraints();
3355 if (constr)
3356 {
3357 constr->left.SetDone(FALSE);
3358 constr->top.SetDone(FALSE);
3359 constr->right.SetDone(FALSE);
3360 constr->bottom.SetDone(FALSE);
3361 constr->width.SetDone(FALSE);
3362 constr->height.SetDone(FALSE);
3363 constr->centreX.SetDone(FALSE);
3364 constr->centreY.SetDone(FALSE);
3365 }
db1b4961 3366 wxNode *node = m_children.First();
c801d85f
KB
3367 while (node)
3368 {
3369 wxWindow *win = (wxWindow *)node->Data();
3370 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3371 win->ResetConstraints();
3372 node = node->Next();
3373 }
3374}
3375
3376// Need to distinguish between setting the 'fake' size for
3377// windows and sizers, and setting the real values.
debe6624 3378void wxWindow::SetConstraintSizes(bool recurse)
c801d85f
KB
3379{
3380 wxLayoutConstraints *constr = GetConstraints();
3381 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3382 constr->width.GetDone() && constr->height.GetDone())
3383 {
3384 int x = constr->left.GetValue();
3385 int y = constr->top.GetValue();
3386 int w = constr->width.GetValue();
3387 int h = constr->height.GetValue();
3388
3389 // If we don't want to resize this window, just move it...
3390 if ((constr->width.GetRelationship() != wxAsIs) ||
3391 (constr->height.GetRelationship() != wxAsIs))
3392 {
3393 // Calls Layout() recursively. AAAGH. How can we stop that.
3394 // Simply take Layout() out of non-top level OnSizes.
3395 SizerSetSize(x, y, w, h);
3396 }
3397 else
3398 {
3399 SizerMove(x, y);
3400 }
3401 }
3402 else if (constr)
3403 {
3404 char *windowClass = this->GetClassInfo()->GetClassName();
3405
3406 wxString winName;
5e0aa05a 3407 if (GetName() == "")
3069ac4e 3408 winName = "unnamed";
5e0aa05a
VZ
3409 else
3410 winName = GetName();
ff8bfdbb
VZ
3411 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3412 (const char *)windowClass,
3413 (const char *)winName);
3069ac4e
RR
3414 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3415 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3416 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3417 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3418 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
c801d85f
KB
3419 }
3420
3421 if (recurse)
3422 {
db1b4961 3423 wxNode *node = m_children.First();
c801d85f
KB
3424 while (node)
3425 {
3426 wxWindow *win = (wxWindow *)node->Data();
3427 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3428 win->SetConstraintSizes();
3429 node = node->Next();
3430 }
3431 }
3432}
3433
3434// This assumes that all sizers are 'on' the same
3435// window, i.e. the parent of this window.
3436void wxWindow::TransformSizerToActual(int *x, int *y) const
3437{
3438 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
5e0aa05a 3439 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
c801d85f 3440 return;
47d67540 3441
c801d85f
KB
3442 int xp, yp;
3443 m_sizerParent->GetPosition(&xp, &yp);
3444 m_sizerParent->TransformSizerToActual(&xp, &yp);
3445 *x += xp;
3446 *y += yp;
3447}
3448
debe6624 3449void wxWindow::SizerSetSize(int x, int y, int w, int h)
c801d85f 3450{
5e0aa05a
VZ
3451 int xx = x;
3452 int yy = y;
c801d85f
KB
3453 TransformSizerToActual(&xx, &yy);
3454 SetSize(xx, yy, w, h);
3455}
3456
debe6624 3457void wxWindow::SizerMove(int x, int y)
c801d85f 3458{
5e0aa05a
VZ
3459 int xx = x;
3460 int yy = y;
c801d85f
KB
3461 TransformSizerToActual(&xx, &yy);
3462 Move(xx, yy);
3463}
3464
3465// Only set the size/position of the constraint (if any)
debe6624 3466void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
c801d85f
KB
3467{
3468 wxLayoutConstraints *constr = GetConstraints();
3469 if (constr)
3470 {
3471 if (x != -1)
3472 {
3473 constr->left.SetValue(x);
3474 constr->left.SetDone(TRUE);
3475 }
3476 if (y != -1)
3477 {
3478 constr->top.SetValue(y);
3479 constr->top.SetDone(TRUE);
3480 }
3481 if (w != -1)
3482 {
3483 constr->width.SetValue(w);
3484 constr->width.SetDone(TRUE);
3485 }
3486 if (h != -1)
3487 {
3488 constr->height.SetValue(h);
3489 constr->height.SetDone(TRUE);
3490 }
3491 }
3492}
3493
debe6624 3494void wxWindow::MoveConstraint(int x, int y)
c801d85f
KB
3495{
3496 wxLayoutConstraints *constr = GetConstraints();
3497 if (constr)
3498 {
3499 if (x != -1)
3500 {
3501 constr->left.SetValue(x);
3502 constr->left.SetDone(TRUE);
3503 }
3504 if (y != -1)
3505 {
3506 constr->top.SetValue(y);
3507 constr->top.SetDone(TRUE);
3508 }
3509 }
3510}
3511
3512void wxWindow::GetSizeConstraint(int *w, int *h) const
3513{
3514 wxLayoutConstraints *constr = GetConstraints();
3515 if (constr)
3516 {
3517 *w = constr->width.GetValue();
3518 *h = constr->height.GetValue();
3519 }
3520 else
3521 GetSize(w, h);
3522}
3523
3524void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3525{
3526 wxLayoutConstraints *constr = GetConstraints();
3527 if (constr)
3528 {
3529 *w = constr->width.GetValue();
3530 *h = constr->height.GetValue();
3531 }
3532 else
3533 GetClientSize(w, h);
3534}
3535
3536void wxWindow::GetPositionConstraint(int *x, int *y) const
3537{
b292e2f5
RR
3538 wxLayoutConstraints *constr = GetConstraints();
3539 if (constr)
c801d85f
KB
3540 {
3541 *x = constr->left.GetValue();
3542 *y = constr->top.GetValue();
3543 }
3544 else
3545 GetPosition(x, y);
3546}
3547