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