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