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