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