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