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