]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/window.cpp
fixed 64but bug with g_strEmpty initialization
[wxWidgets.git] / src / gtk / 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;
84efdbf1 809
cb43b372
RR
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
84efdbf1
RR
933 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
934 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
935
936 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
937 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
938
cb43b372
RR
939 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
940 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
941
c801d85f
KB
942 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
943 scroll_class->scrollbar_spacing = 0;
944
945 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
946
947 m_oldHorizontalPos = 0.0;
948 m_oldVerticalPos = 0.0;
949
950 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
951 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
952
cb43b372 953 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
5e0aa05a 954 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
cb43b372 955 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
5e0aa05a
VZ
956 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
957
cb43b372 958 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
5e0aa05a 959 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
cb43b372 960 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
5e0aa05a 961 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
c801d85f 962
cb43b372 963 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
c801d85f
KB
964
965 if (m_windowStyle & wxRAISED_BORDER)
966 {
967 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
968 }
969 else if (m_windowStyle & wxSUNKEN_BORDER)
970 {
971 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
972 }
973 else
974 {
975 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
362c6693 976 }
c801d85f
KB
977
978 m_wxwindow = gtk_myfixed_new();
979
66bd6b93
RR
980 if (m_wxwindow) GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
981
c801d85f
KB
982 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
983 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
984 else
985 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
986
987 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
988
989 // shut the viewport up
990 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
991 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
992
993 // I _really_ don't want scrollbars in the beginning
994 m_vAdjust->lower = 0.0;
995 m_vAdjust->upper = 1.0;
996 m_vAdjust->value = 0.0;
997 m_vAdjust->step_increment = 1.0;
998 m_vAdjust->page_increment = 1.0;
999 m_vAdjust->page_size = 5.0;
1000 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1001 m_hAdjust->lower = 0.0;
1002 m_hAdjust->upper = 1.0;
1003 m_hAdjust->value = 0.0;
1004 m_hAdjust->step_increment = 1.0;
1005 m_hAdjust->page_increment = 1.0;
1006 m_hAdjust->page_size = 5.0;
1007 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1008
1009 gtk_widget_show( m_wxwindow );
1010
1011 PostCreation();
1012
1013 Show( TRUE );
1014
1015 return TRUE;
362c6693 1016}
c801d85f
KB
1017
1018wxWindow::~wxWindow(void)
1019{
1020 m_hasVMT = FALSE;
1021
1022 if (m_pDropTarget) delete m_pDropTarget;
1023
1024 if (m_parent) m_parent->RemoveChild( this );
1025 if (m_widget) Show( FALSE );
1026
1027 DestroyChildren();
1028
1029 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1030
1031 if (m_widget) gtk_widget_destroy( m_widget );
1032
a3622daa 1033 wxDELETE(m_cursor);
c801d85f
KB
1034
1035 DeleteRelatedConstraints();
1036 if (m_constraints)
1037 {
1038 // This removes any dangling pointers to this window
1039 // in other windows' constraintsInvolvedIn lists.
1040 UnsetConstraints(m_constraints);
1041 delete m_constraints;
c67daf87 1042 m_constraints = (wxLayoutConstraints *) NULL;
c801d85f
KB
1043 }
1044 if (m_windowSizer)
1045 {
1046 delete m_windowSizer;
c67daf87 1047 m_windowSizer = (wxSizer *) NULL;
c801d85f
KB
1048 }
1049 // If this is a child of a sizer, remove self from parent
6de97a3b 1050 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
c801d85f
KB
1051
1052 // Just in case the window has been Closed, but
1053 // we're then deleting immediately: don't leave
1054 // dangling pointers.
1055 wxPendingDelete.DeleteObject(this);
1056
1057 // Just in case we've loaded a top-level window via
1058 // wxWindow::LoadNativeDialog but we weren't a dialog
1059 // class
1060 wxTopLevelWindows.DeleteObject(this);
1061
6de97a3b 1062 if (m_windowValidator) delete m_windowValidator;
362c6693 1063}
c801d85f 1064
debe6624
JS
1065void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1066 const wxPoint &pos, const wxSize &size,
1067 long style, const wxString &name )
c801d85f
KB
1068{
1069 if (m_needParent && (parent == NULL))
2f2aa628 1070 wxFatalError( "Need complete parent.", name );
c801d85f 1071
c67daf87 1072 m_widget = (GtkWidget *) NULL;
c801d85f
KB
1073 m_hasVMT = FALSE;
1074 m_parent = parent;
1075 m_children.DeleteContents( FALSE );
1076 m_x = (int)pos.x;
1077 m_y = (int)pos.y;
1078 m_width = size.x;
1079 if (m_width == -1) m_width = 20;
1080 m_height = size.y;
1081 if (m_height == -1) m_height = 20;
2f2aa628
RR
1082 m_minWidth = -1;
1083 m_minHeight = -1;
1084 m_maxWidth = -1;
1085 m_maxHeight = -1;
c801d85f
KB
1086 m_retCode = 0;
1087 m_eventHandler = this;
c801d85f
KB
1088 m_windowId = id;
1089 m_sizeSet = FALSE;
a3622daa
VZ
1090 if (m_cursor == NULL)
1091 m_cursor = new wxCursor( wxCURSOR_ARROW );
c801d85f
KB
1092 m_font = *wxSWISS_FONT;
1093 m_backgroundColour = wxWHITE;
1094 m_foregroundColour = wxBLACK;
1095 m_windowStyle = style;
1096 m_windowName = name;
c67daf87
UR
1097 m_constraints = (wxLayoutConstraints *) NULL;
1098 m_constraintsInvolvedIn = (wxList *) NULL;
1099 m_windowSizer = (wxSizer *) NULL;
1100 m_sizerParent = (wxWindow *) NULL;
c801d85f 1101 m_autoLayout = FALSE;
cb43b372
RR
1102 m_hasScrolling = FALSE;
1103 m_isScrolling = FALSE;
c67daf87 1104 m_pDropTarget = (wxDropTarget *) NULL;
33d0b396 1105 m_resizing = FALSE;
c67daf87 1106 m_windowValidator = (wxValidator *) NULL;
868a2826 1107 m_hasOwnStyle = FALSE;
c801d85f
KB
1108}
1109
1110void wxWindow::PostCreation(void)
1111{
1112 if (m_parent) m_parent->AddChild( this );
1113
c801d85f
KB
1114 if (m_wxwindow)
1115 {
1116 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1117 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1118
1119 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1120 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
362c6693 1121 }
c801d85f 1122
b4071e91
RR
1123 ConnectWidget( GetConnectWidget() );
1124
1125 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1126
1127 if (m_wxwindow)
1128 {
1129 gtk_widget_realize( m_wxwindow );
1130 gdk_gc_set_exposures( m_wxwindow->style->fg_gc[0], TRUE );
1131 }
1132
d8c83875 1133 SetCursor( *wxSTANDARD_CURSOR );
b4071e91
RR
1134
1135 m_hasVMT = TRUE;
1136}
1137
1138void wxWindow::ConnectWidget( GtkWidget *widget )
1139{
1140 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
c801d85f
KB
1141 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1142
b4071e91 1143 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
c801d85f
KB
1144 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1145
b4071e91 1146 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
c801d85f
KB
1147 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1148
b4071e91 1149 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
c801d85f
KB
1150 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1151
b4071e91 1152 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
c801d85f
KB
1153 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1154
b4071e91 1155 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
c801d85f
KB
1156 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1157
b4071e91 1158 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
c801d85f
KB
1159 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1160
b4071e91 1161 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
c801d85f 1162 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1163}
c801d85f
KB
1164
1165bool wxWindow::HasVMT(void)
1166{
1167 return m_hasVMT;
362c6693 1168}
c801d85f 1169
debe6624 1170bool wxWindow::Close( bool force )
c801d85f 1171{
e55ad60e
RR
1172 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1173
c801d85f
KB
1174 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1175 event.SetEventObject(this);
1176 event.SetForce(force);
1177
1178 return GetEventHandler()->ProcessEvent(event);
362c6693 1179}
c801d85f
KB
1180
1181bool wxWindow::Destroy(void)
1182{
e55ad60e
RR
1183 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1184
c801d85f
KB
1185 m_hasVMT = FALSE;
1186 delete this;
1187 return TRUE;
362c6693 1188}
c801d85f
KB
1189
1190bool wxWindow::DestroyChildren(void)
1191{
1192 if (GetChildren())
1193 {
1194 wxNode *node;
1195 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1196 {
1197 wxWindow *child;
1198 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1199 {
1200 delete child;
11026f7b 1201 if (GetChildren()->Member(child)) delete node;
362c6693
RR
1202 }
1203 }
1204 }
c801d85f 1205 return TRUE;
362c6693 1206}
c801d85f
KB
1207
1208void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1209{
1210 // are we to set fonts here ?
362c6693 1211}
c801d85f
KB
1212
1213void wxWindow::ImplementSetSize(void)
1214{
2f2aa628
RR
1215 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1216 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1217 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1218 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
c801d85f 1219 gtk_widget_set_usize( m_widget, m_width, m_height );
362c6693 1220}
c801d85f
KB
1221
1222void wxWindow::ImplementSetPosition(void)
1223{
66bd6b93
RR
1224 if (IS_KIND_OF(this,wxFrame) || IS_KIND_OF(this,wxDialog))
1225 {
1226 if ((m_x != -1) || (m_y != -1))
1227 gtk_widget_set_uposition( m_widget, m_x, m_y );
1228 return;
1229 }
1230
1a6944fd
RR
1231 if (!m_parent)
1232 {
2f2aa628 1233 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1a6944fd
RR
1234 return;
1235 }
1236
c801d85f
KB
1237 if ((m_parent) && (m_parent->m_wxwindow))
1238 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1a6944fd
RR
1239
1240 // Don't do anything for children of wxNotebook and wxMDIChildFrame
362c6693 1241}
c801d85f 1242
debe6624 1243void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1244{
e55ad60e
RR
1245 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1246
33d0b396
RR
1247 if (m_resizing) return; // I don't like recursions
1248 m_resizing = TRUE;
1249
c801d85f
KB
1250 int newX = x;
1251 int newY = y;
1252 int newW = width;
1253 int newH = height;
1254
1255 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1256 {
1257 if (newX == -1) newX = m_x;
1258 if (newY == -1) newY = m_y;
1259 if (newW == -1) newW = m_width;
1260 if (newH == -1) newH = m_height;
362c6693 1261 }
c801d85f
KB
1262
1263 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1264 {
1265 if (newW == -1) newW = 80;
362c6693 1266 }
c801d85f
KB
1267
1268 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1269 {
1270 if (newH == -1) newH = 26;
362c6693 1271 }
c801d85f
KB
1272
1273 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1274 {
1275 m_x = newX;
1276 m_y = newY;
1277 ImplementSetPosition();
362c6693 1278 }
c801d85f
KB
1279 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1280 {
1281 m_width = newW;
1282 m_height = newH;
1283 ImplementSetSize();
362c6693 1284 }
c801d85f
KB
1285 m_sizeSet = TRUE;
1286
1287 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1288 event.SetEventObject( this );
1289 ProcessEvent( event );
33d0b396
RR
1290
1291 m_resizing = FALSE;
362c6693 1292}
c801d85f 1293
debe6624 1294void wxWindow::SetSize( int width, int height )
c801d85f
KB
1295{
1296 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
362c6693 1297}
c801d85f 1298
debe6624 1299void wxWindow::Move( int x, int y )
c801d85f
KB
1300{
1301 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
362c6693 1302}
c801d85f
KB
1303
1304void wxWindow::GetSize( int *width, int *height ) const
1305{
e55ad60e
RR
1306 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1307
33d0b396
RR
1308 if (width) (*width) = m_width;
1309 if (height) (*height) = m_height;
362c6693 1310}
c801d85f 1311
debe6624 1312void wxWindow::SetClientSize( int width, int height )
c801d85f 1313{
e55ad60e
RR
1314 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1315
c801d85f
KB
1316 if (!m_wxwindow)
1317 {
1318 SetSize( width, height );
1319 }
1320 else
1321 {
1322 int dw = 0;
1323 int dh = 0;
1324
1325 if (!m_hasScrolling)
1326 {
1327/*
1328 do we have sunken dialogs ?
1329
1330 GtkStyleClass *window_class = m_wxwindow->style->klass;
1331
1332 dw += 2 * window_class->xthickness;
1333 dh += 2 * window_class->ythickness;
1334*/
1335 }
1336 else
1337 {
1338 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1339 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1340
1341 GtkWidget *viewport = scroll_window->viewport;
1342 GtkStyleClass *viewport_class = viewport->style->klass;
1343
1344 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1345 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1346
1347 if ((m_windowStyle & wxRAISED_BORDER) ||
2f2aa628 1348 (m_windowStyle & wxSUNKEN_BORDER))
c801d85f
KB
1349 {
1350 dw += 2 * viewport_class->xthickness;
1351 dh += 2 * viewport_class->ythickness;
362c6693 1352 }
c801d85f
KB
1353
1354 if (GTK_WIDGET_VISIBLE(vscrollbar))
1355 {
1356 dw += vscrollbar->allocation.width;
1357 dw += scroll_class->scrollbar_spacing;
362c6693 1358 }
c801d85f
KB
1359
1360 if (GTK_WIDGET_VISIBLE(hscrollbar))
1361 {
1362 dh += hscrollbar->allocation.height;
1363 dw += scroll_class->scrollbar_spacing;
362c6693
RR
1364 }
1365 }
c801d85f
KB
1366
1367 SetSize( width+dw, height+dh );
362c6693
RR
1368 }
1369}
c801d85f
KB
1370
1371void wxWindow::GetClientSize( int *width, int *height ) const
1372{
e55ad60e
RR
1373 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1374
c801d85f
KB
1375 if (!m_wxwindow)
1376 {
1377 if (width) (*width) = m_width;
1378 if (height) (*height) = m_height;
1379 }
1380 else
1381 {
1382 int dw = 0;
1383 int dh = 0;
1384
1385 if (!m_hasScrolling)
1386 {
1387/*
1388 do we have sunken dialogs ?
1389
1390 GtkStyleClass *window_class = m_wxwindow->style->klass;
1391
1392 dw += 2 * window_class->xthickness;
1393 dh += 2 * window_class->ythickness;
1394*/
1395 }
1396 else
1397 {
1398 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1399 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1400
1401 GtkWidget *viewport = scroll_window->viewport;
1402 GtkStyleClass *viewport_class = viewport->style->klass;
1403
1404 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1405 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1406
1407 if ((m_windowStyle & wxRAISED_BORDER) ||
2f2aa628 1408 (m_windowStyle & wxSUNKEN_BORDER))
c801d85f
KB
1409 {
1410 dw += 2 * viewport_class->xthickness;
1411 dh += 2 * viewport_class->ythickness;
362c6693 1412 }
c801d85f
KB
1413
1414 if (GTK_WIDGET_VISIBLE(vscrollbar))
1415 {
1416// dw += vscrollbar->allocation.width;
1417 dw += 15; // range.slider_width = 11 + 2*2pts edge
1418 dw += scroll_class->scrollbar_spacing;
362c6693 1419 }
c801d85f
KB
1420
1421 if (GTK_WIDGET_VISIBLE(hscrollbar))
1422 {
1423// dh += hscrollbar->allocation.height;
1424 dh += 15;
1425 dh += scroll_class->scrollbar_spacing;
362c6693
RR
1426 }
1427 }
c801d85f
KB
1428
1429 if (width) (*width) = m_width - dw;
1430 if (height) (*height) = m_height - dh;
362c6693
RR
1431 }
1432}
c801d85f
KB
1433
1434void wxWindow::GetPosition( int *x, int *y ) const
1435{
e55ad60e
RR
1436 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1437
c801d85f
KB
1438 if (x) (*x) = m_x;
1439 if (y) (*y) = m_y;
362c6693 1440}
c801d85f
KB
1441
1442void wxWindow::ClientToScreen( int *x, int *y )
1443{
e55ad60e
RR
1444 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1445
c67daf87 1446 GdkWindow *source = (GdkWindow *) NULL;
c801d85f
KB
1447 if (m_wxwindow)
1448 source = m_wxwindow->window;
1449 else
1450 source = m_widget->window;
1451
1452 int org_x = 0;
1453 int org_y = 0;
1454 gdk_window_get_origin( source, &org_x, &org_y );
1455
1456 if (!m_wxwindow)
1457 {
1458 if (GTK_WIDGET_NO_WINDOW (m_widget))
1459 {
1460 org_x += m_widget->allocation.x;
1461 org_y += m_widget->allocation.y;
362c6693
RR
1462 }
1463 }
c801d85f
KB
1464
1465 if (x) *x += org_x;
1466 if (y) *y += org_y;
362c6693 1467}
c801d85f
KB
1468
1469void wxWindow::ScreenToClient( int *x, int *y )
1470{
e55ad60e
RR
1471 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1472
c67daf87 1473 GdkWindow *source = (GdkWindow *) NULL;
c801d85f
KB
1474 if (m_wxwindow)
1475 source = m_wxwindow->window;
1476 else
1477 source = m_widget->window;
1478
1479 int org_x = 0;
1480 int org_y = 0;
1481 gdk_window_get_origin( source, &org_x, &org_y );
1482
1483 if (!m_wxwindow)
1484 {
1485 if (GTK_WIDGET_NO_WINDOW (m_widget))
1486 {
1487 org_x += m_widget->allocation.x;
1488 org_y += m_widget->allocation.y;
362c6693
RR
1489 }
1490 }
c801d85f
KB
1491
1492 if (x) *x -= org_x;
1493 if (y) *y -= org_y;
362c6693 1494}
c801d85f 1495
debe6624 1496void wxWindow::Centre( int direction )
c801d85f 1497{
e55ad60e
RR
1498 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1499
66bd6b93 1500 if (IS_KIND_OF(this,wxDialog) || IS_KIND_OF(this,wxFrame))
c801d85f 1501 {
d4c99d6f
RR
1502 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
1503 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
1504 ImplementSetPosition();
c801d85f
KB
1505 }
1506 else
1507 {
1508 if (m_parent)
1509 {
1510 int p_w = 0;
1511 int p_h = 0;
1512 m_parent->GetSize( &p_w, &p_h );
d4c99d6f
RR
1513 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (p_w - m_width) / 2;
1514 if (direction & wxVERTICAL == wxVERTICAL) m_y = (p_h - m_height) / 2;
1515 ImplementSetPosition();
362c6693 1516 }
c801d85f 1517 }
362c6693 1518}
c801d85f
KB
1519
1520void wxWindow::Fit(void)
1521{
e55ad60e
RR
1522 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1523
5e0aa05a
VZ
1524 int maxX = 0;
1525 int maxY = 0;
1526 wxNode *node = GetChildren()->First();
1527 while ( node )
1528 {
1529 wxWindow *win = (wxWindow *)node->Data();
1530 int wx, wy, ww, wh;
1531 win->GetPosition(&wx, &wy);
1532 win->GetSize(&ww, &wh);
1533 if ( wx + ww > maxX )
1534 maxX = wx + ww;
1535 if ( wy + wh > maxY )
1536 maxY = wy + wh;
1537
1538 node = node->Next();
1539 }
47908e25 1540 SetClientSize(maxX + 5, maxY + 10);
362c6693 1541}
c801d85f 1542
2f2aa628
RR
1543void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1544{
e55ad60e
RR
1545 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1546
2f2aa628
RR
1547 m_minWidth = minW;
1548 m_minHeight = minH;
1549 m_maxWidth = maxW;
1550 m_maxHeight = maxH;
1551}
1552
c801d85f
KB
1553void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1554{
da7f8ac4 1555 //if (GetAutoLayout()) Layout();
362c6693 1556}
c801d85f 1557
debe6624 1558bool wxWindow::Show( bool show )
c801d85f 1559{
e55ad60e
RR
1560 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1561
c801d85f
KB
1562 if (show)
1563 gtk_widget_show( m_widget );
1564 else
1565 gtk_widget_hide( m_widget );
1566 m_isShown = show;
1567 return TRUE;
362c6693 1568}
c801d85f 1569
debe6624 1570void wxWindow::Enable( bool enable )
c801d85f 1571{
e55ad60e
RR
1572 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1573
c801d85f
KB
1574 m_isEnabled = enable;
1575 gtk_widget_set_sensitive( m_widget, enable );
1576 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
362c6693 1577}
c801d85f 1578
c33c4050
RR
1579int wxWindow::GetCharHeight(void) const
1580{
e55ad60e
RR
1581 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1582
1583 if (!m_font.Ok())
1584 {
1585 wxFAIL_MSG( "invalid font" );
1586 return -1;
1587 }
1588
c33c4050
RR
1589 GdkFont *font = m_font.GetInternalFont( 1.0 );
1590 return font->ascent + font->descent;
1591}
1592
1593int wxWindow::GetCharWidth(void) const
1594{
e55ad60e
RR
1595 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1596
1597 if (!m_font.Ok())
1598 {
1599 wxFAIL_MSG( "invalid font" );
1600 return -1;
1601 }
1602
c33c4050
RR
1603 GdkFont *font = m_font.GetInternalFont( 1.0 );
1604 return gdk_string_width( font, "H" );
1605}
1606
1607void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1608 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1609{
e55ad60e
RR
1610 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1611
c33c4050
RR
1612 wxFont fontToUse = m_font;
1613 if (theFont) fontToUse = *theFont;
1614
e55ad60e
RR
1615 if (!fontToUse.Ok())
1616 {
1617 wxFAIL_MSG( "invalid font" );
1618 return;
1619 }
1620 wxASSERT_MSG( (m_font.Ok()), "invalid font" );
1621
c33c4050 1622 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
66c135f3 1623 if (x) (*x) = gdk_string_width( font, string );
c33c4050
RR
1624 if (y) (*y) = font->ascent + font->descent;
1625 if (descent) (*descent) = font->descent;
1626 if (externalLeading) (*externalLeading) = 0; // ??
1627}
1628
debe6624 1629void wxWindow::MakeModal( bool modal )
c801d85f
KB
1630{
1631 return;
1632 // Disable all other windows
1633 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1634 {
1635 wxNode *node = wxTopLevelWindows.First();
1636 while (node)
1637 {
1638 wxWindow *win = (wxWindow *)node->Data();
1639 if (win != this)
1640 win->Enable(!modal);
1641
1642 node = node->Next();
1643 }
1644 }
1645}
1646
1647void wxWindow::SetFocus(void)
1648{
e55ad60e
RR
1649 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1650
30dea054 1651 GtkWidget *connect_widget = GetConnectWidget();
c801d85f
KB
1652 if (connect_widget)
1653 {
1654 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1655 {
1656 gtk_widget_grab_focus (connect_widget);
362c6693
RR
1657 }
1658 }
1659}
c801d85f
KB
1660
1661bool wxWindow::OnClose(void)
1662{
c801d85f 1663 return TRUE;
362c6693 1664}
c801d85f
KB
1665
1666void wxWindow::AddChild( wxWindow *child )
1667{
e55ad60e
RR
1668 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1669 wxASSERT_MSG( (m_wxwindow != NULL), "window need client area" );
1670 wxASSERT_MSG( (child != NULL), "invalid child" );
1671 wxASSERT_MSG( (child->m_widget != NULL), "invalid child" );
1672
c801d85f
KB
1673 // Addchild is (often) called before the program
1674 // has left the parents constructor so that no
1675 // virtual tables work yet. The approach below
1676 // practically imitates virtual tables, i.e. it
1677 // implements a different AddChild() behaviour
1678 // for wxFrame, wxDialog, wxWindow and
1679 // wxMDIParentFrame.
1680
46dc76ba
RR
1681 // wxFrame and wxDialog as children aren't placed into the parents
1682
d4c99d6f
RR
1683 if (( IS_KIND_OF(child,wxFrame) || IS_KIND_OF(child,wxDialog) ) &&
1684 (!IS_KIND_OF(child,wxMDIChildFrame)))
46dc76ba
RR
1685 {
1686 m_children.Append( child );
1687
1688 if ((child->m_x != -1) && (child->m_y != -1))
1689 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1690
1691 return;
1692 }
1693
1694 // In the case of an wxMDIChildFrame descendant, we use the
1695 // client windows's AddChild()
1696
d4c99d6f 1697 if (IS_KIND_OF(this,wxMDIParentFrame))
c801d85f 1698 {
d4c99d6f 1699 if (IS_KIND_OF(child,wxMDIChildFrame))
c801d85f
KB
1700 {
1701 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1702 if (client)
1703 {
1704 client->AddChild( child );
1705 return;
46dc76ba
RR
1706 }
1707 }
1708 }
7f4dc78d 1709
46dc76ba 1710 // wxNotebook is very special, so it has a private AddChild()
33d0b396 1711
d4c99d6f 1712 if (IS_KIND_OF(this,wxNotebook))
7f4dc78d 1713 {
53b28675 1714 wxNotebook *tab = (wxNotebook*)this;
7f4dc78d
RR
1715 tab->AddChild( child );
1716 return;
46dc76ba 1717 }
7f4dc78d 1718
46dc76ba
RR
1719 // wxFrame has a private AddChild
1720
47908e25 1721 if (IS_KIND_OF(this,wxFrame) && !IS_KIND_OF(this,wxMDIChildFrame))
c801d85f 1722 {
46dc76ba
RR
1723 wxFrame *frame = (wxFrame*)this;
1724 frame->AddChild( child );
1725 return;
c801d85f 1726 }
46dc76ba
RR
1727
1728 // All the rest
1729
1730 m_children.Append( child );
d4c99d6f
RR
1731 if (m_wxwindow) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget,
1732 child->m_x, child->m_y );
e3e65dac 1733
c801d85f 1734 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
362c6693 1735}
c801d85f
KB
1736
1737wxList *wxWindow::GetChildren(void)
1738{
1739 return (&m_children);
362c6693 1740}
c801d85f
KB
1741
1742void wxWindow::RemoveChild( wxWindow *child )
1743{
1744 if (GetChildren())
e55ad60e 1745 GetChildren()->DeleteObject( child );
c67daf87 1746 child->m_parent = (wxWindow *) NULL;
362c6693 1747}
c801d85f
KB
1748
1749void wxWindow::SetReturnCode( int retCode )
1750{
1751 m_retCode = retCode;
362c6693 1752}
c801d85f
KB
1753
1754int wxWindow::GetReturnCode(void)
1755{
1756 return m_retCode;
362c6693 1757}
c801d85f 1758
362c6693
RR
1759void wxWindow::Raise(void)
1760{
e55ad60e
RR
1761 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1762
362c6693
RR
1763 if (m_widget) gdk_window_raise( m_widget->window );
1764}
1765
1766void wxWindow::Lower(void)
1767{
e55ad60e
RR
1768 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1769
362c6693
RR
1770 if (m_widget) gdk_window_lower( m_widget->window );
1771}
c801d85f
KB
1772
1773wxEvtHandler *wxWindow::GetEventHandler(void)
1774{
1775 return m_eventHandler;
362c6693 1776}
c801d85f 1777
86b29a61 1778void wxWindow::SetEventHandler( wxEvtHandler *handler )
c801d85f
KB
1779{
1780 m_eventHandler = handler;
362c6693 1781}
c801d85f 1782
86b29a61
RR
1783void wxWindow::PushEventHandler(wxEvtHandler *handler)
1784{
e55ad60e
RR
1785 handler->SetNextHandler(GetEventHandler());
1786 SetEventHandler(handler);
86b29a61
RR
1787}
1788
1789wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1790{
e55ad60e
RR
1791 if (GetEventHandler())
1792 {
1793 wxEvtHandler *handlerA = GetEventHandler();
1794 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1795 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1796 SetEventHandler(handlerB);
1797 if (deleteHandler)
1798 {
1799 delete handlerA;
1800 return (wxEvtHandler*) NULL;
1801 }
1802 else
1803 return handlerA;
1804 }
1805 else
1806 return (wxEvtHandler *) NULL;
86b29a61
RR
1807}
1808
c801d85f
KB
1809wxValidator *wxWindow::GetValidator(void)
1810{
1811 return m_windowValidator;
362c6693 1812}
c801d85f 1813
6de97a3b 1814void wxWindow::SetValidator( const wxValidator& validator )
c801d85f 1815{
6de97a3b
RR
1816 if (m_windowValidator) delete m_windowValidator;
1817 m_windowValidator = validator.Clone();
1818 if (m_windowValidator) m_windowValidator->SetWindow(this);
362c6693 1819}
c801d85f
KB
1820
1821bool wxWindow::IsBeingDeleted(void)
1822{
1823 return FALSE;
362c6693 1824}
c801d85f
KB
1825
1826void wxWindow::SetId( wxWindowID id )
1827{
1828 m_windowId = id;
362c6693 1829}
c801d85f
KB
1830
1831wxWindowID wxWindow::GetId(void)
1832{
1833 return m_windowId;
362c6693 1834}
c801d85f
KB
1835
1836void wxWindow::SetCursor( const wxCursor &cursor )
1837{
e55ad60e
RR
1838 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1839
d8c83875
RR
1840 if (m_cursor == NULL)
1841 {
1842 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1843 m_cursor = new wxCursor( wxCURSOR_ARROW );
1844 }
1845
1846 if (cursor.Ok())
1847 {
1848 if (*((wxCursor*)&cursor) == m_cursor) return;
1849 *m_cursor = cursor;
1850 }
1851 else
1852 {
1853 *m_cursor = *wxSTANDARD_CURSOR;
1854 }
a3622daa 1855
d8c83875 1856 if ((m_widget) && (m_widget->window))
c801d85f 1857 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
d8c83875
RR
1858
1859 if ((m_wxwindow) && (m_wxwindow->window))
c801d85f 1860 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
362c6693 1861}
c801d85f 1862
debe6624 1863void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 1864{
e55ad60e
RR
1865 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1866
c801d85f
KB
1867 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1868 {
1869 if (rect)
1870 gdk_window_clear_area( m_wxwindow->window,
1871 rect->x,
d4c99d6f
RR
1872 rect->y,
1873 rect->width,
1874 rect->height );
c801d85f 1875 else
30dea054 1876 Clear();
362c6693 1877 }
c801d85f
KB
1878 if (!rect)
1879 {
1880 if (m_wxwindow)
1881 {
c801d85f
KB
1882 int w = 0;
1883 int h = 0;
1884 GetClientSize( &w, &h );
1885
1886 GdkRectangle gdk_rect;
11026f7b
RR
1887 gdk_rect.x = 0;
1888 gdk_rect.y = 0;
c801d85f
KB
1889 gdk_rect.width = w;
1890 gdk_rect.height = h;
1891 gtk_widget_draw( m_wxwindow, &gdk_rect );
362c6693 1892 }
c801d85f
KB
1893 }
1894 else
1895 {
1896 GdkRectangle gdk_rect;
1897 gdk_rect.x = rect->x;
1898 gdk_rect.y = rect->y;
1899 gdk_rect.width = rect->width;
1900 gdk_rect.height = rect->height;
d4c99d6f 1901
c801d85f
KB
1902 if (m_wxwindow)
1903 gtk_widget_draw( m_wxwindow, &gdk_rect );
1904 else
1905 gtk_widget_draw( m_widget, &gdk_rect );
362c6693
RR
1906 }
1907}
c801d85f 1908
8429bec1
RR
1909wxRegion wxWindow::GetUpdateRegion() const
1910{
1911 return m_updateRegion;
1912}
1913
1914bool wxWindow::IsExposed( int x, int y) const
c801d85f
KB
1915{
1916 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
362c6693 1917}
c801d85f 1918
8429bec1
RR
1919bool wxWindow::IsExposed( int x, int y, int w, int h ) const
1920{
1921 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
1922}
1923
1924bool wxWindow::IsExposed( const wxPoint& pt ) const
1925{
1926 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
1927}
1928
1929bool wxWindow::IsExposed( const wxRect& rect ) const
c801d85f 1930{
8429bec1 1931 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
362c6693 1932}
c801d85f
KB
1933
1934void wxWindow::Clear(void)
1935{
e55ad60e
RR
1936 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1937
c801d85f 1938 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
362c6693 1939}
c801d85f
KB
1940
1941wxColour wxWindow::GetBackgroundColour(void) const
1942{
1943 return m_backgroundColour;
362c6693 1944}
c801d85f
KB
1945
1946void wxWindow::SetBackgroundColour( const wxColour &colour )
1947{
e55ad60e
RR
1948 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1949
c801d85f
KB
1950 m_backgroundColour = colour;
1951 if (m_wxwindow)
1952 {
1953 m_backgroundColour.CalcPixel( m_wxwindow->style->colormap );
1954 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
1955 gdk_window_clear( m_wxwindow->window );
362c6693 1956 }
c801d85f 1957 // do something ?
362c6693 1958}
c801d85f 1959
6de97a3b
RR
1960wxColour wxWindow::GetForegroundColour(void) const
1961{
1962 return m_foregroundColour;
1963}
1964
1965void wxWindow::SetForegroundColour( const wxColour &colour )
1966{
1967 m_foregroundColour = colour;
1968}
1969
c801d85f
KB
1970bool wxWindow::Validate(void)
1971{
e55ad60e
RR
1972 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1973
c801d85f
KB
1974 wxNode *node = GetChildren()->First();
1975 while (node)
1976 {
1977 wxWindow *child = (wxWindow *)node->Data();
1978 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
1979 { return FALSE; }
1980 node = node->Next();
362c6693 1981 }
c801d85f 1982 return TRUE;
362c6693 1983}
c801d85f
KB
1984
1985bool wxWindow::TransferDataToWindow(void)
1986{
e55ad60e
RR
1987 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1988
c801d85f
KB
1989 wxNode *node = GetChildren()->First();
1990 while (node)
1991 {
1992 wxWindow *child = (wxWindow *)node->Data();
1993 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
5e0aa05a 1994 !child->GetValidator()->TransferToWindow() )
c801d85f 1995 {
1a5a8367 1996 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
c801d85f 1997 return FALSE;
362c6693 1998 }
c801d85f 1999 node = node->Next();
362c6693 2000 }
c801d85f 2001 return TRUE;
362c6693 2002}
c801d85f
KB
2003
2004bool wxWindow::TransferDataFromWindow(void)
2005{
e55ad60e
RR
2006 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2007
c801d85f
KB
2008 wxNode *node = GetChildren()->First();
2009 while (node)
2010 {
2011 wxWindow *child = (wxWindow *)node->Data();
2012 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2013 { return FALSE; }
2014 node = node->Next();
2015 }
2016 return TRUE;
362c6693 2017}
c801d85f 2018
bcf1fa6b
RR
2019void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2020{
2021 m_acceleratorTable = accel;
2022}
2023
c801d85f
KB
2024void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2025{
2026 TransferDataToWindow();
362c6693 2027}
c801d85f
KB
2028
2029void wxWindow::InitDialog(void)
2030{
e55ad60e
RR
2031 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2032
c801d85f
KB
2033 wxInitDialogEvent event(GetId());
2034 event.SetEventObject( this );
2035 GetEventHandler()->ProcessEvent(event);
362c6693 2036}
c801d85f 2037
30dea054
RR
2038static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2039{
2040 menu->SetInvokingWindow( win );
2041 wxNode *node = menu->m_items.First();
2042 while (node)
2043 {
2044 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2045 if (menuitem->IsSubMenu())
2046 SetInvokingWindow( menuitem->GetSubMenu(), win );
2047 node = node->Next();
362c6693
RR
2048 }
2049}
30dea054
RR
2050
2051bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2052{
e55ad60e
RR
2053 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2054
30dea054 2055 SetInvokingWindow( menu, this );
c67daf87 2056 gtk_menu_popup( GTK_MENU(menu->m_menu), (GtkWidget *) NULL, (GtkWidget *) NULL, (GtkMenuPositionFunc) NULL, NULL, 0, 0 );
30dea054
RR
2057 return TRUE;
2058}
2059
c801d85f
KB
2060void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2061{
e55ad60e
RR
2062 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2063
30dea054 2064 GtkWidget *dnd_widget = GetConnectWidget();
e3e65dac 2065
a60c99e6 2066 DisconnectDnDWidget( dnd_widget );
e3e65dac 2067
a60c99e6 2068 if (m_pDropTarget) delete m_pDropTarget;
c801d85f 2069 m_pDropTarget = dropTarget;
a60c99e6
RR
2070
2071 ConnectDnDWidget( dnd_widget );
362c6693 2072}
c801d85f
KB
2073
2074wxDropTarget *wxWindow::GetDropTarget() const
2075{
2076 return m_pDropTarget;
362c6693 2077}
c801d85f 2078
a60c99e6
RR
2079void wxWindow::ConnectDnDWidget( GtkWidget *widget )
2080{
2081 if (!m_pDropTarget) return;
2082
2083 m_pDropTarget->RegisterWidget( widget );
2084
2085 gtk_signal_connect( GTK_OBJECT(widget), "drop_data_available_event",
2086 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2087}
2088
2089void wxWindow::DisconnectDnDWidget( GtkWidget *widget )
2090{
2091 if (!m_pDropTarget) return;
2092
2093 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
2094 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2095
2096 m_pDropTarget->UnregisterWidget( widget );
2097}
2098
30dea054 2099GtkWidget* wxWindow::GetConnectWidget(void)
e3e65dac
RR
2100{
2101 GtkWidget *connect_widget = m_widget;
2102 if (m_wxwindow) connect_widget = m_wxwindow;
2103
2104 return connect_widget;
2105}
2106
903f689b
RR
2107bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2108{
2109 if (m_wxwindow) return (window == m_wxwindow->window);
2110 return (window == m_widget->window);
2111}
2112
c801d85f
KB
2113void wxWindow::SetFont( const wxFont &font )
2114{
e55ad60e
RR
2115 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2116
3f659fd6 2117 if (((wxFont*)&font)->Ok())
560b92f5
JS
2118 m_font = font;
2119 else
2120 m_font = *wxSWISS_FONT;
2121
3f659fd6 2122 GtkStyle *style = (GtkStyle*) NULL;
868a2826
RR
2123 if (!m_hasOwnStyle)
2124 {
2125 m_hasOwnStyle = TRUE;
2126 style = gtk_style_copy( gtk_widget_get_style( m_widget ) );
2127 }
2128 else
2129 {
2130 style = gtk_widget_get_style( m_widget );
2131 }
c801d85f 2132
868a2826
RR
2133 gdk_font_unref( style->font );
2134 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2135
2136 gtk_widget_set_style( m_widget, style );
362c6693 2137}
c801d85f
KB
2138
2139wxFont *wxWindow::GetFont(void)
2140{
2141 return &m_font;
362c6693 2142}
c801d85f
KB
2143
2144void wxWindow::SetWindowStyleFlag( long flag )
2145{
2146 m_windowStyle = flag;
362c6693 2147}
c801d85f
KB
2148
2149long wxWindow::GetWindowStyleFlag(void) const
2150{
2151 return m_windowStyle;
362c6693 2152}
c801d85f
KB
2153
2154void wxWindow::CaptureMouse(void)
2155{
e55ad60e
RR
2156 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2157
2158 wxASSERT_MSG( (g_capturing == FALSE), "CaptureMouse called twice" );
2159
30dea054 2160 GtkWidget *connect_widget = GetConnectWidget();
c801d85f
KB
2161 gtk_grab_add( connect_widget );
2162 gdk_pointer_grab ( connect_widget->window, FALSE,
2163 (GdkEventMask)
5e0aa05a
VZ
2164 (GDK_BUTTON_PRESS_MASK |
2165 GDK_BUTTON_RELEASE_MASK |
2166 GDK_POINTER_MOTION_MASK),
c67daf87 2167 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
6987a6c3 2168 g_capturing = TRUE;
362c6693 2169}
c801d85f
KB
2170
2171void wxWindow::ReleaseMouse(void)
2172{
e55ad60e
RR
2173 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2174
2175 wxASSERT_MSG( (g_capturing == TRUE), "ReleaseMouse called twice" );
2176
30dea054 2177 GtkWidget *connect_widget = GetConnectWidget();
c801d85f
KB
2178 gtk_grab_remove( connect_widget );
2179 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
6987a6c3 2180 g_capturing = FALSE;
362c6693 2181}
c801d85f
KB
2182
2183void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2184{
362c6693 2185}
c801d85f
KB
2186
2187wxString wxWindow::GetTitle(void) const
2188{
2189 return (wxString&)m_windowName;
362c6693 2190}
c801d85f
KB
2191
2192wxString wxWindow::GetLabel(void) const
2193{
2194 return GetTitle();
362c6693 2195}
c801d85f
KB
2196
2197void wxWindow::SetName( const wxString &name )
2198{
2199 m_windowName = name;
362c6693 2200}
c801d85f
KB
2201
2202wxString wxWindow::GetName(void) const
2203{
2204 return (wxString&)m_windowName;
362c6693 2205}
c801d85f 2206
7fd1d163 2207bool wxWindow::IsShown(void) const
c801d85f
KB
2208{
2209 return m_isShown;
362c6693 2210}
c801d85f
KB
2211
2212bool wxWindow::IsRetained(void)
2213{
2214 return FALSE;
362c6693 2215}
c801d85f 2216
debe6624 2217wxWindow *wxWindow::FindWindow( long id )
c801d85f
KB
2218{
2219 if (id == m_windowId) return this;
2220 wxNode *node = m_children.First();
2221 while (node)
2222 {
2223 wxWindow *child = (wxWindow*)node->Data();
2224 wxWindow *res = child->FindWindow( id );
2225 if (res) return res;
2226 node = node->Next();
362c6693 2227 }
c67daf87 2228 return (wxWindow *) NULL;
362c6693 2229}
c801d85f
KB
2230
2231wxWindow *wxWindow::FindWindow( const wxString& name )
2232{
2233 if (name == m_windowName) return this;
2234 wxNode *node = m_children.First();
2235 while (node)
2236 {
2237 wxWindow *child = (wxWindow*)node->Data();
2238 wxWindow *res = child->FindWindow( name );
2239 if (res) return res;
2240 node = node->Next();
362c6693 2241 }
c67daf87 2242 return (wxWindow *) NULL;
362c6693 2243}
c801d85f 2244
debe6624 2245void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2246 int range, bool refresh )
c801d85f 2247{
e55ad60e
RR
2248 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2249
2250 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2251
c801d85f
KB
2252 if (!m_wxwindow) return;
2253
2254 if (orient == wxHORIZONTAL)
2255 {
2256 float fpos = (float)pos;
c801d85f
KB
2257 float frange = (float)range;
2258 float fthumb = (float)thumbVisible;
2259
cb43b372
RR
2260 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2261 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2262 {
2263 SetScrollPos( orient, pos, refresh );
c801d85f 2264 return;
cb43b372 2265 }
c801d85f 2266
cb43b372
RR
2267 m_oldHorizontalPos = fpos;
2268
c801d85f
KB
2269 m_hAdjust->lower = 0.0;
2270 m_hAdjust->upper = frange;
2271 m_hAdjust->value = fpos;
2272 m_hAdjust->step_increment = 1.0;
84efdbf1 2273 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
c801d85f
KB
2274 m_hAdjust->page_size = fthumb;
2275 }
2276 else
2277 {
2278 float fpos = (float)pos;
c801d85f
KB
2279 float frange = (float)range;
2280 float fthumb = (float)thumbVisible;
2281
cb43b372
RR
2282 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2283 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2284 {
2285 SetScrollPos( orient, pos, refresh );
c801d85f 2286 return;
cb43b372
RR
2287 }
2288
2289 m_oldVerticalPos = fpos;
c801d85f
KB
2290
2291 m_vAdjust->lower = 0.0;
2292 m_vAdjust->upper = frange;
2293 m_vAdjust->value = fpos;
2294 m_vAdjust->step_increment = 1.0;
84efdbf1 2295 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
c801d85f 2296 m_vAdjust->page_size = fthumb;
362c6693 2297 }
33d0b396 2298
c801d85f 2299 if (m_wxwindow->window)
d4c99d6f 2300 {
c801d85f
KB
2301 if (orient == wxHORIZONTAL)
2302 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
d4c99d6f 2303 else
c801d85f
KB
2304 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2305
401ec7b6 2306 gtk_widget_set_usize( m_widget, m_width, m_height );
362c6693
RR
2307 }
2308}
c801d85f 2309
debe6624 2310void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 2311{
e55ad60e
RR
2312 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2313
2314 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2315
c801d85f
KB
2316 if (!m_wxwindow) return;
2317
2318 if (orient == wxHORIZONTAL)
2319 {
2320 float fpos = (float)pos;
2321 m_oldHorizontalPos = fpos;
2322
2323 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2324 m_hAdjust->value = fpos;
2325 }
2326 else
2327 {
2328 float fpos = (float)pos;
2329 m_oldVerticalPos = fpos;
2330 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2331 m_vAdjust->value = fpos;
362c6693 2332 }
c801d85f 2333
cb43b372
RR
2334 if (!m_isScrolling)
2335 {
2336 if (m_wxwindow->window)
2337 {
2338 if (orient == wxHORIZONTAL)
2339 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2340 else
2341 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2342 }
362c6693
RR
2343 }
2344}
c801d85f 2345
debe6624 2346int wxWindow::GetScrollThumb( int orient ) const
c801d85f 2347{
e55ad60e
RR
2348 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2349
2350 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2351
c801d85f
KB
2352 if (!m_wxwindow) return 0;
2353
2354 if (orient == wxHORIZONTAL)
2355 return (int)(m_hAdjust->page_size+0.5);
2356 else
2357 return (int)(m_vAdjust->page_size+0.5);
362c6693 2358}
c801d85f 2359
debe6624 2360int wxWindow::GetScrollPos( int orient ) const
c801d85f 2361{
e55ad60e
RR
2362 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2363
2364 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2365
c801d85f
KB
2366 if (!m_wxwindow) return 0;
2367
2368 if (orient == wxHORIZONTAL)
2369 return (int)(m_hAdjust->value+0.5);
2370 else
2371 return (int)(m_vAdjust->value+0.5);
362c6693 2372}
c801d85f 2373
debe6624 2374int wxWindow::GetScrollRange( int orient ) const
c801d85f 2375{
e55ad60e
RR
2376 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2377
2378 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2379
c801d85f
KB
2380 if (!m_wxwindow) return 0;
2381
2382 if (orient == wxHORIZONTAL)
2383 return (int)(m_hAdjust->upper+0.5);
2384 else
2385 return (int)(m_vAdjust->upper+0.5);
362c6693 2386}
c801d85f 2387
debe6624 2388void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 2389{
e55ad60e 2390 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
c801d85f 2391
e55ad60e 2392 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
c801d85f 2393
e55ad60e 2394 if (!m_wxwindow) return;
c801d85f
KB
2395
2396 int cw = 0;
2397 int ch = 0;
2398 GetClientSize( &cw, &ch );
2399
2400 int w = cw - abs(dx);
2401 int h = ch - abs(dy);
2402 if ((h < 0) || (w < 0))
2403 {
2404 Refresh();
2405 return;
362c6693 2406 }
c801d85f
KB
2407 int s_x = 0;
2408 int s_y = 0;
2409 if (dx < 0) s_x = -dx;
2410 if (dy < 0) s_y = -dy;
2411 int d_x = 0;
2412 int d_y = 0;
2413 if (dx > 0) d_x = dx;
2414 if (dy > 0) d_y = dy;
2415 gdk_window_copy_area( m_wxwindow->window, m_wxwindow->style->fg_gc[0], d_x, d_y,
2416 m_wxwindow->window, s_x, s_y, w, h );
2417
2418 wxRect rect;
2419 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2420 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2421 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2422 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2423
2424 Refresh( TRUE, &rect );
362c6693 2425}
c801d85f
KB
2426
2427//-------------------------------------------------------------------------------------
2428// Layout
2429//-------------------------------------------------------------------------------------
2430
2431wxLayoutConstraints *wxWindow::GetConstraints(void) const
2432{
2433 return m_constraints;
362c6693 2434}
c801d85f
KB
2435
2436void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2437{
2438 if (m_constraints)
2439 {
2440 UnsetConstraints(m_constraints);
2441 delete m_constraints;
2442 }
2443 m_constraints = constraints;
2444 if (m_constraints)
2445 {
2446 // Make sure other windows know they're part of a 'meaningful relationship'
2447 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2448 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2449 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2450 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2451 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2452 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2453 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2454 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2455 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2456 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2457 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2458 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2459 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2460 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2461 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2462 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2463 }
2464;
2465}
2466;
2467
debe6624 2468void wxWindow::SetAutoLayout( bool autoLayout )
c801d85f
KB
2469{
2470 m_autoLayout = autoLayout;
362c6693 2471}
c801d85f
KB
2472
2473bool wxWindow::GetAutoLayout(void) const
2474{
2475 return m_autoLayout;
362c6693 2476}
c801d85f
KB
2477
2478wxSizer *wxWindow::GetSizer(void) const
2479{
2480 return m_windowSizer;
362c6693 2481}
c801d85f
KB
2482
2483void wxWindow::SetSizerParent( wxWindow *win )
2484{
2485 m_sizerParent = win;
362c6693 2486}
c801d85f
KB
2487
2488wxWindow *wxWindow::GetSizerParent(void) const
2489{
2490 return m_sizerParent;
362c6693 2491}
c801d85f
KB
2492
2493// This removes any dangling pointers to this window
2494// in other windows' constraintsInvolvedIn lists.
2495void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2496{
2497 if (c)
2498 {
2499 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2500 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2501 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2502 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2503 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2504 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2505 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2506 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2507 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2508 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2509 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2510 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2511 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2512 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2513 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2514 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2515 }
2516}
2517
2518// Back-pointer to other windows we're involved with, so if we delete
2519// this window, we must delete any constraints we're involved with.
2520void wxWindow::AddConstraintReference(wxWindow *otherWin)
2521{
2522 if (!m_constraintsInvolvedIn)
2523 m_constraintsInvolvedIn = new wxList;
2524 if (!m_constraintsInvolvedIn->Member(otherWin))
2525 m_constraintsInvolvedIn->Append(otherWin);
2526}
2527
2528// REMOVE back-pointer to other windows we're involved with.
2529void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2530{
2531 if (m_constraintsInvolvedIn)
2532 m_constraintsInvolvedIn->DeleteObject(otherWin);
2533}
2534
2535// Reset any constraints that mention this window
2536void wxWindow::DeleteRelatedConstraints(void)
2537{
2538 if (m_constraintsInvolvedIn)
2539 {
2540 wxNode *node = m_constraintsInvolvedIn->First();
2541 while (node)
2542 {
2543 wxWindow *win = (wxWindow *)node->Data();
2544 wxNode *next = node->Next();
2545 wxLayoutConstraints *constr = win->GetConstraints();
2546
2547 // Reset any constraints involving this window
2548 if (constr)
2549 {
2550 constr->left.ResetIfWin((wxWindow *)this);
2551 constr->top.ResetIfWin((wxWindow *)this);
2552 constr->right.ResetIfWin((wxWindow *)this);
2553 constr->bottom.ResetIfWin((wxWindow *)this);
2554 constr->width.ResetIfWin((wxWindow *)this);
2555 constr->height.ResetIfWin((wxWindow *)this);
2556 constr->centreX.ResetIfWin((wxWindow *)this);
2557 constr->centreY.ResetIfWin((wxWindow *)this);
2558 }
2559 delete node;
2560 node = next;
2561 }
2562 delete m_constraintsInvolvedIn;
c67daf87 2563 m_constraintsInvolvedIn = (wxList *) NULL;
c801d85f
KB
2564 }
2565}
2566
2567void wxWindow::SetSizer(wxSizer *sizer)
2568{
2569 m_windowSizer = sizer;
2570 if (sizer)
2571 sizer->SetSizerParent((wxWindow *)this);
2572}
2573
2574/*
2575 * New version
2576 */
2577
2578bool wxWindow::Layout(void)
2579{
2580 if (GetConstraints())
2581 {
2582 int w, h;
2583 GetClientSize(&w, &h);
2584 GetConstraints()->width.SetValue(w);
2585 GetConstraints()->height.SetValue(h);
2586 }
2587
2588 // If top level (one sizer), evaluate the sizer's constraints.
2589 if (GetSizer())
2590 {
2591 int noChanges;
2592 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2593 GetSizer()->LayoutPhase1(&noChanges);
2594 GetSizer()->LayoutPhase2(&noChanges);
2595 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2596 return TRUE;
2597 }
2598 else
2599 {
2600 // Otherwise, evaluate child constraints
2601 ResetConstraints(); // Mark all constraints as unevaluated
2602 DoPhase(1); // Just one phase need if no sizers involved
2603 DoPhase(2);
2604 SetConstraintSizes(); // Recursively set the real window sizes
2605 }
2606 return TRUE;
2607}
2608
2609
2610// Do a phase of evaluating constraints:
2611// the default behaviour. wxSizers may do a similar
2612// thing, but also impose their own 'constraints'
2613// and order the evaluation differently.
2614bool wxWindow::LayoutPhase1(int *noChanges)
2615{
2616 wxLayoutConstraints *constr = GetConstraints();
2617 if (constr)
2618 {
2619 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2620 }
2621 else
2622 return TRUE;
2623}
2624
2625bool wxWindow::LayoutPhase2(int *noChanges)
2626{
2627 *noChanges = 0;
2628
2629 // Layout children
2630 DoPhase(1);
2631 DoPhase(2);
2632 return TRUE;
2633}
2634
2635// Do a phase of evaluating child constraints
debe6624 2636bool wxWindow::DoPhase(int phase)
c801d85f
KB
2637{
2638 int noIterations = 0;
2639 int maxIterations = 500;
2640 int noChanges = 1;
2641 int noFailures = 0;
2642 wxList succeeded;
2643 while ((noChanges > 0) && (noIterations < maxIterations))
2644 {
2645 noChanges = 0;
2646 noFailures = 0;
2647 wxNode *node = GetChildren()->First();
2648 while (node)
2649 {
2650 wxWindow *child = (wxWindow *)node->Data();
2651 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2652 {
2653 wxLayoutConstraints *constr = child->GetConstraints();
2654 if (constr)
2655 {
2656 if (succeeded.Member(child))
2657 {
2658 }
2659 else
2660 {
2661 int tempNoChanges = 0;
2662 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2663 noChanges += tempNoChanges;
2664 if (success)
2665 {
2666 succeeded.Append(child);
2667 }
2668 }
2669 }
2670 }
2671 node = node->Next();
2672 }
2673 noIterations ++;
2674 }
2675 return TRUE;
2676}
2677
2678void wxWindow::ResetConstraints(void)
2679{
2680 wxLayoutConstraints *constr = GetConstraints();
2681 if (constr)
2682 {
2683 constr->left.SetDone(FALSE);
2684 constr->top.SetDone(FALSE);
2685 constr->right.SetDone(FALSE);
2686 constr->bottom.SetDone(FALSE);
2687 constr->width.SetDone(FALSE);
2688 constr->height.SetDone(FALSE);
2689 constr->centreX.SetDone(FALSE);
2690 constr->centreY.SetDone(FALSE);
2691 }
2692 wxNode *node = GetChildren()->First();
2693 while (node)
2694 {
2695 wxWindow *win = (wxWindow *)node->Data();
2696 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2697 win->ResetConstraints();
2698 node = node->Next();
2699 }
2700}
2701
2702// Need to distinguish between setting the 'fake' size for
2703// windows and sizers, and setting the real values.
debe6624 2704void wxWindow::SetConstraintSizes(bool recurse)
c801d85f
KB
2705{
2706 wxLayoutConstraints *constr = GetConstraints();
2707 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2708 constr->width.GetDone() && constr->height.GetDone())
2709 {
2710 int x = constr->left.GetValue();
2711 int y = constr->top.GetValue();
2712 int w = constr->width.GetValue();
2713 int h = constr->height.GetValue();
2714
2715 // If we don't want to resize this window, just move it...
2716 if ((constr->width.GetRelationship() != wxAsIs) ||
2717 (constr->height.GetRelationship() != wxAsIs))
2718 {
2719 // Calls Layout() recursively. AAAGH. How can we stop that.
2720 // Simply take Layout() out of non-top level OnSizes.
2721 SizerSetSize(x, y, w, h);
2722 }
2723 else
2724 {
2725 SizerMove(x, y);
2726 }
2727 }
2728 else if (constr)
2729 {
2730 char *windowClass = this->GetClassInfo()->GetClassName();
2731
2732 wxString winName;
5e0aa05a 2733 if (GetName() == "")
1a5a8367 2734 winName = _("unnamed");
5e0aa05a
VZ
2735 else
2736 winName = GetName();
1a5a8367 2737 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
c801d85f 2738 if (!constr->left.GetDone())
1a5a8367 2739 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
c801d85f 2740 if (!constr->right.GetDone())
1a5a8367 2741 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
c801d85f 2742 if (!constr->width.GetDone())
1a5a8367 2743 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
c801d85f 2744 if (!constr->height.GetDone())
1a5a8367
DP
2745 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2746 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
c801d85f
KB
2747 }
2748
2749 if (recurse)
2750 {
2751 wxNode *node = GetChildren()->First();
2752 while (node)
2753 {
2754 wxWindow *win = (wxWindow *)node->Data();
2755 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2756 win->SetConstraintSizes();
2757 node = node->Next();
2758 }
2759 }
2760}
2761
2762// This assumes that all sizers are 'on' the same
2763// window, i.e. the parent of this window.
2764void wxWindow::TransformSizerToActual(int *x, int *y) const
2765{
2766 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
5e0aa05a 2767 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
c801d85f
KB
2768 return;
2769
2770 int xp, yp;
2771 m_sizerParent->GetPosition(&xp, &yp);
2772 m_sizerParent->TransformSizerToActual(&xp, &yp);
2773 *x += xp;
2774 *y += yp;
2775}
2776
debe6624 2777void wxWindow::SizerSetSize(int x, int y, int w, int h)
c801d85f 2778{
5e0aa05a
VZ
2779 int xx = x;
2780 int yy = y;
c801d85f
KB
2781 TransformSizerToActual(&xx, &yy);
2782 SetSize(xx, yy, w, h);
2783}
2784
debe6624 2785void wxWindow::SizerMove(int x, int y)
c801d85f 2786{
5e0aa05a
VZ
2787 int xx = x;
2788 int yy = y;
c801d85f
KB
2789 TransformSizerToActual(&xx, &yy);
2790 Move(xx, yy);
2791}
2792
2793// Only set the size/position of the constraint (if any)
debe6624 2794void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
c801d85f
KB
2795{
2796 wxLayoutConstraints *constr = GetConstraints();
2797 if (constr)
2798 {
2799 if (x != -1)
2800 {
2801 constr->left.SetValue(x);
2802 constr->left.SetDone(TRUE);
2803 }
2804 if (y != -1)
2805 {
2806 constr->top.SetValue(y);
2807 constr->top.SetDone(TRUE);
2808 }
2809 if (w != -1)
2810 {
2811 constr->width.SetValue(w);
2812 constr->width.SetDone(TRUE);
2813 }
2814 if (h != -1)
2815 {
2816 constr->height.SetValue(h);
2817 constr->height.SetDone(TRUE);
2818 }
2819 }
2820}
2821
debe6624 2822void wxWindow::MoveConstraint(int x, int y)
c801d85f
KB
2823{
2824 wxLayoutConstraints *constr = GetConstraints();
2825 if (constr)
2826 {
2827 if (x != -1)
2828 {
2829 constr->left.SetValue(x);
2830 constr->left.SetDone(TRUE);
2831 }
2832 if (y != -1)
2833 {
2834 constr->top.SetValue(y);
2835 constr->top.SetDone(TRUE);
2836 }
2837 }
2838}
2839
2840void wxWindow::GetSizeConstraint(int *w, int *h) const
2841{
2842 wxLayoutConstraints *constr = GetConstraints();
2843 if (constr)
2844 {
2845 *w = constr->width.GetValue();
2846 *h = constr->height.GetValue();
2847 }
2848 else
2849 GetSize(w, h);
2850}
2851
2852void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2853{
2854 wxLayoutConstraints *constr = GetConstraints();
2855 if (constr)
2856 {
2857 *w = constr->width.GetValue();
2858 *h = constr->height.GetValue();
2859 }
2860 else
2861 GetClientSize(w, h);
2862}
2863
2864void wxWindow::GetPositionConstraint(int *x, int *y) const
2865{
2866 wxLayoutConstraints *constr = GetConstraints();
2867 if (constr)
2868 {
2869 *x = constr->left.GetValue();
2870 *y = constr->top.GetValue();
2871 }
2872 else
2873 GetPosition(x, y);
2874}
2875
7fd1d163 2876bool wxWindow::AcceptsFocus() const
0abbe297
VZ
2877{
2878 return IsEnabled() && IsShown();
2879}
5e0aa05a 2880
e3e65dac 2881void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
5e0aa05a
VZ
2882{
2883 UpdateWindowUI();
2884}