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