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