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