]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/window.cpp
wxComboBox included (removed dependency on wxUSE_COMBOBOX which was never
[wxWidgets.git] / src / gtk / 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{
e380f72b 637 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
47d67540 638
e380f72b 639 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 640 if (g_blockEventsOnScroll) return TRUE;
8bbe427f 641
e380f72b 642 if (!win->HasVMT()) return TRUE;
47d67540 643
c801d85f 644/*
e380f72b
RR
645 printf( "OnMotion from " );
646 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
647 printf( win->GetClassInfo()->GetClassName() );
648 printf( ".\n" );
4a33eba6 649*/
47d67540 650
e380f72b
RR
651 wxMouseEvent event( wxEVT_MOTION );
652 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
653 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
654 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
655 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
656 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
657 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
658 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
659
660 event.m_x = (long)gdk_event->x;
661 event.m_y = (long)gdk_event->y;
662
663 // Some control don't have their own X window and thus cannot get
664 // any events.
665
666 if (!g_capturing)
2f2aa628 667 {
db1b4961 668 wxNode *node = win->GetChildren().First();
e380f72b
RR
669 while (node)
670 {
671 wxWindow *child = (wxWindow*)node->Data();
1ecc4d80
RR
672
673 if (child->m_isStaticBox)
674 {
675 // wxStaticBox is transparent in the box itself
676 int x = event.m_x;
677 int y = event.m_y;
678 int xx1 = child->m_x;
679 int yy1 = child->m_y;
680 int xx2 = child->m_x + child->m_width;
681 int yy2 = child->m_x + child->m_height;
682
683 // left
684 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
685 // right
686 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
687 // top
688 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
689 // bottom
690 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
691 {
692 win = child;
693 event.m_x -= child->m_x;
694 event.m_y -= child->m_y;
695 break;
696 }
697
698 }
699 else
700 {
701 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
702 (child->m_x <= event.m_x) &&
703 (child->m_y <= event.m_y) &&
704 (child->m_x+child->m_width >= event.m_x) &&
705 (child->m_y+child->m_height >= event.m_y))
706 {
707 win = child;
708 event.m_x -= child->m_x;
709 event.m_y -= child->m_y;
710 break;
711 }
e380f72b
RR
712 }
713 node = node->Next();
714 }
2f2aa628 715 }
47d67540 716
e380f72b 717 event.SetEventObject( win );
47d67540 718
e380f72b
RR
719 if (win->GetEventHandler()->ProcessEvent( event ))
720 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
47d67540 721
e380f72b 722 return TRUE;
362c6693 723}
c801d85f
KB
724
725//-----------------------------------------------------------------------------
2f2aa628
RR
726// "focus_in_event"
727//-----------------------------------------------------------------------------
c801d85f 728
2f2aa628 729static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 730{
e380f72b 731 if (g_blockEventsOnDrag) return TRUE;
b292e2f5
RR
732
733 g_focusWindow = win;
734
e380f72b 735 if (win->m_wxwindow)
c801d85f 736 {
e380f72b
RR
737 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
738 {
739 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 740/*
e380f72b
RR
741 printf( "SetFocus flag from " );
742 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
743 printf( win->GetClassInfo()->GetClassName() );
744 printf( ".\n" );
c801d85f 745*/
e380f72b 746 }
362c6693 747 }
47d67540 748
e380f72b 749 if (!win->HasVMT()) return TRUE;
47d67540 750
c801d85f 751/*
e380f72b
RR
752 printf( "OnSetFocus from " );
753 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
754 printf( win->GetClassInfo()->GetClassName() );
755 printf( " " );
756 printf( WXSTRINGCAST win->GetLabel() );
757 printf( ".\n" );
c801d85f 758*/
47d67540 759
e380f72b
RR
760 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
761 event.SetEventObject( win );
47d67540 762
e380f72b
RR
763 if (win->GetEventHandler()->ProcessEvent( event ))
764 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
47d67540 765
e380f72b 766 return TRUE;
362c6693 767}
c801d85f
KB
768
769//-----------------------------------------------------------------------------
2f2aa628
RR
770// "focus_out_event"
771//-----------------------------------------------------------------------------
c801d85f 772
2f2aa628 773static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 774{
e380f72b
RR
775 if (g_blockEventsOnDrag) return TRUE;
776 if (win->m_wxwindow)
777 {
778 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
779 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
780 }
47d67540 781
e380f72b 782 if (!win->HasVMT()) return TRUE;
47d67540 783
c801d85f 784/*
e380f72b
RR
785 printf( "OnKillFocus from " );
786 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
787 printf( win->GetClassInfo()->GetClassName() );
788 printf( ".\n" );
c801d85f 789*/
47d67540 790
e380f72b
RR
791 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
792 event.SetEventObject( win );
47d67540 793
e380f72b
RR
794 if (win->GetEventHandler()->ProcessEvent( event ))
795 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
2f2aa628 796
e380f72b 797 return TRUE;
362c6693 798}
c801d85f 799
b4071e91
RR
800//-----------------------------------------------------------------------------
801// "enter_notify_event"
802//-----------------------------------------------------------------------------
803
804static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
805{
e380f72b 806 if (g_blockEventsOnDrag) return TRUE;
47d67540 807
b292e2f5
RR
808 if ((widget->window) && (win->m_cursor))
809 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
810
811 if (widget->window != gdk_event->window) return TRUE;
812
e380f72b 813 if (!win->HasVMT()) return TRUE;
47d67540 814
d8c83875 815/*
e380f72b
RR
816 printf( "OnEnter from " );
817 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
818 printf( win->GetClassInfo()->GetClassName() );
819 printf( ".\n" );
d8c83875 820*/
47d67540 821
e380f72b
RR
822 wxMouseEvent event( wxEVT_ENTER_WINDOW );
823 event.SetEventObject( win );
4a33eba6
RR
824
825 int x = 0;
826 int y = 0;
827 GdkModifierType state = (GdkModifierType)0;
828
829 gdk_window_get_pointer( widget->window, &x, &y, &state );
830
831 event.m_shiftDown = (state & GDK_SHIFT_MASK);
832 event.m_controlDown = (state & GDK_CONTROL_MASK);
833 event.m_altDown = (state & GDK_MOD1_MASK);
834 event.m_metaDown = (state & GDK_MOD2_MASK);
835 event.m_leftDown = (state & GDK_BUTTON1_MASK);
836 event.m_middleDown = (state & GDK_BUTTON2_MASK);
837 event.m_rightDown = (state & GDK_BUTTON3_MASK);
838
839 event.m_x = (long)x;
840 event.m_y = (long)y;
841
e380f72b
RR
842 if (win->GetEventHandler()->ProcessEvent( event ))
843 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
47d67540 844
e380f72b 845 return TRUE;
b4071e91 846}
47d67540 847
b4071e91
RR
848//-----------------------------------------------------------------------------
849// "leave_notify_event"
850//-----------------------------------------------------------------------------
851
852static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
853{
e380f72b 854 if (g_blockEventsOnDrag) return TRUE;
47d67540 855
b292e2f5
RR
856 if ((widget->window) && (win->m_cursor))
857 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
858
859 if (widget->window != gdk_event->window) return TRUE;
860
e380f72b 861 if (!win->HasVMT()) return TRUE;
47d67540 862
d8c83875 863/*
e380f72b
RR
864 printf( "OnLeave from " );
865 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
866 printf( win->GetClassInfo()->GetClassName() );
867 printf( ".\n" );
d8c83875 868*/
47d67540 869
e380f72b
RR
870 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
871 event.SetEventObject( win );
47d67540 872
4a33eba6
RR
873 int x = 0;
874 int y = 0;
875 GdkModifierType state = (GdkModifierType)0;
876
877 gdk_window_get_pointer( widget->window, &x, &y, &state );
878
879 event.m_shiftDown = (state & GDK_SHIFT_MASK);
880 event.m_controlDown = (state & GDK_CONTROL_MASK);
881 event.m_altDown = (state & GDK_MOD1_MASK);
882 event.m_metaDown = (state & GDK_MOD2_MASK);
883 event.m_leftDown = (state & GDK_BUTTON1_MASK);
884 event.m_middleDown = (state & GDK_BUTTON2_MASK);
885 event.m_rightDown = (state & GDK_BUTTON3_MASK);
886
887 event.m_x = (long)x;
888 event.m_y = (long)y;
889
e380f72b
RR
890 if (win->GetEventHandler()->ProcessEvent( event ))
891 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
47d67540 892
e380f72b 893 return TRUE;
b4071e91 894}
47d67540 895
c801d85f 896//-----------------------------------------------------------------------------
2f2aa628
RR
897// "value_changed" from m_vAdjust
898//-----------------------------------------------------------------------------
c801d85f 899
2f2aa628 900static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 901{
e380f72b 902 if (g_blockEventsOnDrag) return;
c801d85f
KB
903
904/*
e380f72b
RR
905 printf( "OnVScroll from " );
906 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
907 printf( win->GetClassInfo()->GetClassName() );
908 printf( ".\n" );
c801d85f 909*/
47d67540 910
e380f72b 911 if (!win->HasVMT()) return;
47d67540 912
e380f72b
RR
913 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
914 if (fabs(diff) < 0.2) return;
47d67540 915
e380f72b 916 wxEventType command = wxEVT_NULL;
47d67540 917
e380f72b
RR
918 float line_step = win->m_vAdjust->step_increment;
919 float page_step = win->m_vAdjust->page_increment;
47d67540 920
76ed8f8d
RR
921 if (win->m_isScrolling)
922 {
923 command = wxEVT_SCROLL_THUMBTRACK;
924 }
925 else
926 {
927 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
928 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
929 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
930 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
931 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
932 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
933 else command = wxEVT_SCROLL_THUMBTRACK;
934 }
47d67540 935
e380f72b 936 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 937
e380f72b
RR
938 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
939 event.SetEventObject( win );
940 win->GetEventHandler()->ProcessEvent( event );
362c6693 941}
c801d85f
KB
942
943//-----------------------------------------------------------------------------
2f2aa628
RR
944// "value_changed" from m_hAdjust
945//-----------------------------------------------------------------------------
c801d85f 946
2f2aa628 947static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 948{
e380f72b 949 if (g_blockEventsOnDrag) return;
47d67540 950
c801d85f 951/*
e380f72b
RR
952 printf( "OnHScroll from " );
953 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
954 printf( win->GetClassInfo()->GetClassName() );
955 printf( ".\n" );
c801d85f 956*/
47d67540 957
e380f72b 958 if (!win->HasVMT()) return;
47d67540 959
e380f72b
RR
960 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
961 if (fabs(diff) < 0.2) return;
47d67540 962
e380f72b 963 wxEventType command = wxEVT_NULL;
47d67540 964
e380f72b
RR
965 float line_step = win->m_hAdjust->step_increment;
966 float page_step = win->m_hAdjust->page_increment;
8bbe427f 967
76ed8f8d
RR
968 if (win->m_isScrolling)
969 {
970 command = wxEVT_SCROLL_THUMBTRACK;
971 }
972 else
973 {
974 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
975 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
976 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
977 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
978 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
979 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
980 else command = wxEVT_SCROLL_THUMBTRACK;
981 }
c801d85f 982
e380f72b 983 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 984
e380f72b
RR
985 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
986 event.SetEventObject( win );
987 win->GetEventHandler()->ProcessEvent( event );
362c6693 988}
c801d85f
KB
989
990//-----------------------------------------------------------------------------
2f2aa628
RR
991// "changed" from m_vAdjust
992//-----------------------------------------------------------------------------
c801d85f 993
2f2aa628 994static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 995{
e380f72b 996 if (g_blockEventsOnDrag) return;
c801d85f
KB
997
998/*
e380f72b
RR
999 printf( "OnVScroll change from " );
1000 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1001 printf( win->GetClassInfo()->GetClassName() );
1002 printf( ".\n" );
c801d85f 1003*/
47d67540 1004
e380f72b 1005 if (!win->HasVMT()) return;
47d67540 1006
e380f72b
RR
1007 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1008 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1009
e380f72b
RR
1010 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1011 event.SetEventObject( win );
1012 win->GetEventHandler()->ProcessEvent( event );
362c6693 1013}
c801d85f
KB
1014
1015//-----------------------------------------------------------------------------
2f2aa628
RR
1016// "changed" from m_hAdjust
1017//-----------------------------------------------------------------------------
c801d85f 1018
2f2aa628 1019static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1020{
e380f72b 1021 if (g_blockEventsOnDrag) return;
47d67540 1022
c801d85f 1023/*
e380f72b
RR
1024 printf( "OnHScroll change from " );
1025 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1026 printf( win->GetClassInfo()->GetClassName() );
1027 printf( ".\n" );
c801d85f 1028*/
47d67540 1029
e380f72b 1030 if (!win->HasVMT()) return;
47d67540 1031
e380f72b
RR
1032 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
1033 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1034
e380f72b
RR
1035 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1036 event.SetEventObject( win );
1037 win->GetEventHandler()->ProcessEvent( event );
362c6693 1038}
c801d85f 1039
cb43b372
RR
1040//-----------------------------------------------------------------------------
1041// "button_press_event" from scrollbar
1042//-----------------------------------------------------------------------------
1043
8bbe427f
VZ
1044static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1045 GdkEventButton *WXUNUSED(gdk_event),
76ed8f8d 1046 wxWindow *win )
cb43b372 1047{
1ecc4d80
RR
1048// don't test here as we can release the mouse while being over
1049// a different window then the slider
1050//
76ed8f8d 1051// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1052
e380f72b 1053 win->m_isScrolling = TRUE;
76ed8f8d 1054 g_blockEventsOnScroll = TRUE;
47d67540 1055
e380f72b 1056 return FALSE;
cb43b372
RR
1057}
1058
1059//-----------------------------------------------------------------------------
1060// "button_release_event" from scrollbar
1061//-----------------------------------------------------------------------------
1062
8bbe427f
VZ
1063static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1064 GdkEventButton *WXUNUSED(gdk_event),
76ed8f8d 1065 wxWindow *win )
cb43b372 1066{
76ed8f8d 1067
1ecc4d80 1068// don't test here as we can release the mouse while being over
76ed8f8d
RR
1069// a different window then the slider
1070//
1071// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1072
e380f72b 1073 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1074
e380f72b
RR
1075 if (widget == GTK_RANGE(s_window->vscrollbar))
1076 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
1077 else
1078 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1079
e380f72b 1080 win->m_isScrolling = FALSE;
76ed8f8d 1081 g_blockEventsOnScroll = FALSE;
47d67540 1082
e380f72b 1083 return FALSE;
cb43b372
RR
1084}
1085
6ca41e57
RR
1086//-----------------------------------------------------------------------------
1087// InsertChild for wxWindow.
1088//-----------------------------------------------------------------------------
1089
1090// Callback for wxWindow. This very strange beast has to be used because
8bbe427f 1091// C++ has no virtual methods in a constructor. We have to emulate a
6ca41e57
RR
1092// virtual function here as wxNotebook requires a different way to insert
1093// a child in it. I had opted for creating a wxNotebookPage window class
1ecc4d80
RR
1094// which would have made this superfluous (such in the MDI window system),
1095// but no-one was listening to me...
6ca41e57
RR
1096
1097static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1098{
8bbe427f
VZ
1099 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1100 GTK_WIDGET(child->m_widget),
1101 child->m_x,
f5e27805 1102 child->m_y );
6ca41e57 1103
8bbe427f
VZ
1104 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
1105 child->m_width,
f5e27805 1106 child->m_height );
6ca41e57
RR
1107}
1108
bbe0af5b
RR
1109//-----------------------------------------------------------------------------
1110// global functions
1111//-----------------------------------------------------------------------------
1112
1113wxWindow* wxGetActiveWindow()
1114{
1115 return g_focusWindow;
1116}
1117
c801d85f 1118//-----------------------------------------------------------------------------
2f2aa628 1119// wxWindow
c801d85f
KB
1120//-----------------------------------------------------------------------------
1121
1122IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
1123
1124BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
e380f72b
RR
1125 EVT_SIZE(wxWindow::OnSize)
1126 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
1127 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
1128 EVT_IDLE(wxWindow::OnIdle)
c801d85f
KB
1129END_EVENT_TABLE()
1130
1131wxWindow::wxWindow()
1132{
e380f72b
RR
1133 m_widget = (GtkWidget *) NULL;
1134 m_wxwindow = (GtkWidget *) NULL;
1135 m_parent = (wxWindow *) NULL;
1136 m_children.DeleteContents( FALSE );
8bbe427f 1137
e380f72b
RR
1138 m_x = 0;
1139 m_y = 0;
1140 m_width = 0;
1141 m_height = 0;
1142 m_minWidth = -1;
1143 m_minHeight = -1;
1144 m_maxWidth = -1;
1145 m_maxHeight = -1;
8bbe427f 1146
e380f72b 1147 m_retCode = 0;
8bbe427f 1148
e380f72b
RR
1149 m_eventHandler = this;
1150 m_windowValidator = (wxValidator *) NULL;
8bbe427f 1151
e380f72b 1152 m_windowId = -1;
8bbe427f 1153
e380f72b
RR
1154 m_cursor = (wxCursor *) NULL;
1155 m_font = *wxSWISS_FONT;
1156 m_windowStyle = 0;
1157 m_windowName = "noname";
8bbe427f 1158
e380f72b
RR
1159 m_constraints = (wxLayoutConstraints *) NULL;
1160 m_constraintsInvolvedIn = (wxList *) NULL;
1161 m_windowSizer = (wxSizer *) NULL;
1162 m_sizerParent = (wxWindow *) NULL;
1163 m_autoLayout = FALSE;
8bbe427f 1164
e380f72b
RR
1165 m_sizeSet = FALSE;
1166 m_hasVMT = FALSE;
1167 m_needParent = TRUE;
8bbe427f 1168
e380f72b
RR
1169 m_hasScrolling = FALSE;
1170 m_isScrolling = FALSE;
1171 m_hAdjust = (GtkAdjustment*) NULL;
1172 m_vAdjust = (GtkAdjustment*) NULL;
1173 m_oldHorizontalPos = 0.0;
1174 m_oldVerticalPos = 0.0;
8bbe427f 1175
e380f72b
RR
1176 m_isShown = FALSE;
1177 m_isEnabled = TRUE;
8bbe427f 1178
06cfab17 1179#if wxUSE_DRAG_AND_DROP
e380f72b 1180 m_dropTarget = (wxDropTarget*) NULL;
ac57418f 1181#endif
e380f72b
RR
1182 m_resizing = FALSE;
1183 m_scrollGC = (GdkGC*) NULL;
1184 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1185
e380f72b 1186 m_insertCallback = wxInsertChildInWindow;
8bbe427f 1187
e380f72b
RR
1188 m_clientObject = (wxClientData*) NULL;
1189 m_clientData = NULL;
1ecc4d80
RR
1190
1191 m_isStaticBox = FALSE;
b292e2f5 1192 m_acceptsFocus = FALSE;
362c6693 1193}
c801d85f 1194
6ca41e57 1195wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1196 const wxPoint &pos, const wxSize &size,
1197 long style, const wxString &name )
6ca41e57 1198{
e380f72b
RR
1199 m_insertCallback = wxInsertChildInWindow;
1200 Create( parent, id, pos, size, style, name );
6ca41e57 1201}
8bbe427f 1202
debe6624 1203bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1204 const wxPoint &pos, const wxSize &size,
1205 long style, const wxString &name )
c801d85f 1206{
e380f72b
RR
1207 m_isShown = FALSE;
1208 m_isEnabled = TRUE;
1209 m_needParent = TRUE;
47d67540 1210
e380f72b 1211 PreCreation( parent, id, pos, size, style, name );
47d67540 1212
e380f72b 1213 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1214 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
b292e2f5
RR
1215
1216#ifdef __WXDEBUG__
1217 debug_focus_in( m_widget, "wxWindow::m_widget", name );
1218#endif
47d67540 1219
e380f72b 1220 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1221
b292e2f5
RR
1222#ifdef __WXDEBUG__
1223 debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
1224 debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
1225#endif
1226
e380f72b
RR
1227 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1228 scroll_class->scrollbar_spacing = 0;
47d67540 1229
e380f72b 1230 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1231
e380f72b
RR
1232 m_oldHorizontalPos = 0.0;
1233 m_oldVerticalPos = 0.0;
47d67540 1234
e380f72b
RR
1235 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1236 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
47d67540 1237
38c7b3d3
RR
1238 m_wxwindow = gtk_myfixed_new();
1239
b292e2f5
RR
1240#ifdef __WXDEBUG__
1241 debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
1242#endif
1243
38c7b3d3
RR
1244#ifdef NEW_GTK_SCROLL_CODE
1245 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1246 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1247#else
1248 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
e380f72b 1249 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
38c7b3d3 1250#endif
47d67540 1251
b292e2f5
RR
1252#ifdef __WXDEBUG__
1253 debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
1254#endif
1255
e380f72b
RR
1256 if (m_windowStyle & wxRAISED_BORDER)
1257 {
1258 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1259 }
1260 else if (m_windowStyle & wxSUNKEN_BORDER)
1261 {
1262 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1263 }
1264 else
1265 {
1266 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1267 }
47d67540 1268
b292e2f5
RR
1269 if ((m_windowStyle & wxTAB_TRAVERSAL) != 0)
1270 {
e380f72b 1271 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1272 m_acceptsFocus = FALSE;
1273 }
e380f72b 1274 else
b292e2f5 1275 {
e380f72b 1276 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1277 m_acceptsFocus = TRUE;
1278 }
e380f72b 1279
e380f72b
RR
1280 // shut the viewport up
1281 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1282 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1283
1284 // I _really_ don't want scrollbars in the beginning
1285 m_vAdjust->lower = 0.0;
1286 m_vAdjust->upper = 1.0;
1287 m_vAdjust->value = 0.0;
1288 m_vAdjust->step_increment = 1.0;
1289 m_vAdjust->page_increment = 1.0;
1290 m_vAdjust->page_size = 5.0;
1291 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1292 m_hAdjust->lower = 0.0;
1293 m_hAdjust->upper = 1.0;
1294 m_hAdjust->value = 0.0;
1295 m_hAdjust->step_increment = 1.0;
1296 m_hAdjust->page_increment = 1.0;
1297 m_hAdjust->page_size = 5.0;
1298 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1299
76ed8f8d
RR
1300 // these handlers block mouse events to any window during scrolling
1301 // such as motion events and prevent GTK and wxWindows from fighting
1302 // over where the slider should be
8bbe427f 1303
76ed8f8d
RR
1304 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1305 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1306
1307 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1308 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1309
1310 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1311 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1312
1313 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1314 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1315
76ed8f8d
RR
1316 // these handers het notified when screen updates are required either when
1317 // scrolling or when the window size (and therefore scrollbar configuration)
1318 // has changed
1319
1320 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1321 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1322 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1323 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1324
1325 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1326 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1327 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1328 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1329
e380f72b 1330 gtk_widget_show( m_wxwindow );
8bbe427f 1331
e380f72b 1332 if (m_parent) m_parent->AddChild( this );
47d67540 1333
e380f72b 1334 (m_parent->m_insertCallback)( m_parent, this );
8bbe427f 1335
e380f72b 1336 PostCreation();
8bbe427f 1337
e380f72b 1338 Show( TRUE );
c801d85f 1339
e380f72b 1340 return TRUE;
362c6693 1341}
c801d85f 1342
68dda785 1343wxWindow::~wxWindow()
c801d85f 1344{
43a18898 1345 m_hasVMT = FALSE;
47d67540 1346
06cfab17 1347#if wxUSE_DRAG_AND_DROP
43a18898 1348 if (m_dropTarget) delete m_dropTarget;
ac57418f 1349#endif
47d67540 1350
43a18898
RR
1351 if (m_parent) m_parent->RemoveChild( this );
1352 if (m_widget) Show( FALSE );
c801d85f 1353
43a18898 1354 DestroyChildren();
47d67540 1355
43a18898 1356 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 1357
43a18898 1358 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
8bbe427f 1359
43a18898 1360 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
47d67540 1361
43a18898 1362 if (m_widget) gtk_widget_destroy( m_widget );
8bbe427f 1363
43a18898 1364 if (m_cursor) delete m_cursor;
c801d85f 1365
43a18898
RR
1366 DeleteRelatedConstraints();
1367 if (m_constraints)
1368 {
1369 // This removes any dangling pointers to this window
1370 // in other windows' constraintsInvolvedIn lists.
1371 UnsetConstraints(m_constraints);
1372 delete m_constraints;
1373 m_constraints = (wxLayoutConstraints *) NULL;
1374 }
1375 if (m_windowSizer)
1376 {
1377 delete m_windowSizer;
1378 m_windowSizer = (wxSizer *) NULL;
1379 }
1380 // If this is a child of a sizer, remove self from parent
1381 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
c801d85f 1382
43a18898
RR
1383 // Just in case the window has been Closed, but
1384 // we're then deleting immediately: don't leave
1385 // dangling pointers.
1386 wxPendingDelete.DeleteObject(this);
c801d85f 1387
43a18898
RR
1388 // Just in case we've loaded a top-level window via
1389 // wxWindow::LoadNativeDialog but we weren't a dialog
1390 // class
1391 wxTopLevelWindows.DeleteObject(this);
47d67540 1392
43a18898 1393 if (m_windowValidator) delete m_windowValidator;
8bbe427f 1394
43a18898 1395 if (m_clientObject) delete m_clientObject;
362c6693 1396}
c801d85f 1397
debe6624
JS
1398void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1399 const wxPoint &pos, const wxSize &size,
1400 long style, const wxString &name )
c801d85f 1401{
3069ac4e 1402 wxASSERT_MSG( (!m_needParent) || (parent), "Need complete parent." );
8bbe427f 1403
43a18898
RR
1404 m_widget = (GtkWidget*) NULL;
1405 m_wxwindow = (GtkWidget*) NULL;
1406 m_hasVMT = FALSE;
1407 m_parent = parent;
1408 m_children.DeleteContents( FALSE );
8bbe427f 1409
43a18898
RR
1410 m_width = size.x;
1411 if (m_width == -1) m_width = 20;
1412 m_height = size.y;
1413 if (m_height == -1) m_height = 20;
8bbe427f 1414
43a18898
RR
1415 m_x = (int)pos.x;
1416 m_y = (int)pos.y;
8bbe427f 1417
43a18898 1418 if (!m_needParent) // some reasonable defaults
6ca41e57 1419 {
43a18898
RR
1420 if (m_x == -1)
1421 {
1422 m_x = (gdk_screen_width () - m_width) / 2;
1423 if (m_x < 10) m_x = 10;
1424 }
1425 if (m_y == -1)
1426 {
1427 m_y = (gdk_screen_height () - m_height) / 2;
1428 if (m_y < 10) m_y = 10;
1429 }
6ca41e57 1430 }
8bbe427f 1431
43a18898
RR
1432 m_minWidth = -1;
1433 m_minHeight = -1;
1434 m_maxWidth = -1;
1435 m_maxHeight = -1;
8bbe427f 1436
43a18898 1437 m_retCode = 0;
8bbe427f 1438
43a18898 1439 m_eventHandler = this;
8bbe427f 1440
b749747d 1441 m_windowId = id == -1 ? wxNewId() : id;
8bbe427f 1442
43a18898 1443 m_sizeSet = FALSE;
8bbe427f 1444
43a18898
RR
1445 m_cursor = new wxCursor( wxCURSOR_ARROW );
1446 m_font = *wxSWISS_FONT;
1ecc4d80
RR
1447 m_backgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
1448 m_foregroundColour = *wxBLACK;
43a18898
RR
1449 m_windowStyle = style;
1450 m_windowName = name;
8bbe427f 1451
43a18898
RR
1452 m_constraints = (wxLayoutConstraints *) NULL;
1453 m_constraintsInvolvedIn = (wxList *) NULL;
1454 m_windowSizer = (wxSizer *) NULL;
1455 m_sizerParent = (wxWindow *) NULL;
1456 m_autoLayout = FALSE;
8bbe427f 1457
43a18898
RR
1458 m_hasScrolling = FALSE;
1459 m_isScrolling = FALSE;
1460 m_hAdjust = (GtkAdjustment *) NULL;
1461 m_vAdjust = (GtkAdjustment *) NULL;
1462 m_oldHorizontalPos = 0.0;
1463 m_oldVerticalPos = 0.0;
8bbe427f 1464
43a18898
RR
1465 m_isShown = FALSE;
1466 m_isEnabled = TRUE;
8bbe427f 1467
06cfab17 1468#if wxUSE_DRAG_AND_DROP
43a18898 1469 m_dropTarget = (wxDropTarget *) NULL;
ac57418f 1470#endif
43a18898
RR
1471 m_resizing = FALSE;
1472 m_windowValidator = (wxValidator *) NULL;
1473 m_scrollGC = (GdkGC*) NULL;
1474 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1475
43a18898
RR
1476 m_clientObject = (wxClientData*)NULL;
1477 m_clientData = NULL;
1ecc4d80
RR
1478
1479 m_isStaticBox = FALSE;
c801d85f
KB
1480}
1481
68dda785 1482void wxWindow::PostCreation()
c801d85f 1483{
43a18898
RR
1484 if (m_wxwindow)
1485 {
1486 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1487 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 1488
43a18898
RR
1489 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1490 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1491 }
47d67540 1492
43a18898 1493 ConnectWidget( GetConnectWidget() );
47d67540 1494
43a18898 1495 if (m_widget && m_parent) gtk_widget_realize( m_widget );
47d67540 1496
43a18898 1497 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
47d67540 1498
43a18898 1499 SetCursor( *wxSTANDARD_CURSOR );
47d67540 1500
43a18898 1501 m_hasVMT = TRUE;
b4071e91
RR
1502}
1503
1504void wxWindow::ConnectWidget( GtkWidget *widget )
1505{
43a18898
RR
1506 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1507 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 1508
43a18898
RR
1509 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1510 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 1511
43a18898
RR
1512 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1513 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 1514
43a18898
RR
1515 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1516 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 1517
43a18898
RR
1518 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1519 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 1520
43a18898
RR
1521 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1522 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 1523
43a18898
RR
1524 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1525 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 1526
43a18898
RR
1527 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1528 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1529}
c801d85f 1530
68dda785 1531bool wxWindow::HasVMT()
c801d85f 1532{
43a18898 1533 return m_hasVMT;
362c6693 1534}
c801d85f 1535
debe6624 1536bool wxWindow::Close( bool force )
c801d85f 1537{
43a18898 1538 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1539
43a18898
RR
1540 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1541 event.SetEventObject(this);
1542 event.SetForce(force);
c801d85f 1543
43a18898 1544 return GetEventHandler()->ProcessEvent(event);
362c6693 1545}
c801d85f 1546
68dda785 1547bool wxWindow::Destroy()
c801d85f 1548{
43a18898 1549 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
47d67540 1550
43a18898
RR
1551 m_hasVMT = FALSE;
1552 delete this;
1553 return TRUE;
362c6693 1554}
c801d85f 1555
68dda785 1556bool wxWindow::DestroyChildren()
c801d85f 1557{
db1b4961
RR
1558 wxNode *node;
1559 while ((node = m_children.First()) != (wxNode *)NULL)
c801d85f 1560 {
db1b4961
RR
1561 wxWindow *child;
1562 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
43a18898 1563 {
db1b4961
RR
1564 delete child;
1565 if (m_children.Member(child)) delete node;
43a18898 1566 }
362c6693 1567 }
43a18898 1568 return TRUE;
362c6693 1569}
c801d85f
KB
1570
1571void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1572{
43a18898 1573 // are we to set fonts here ?
362c6693 1574}
c801d85f 1575
6ca41e57
RR
1576wxPoint wxWindow::GetClientAreaOrigin() const
1577{
43a18898 1578 return wxPoint(0,0);
6ca41e57
RR
1579}
1580
1581void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1582{
43a18898
RR
1583 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1584 {
1585 wxPoint pt(GetParent()->GetClientAreaOrigin());
8bbe427f 1586 x += pt.x;
43a18898
RR
1587 y += pt.y;
1588 }
6ca41e57
RR
1589}
1590
debe6624 1591void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1592{
fb1585ae
RR
1593 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1594 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
8bbe427f 1595
fb1585ae
RR
1596 if (m_resizing) return; // I don't like recursions
1597 m_resizing = TRUE;
47d67540 1598
ba4e3652 1599 if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
fb1585ae 1600 {
ba4e3652 1601 // don't set the size for children of wxNotebook, just take the values.
fb1585ae
RR
1602 m_x = x;
1603 m_y = y;
1604 m_width = width;
ba4e3652 1605 m_height = height;
fb1585ae 1606 }
ba4e3652 1607 else
fb1585ae 1608 {
ba4e3652
RR
1609 int old_width = m_width;
1610 int old_height = m_height;
8bbe427f 1611
ba4e3652
RR
1612 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1613 {
1614 if (x != -1) m_x = x;
1615 if (y != -1) m_y = y;
1616 if (width != -1) m_width = width;
1617 if (height != -1) m_height = height;
1618 }
1619 else
1620 {
1621 m_x = x;
1622 m_y = y;
1623 m_width = width;
1624 m_height = height;
1625 }
47d67540 1626
ba4e3652
RR
1627 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1628 {
1629 if (width == -1) m_width = 80;
1630 }
1631
1632 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1633 {
1634 if (height == -1) m_height = 26;
1635 }
8bbe427f 1636
ba4e3652
RR
1637 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1638 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
1639 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1640 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 1641
ba4e3652
RR
1642 wxPoint pt( m_parent->GetClientAreaOrigin() );
1643 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
8bbe427f 1644
ba4e3652
RR
1645 if ((old_width != m_width) || (old_height != m_height))
1646 gtk_widget_set_usize( m_widget, m_width, m_height );
1647 }
8bbe427f 1648
fb1585ae 1649 m_sizeSet = TRUE;
47d67540 1650
fb1585ae
RR
1651 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1652 event.SetEventObject( this );
ba4e3652 1653 GetEventHandler()->ProcessEvent( event );
47d67540 1654
fb1585ae 1655 m_resizing = FALSE;
362c6693 1656}
c801d85f 1657
debe6624 1658void wxWindow::SetSize( int width, int height )
c801d85f 1659{
fb1585ae 1660 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
362c6693 1661}
c801d85f 1662
debe6624 1663void wxWindow::Move( int x, int y )
c801d85f 1664{
fb1585ae 1665 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
362c6693 1666}
c801d85f
KB
1667
1668void wxWindow::GetSize( int *width, int *height ) const
1669{
1ecc4d80 1670 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1671
fb1585ae
RR
1672 if (width) (*width) = m_width;
1673 if (height) (*height) = m_height;
362c6693 1674}
c801d85f 1675
debe6624 1676void wxWindow::SetClientSize( int width, int height )
c801d85f 1677{
1ecc4d80 1678 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1679
1ecc4d80 1680 if (!m_wxwindow)
c801d85f 1681 {
1ecc4d80 1682 SetSize( width, height );
c801d85f
KB
1683 }
1684 else
1685 {
1ecc4d80
RR
1686 int dw = 0;
1687 int dh = 0;
1688
1689 if (!m_hasScrolling)
1690 {
1691 GtkStyleClass *window_class = m_wxwindow->style->klass;
1692
1693 if ((m_windowStyle & wxRAISED_BORDER) ||
1694 (m_windowStyle & wxSUNKEN_BORDER))
1695 {
1696 dw += 2 * window_class->xthickness;
1697 dh += 2 * window_class->ythickness;
1698 }
1699 }
1700 else
1701 {
1702 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1703 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1704
38c7b3d3 1705#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1706 GtkWidget *viewport = scroll_window->child;
8bbe427f 1707#else
1ecc4d80 1708 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1709#endif
1710
1ecc4d80
RR
1711 GtkStyleClass *viewport_class = viewport->style->klass;
1712
1713 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1714 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1715
1716 if ((m_windowStyle & wxRAISED_BORDER) ||
1717 (m_windowStyle & wxSUNKEN_BORDER))
1718 {
1719 dw += 2 * viewport_class->xthickness;
1720 dh += 2 * viewport_class->ythickness;
1721 }
47d67540 1722
1ecc4d80
RR
1723 if (scroll_window->vscrollbar_visible)
1724 {
1725 dw += vscrollbar->allocation.width;
1726 dw += scroll_class->scrollbar_spacing;
1727 }
1728
1729 if (scroll_window->hscrollbar_visible)
1730 {
1731 dh += hscrollbar->allocation.height;
1732 dw += scroll_class->scrollbar_spacing;
1733 }
1734 }
1735
1736 SetSize( width+dw, height+dh );
1737 }
362c6693 1738}
c801d85f
KB
1739
1740void wxWindow::GetClientSize( int *width, int *height ) const
1741{
1ecc4d80 1742 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1743
1ecc4d80
RR
1744 if (!m_wxwindow)
1745 {
1746 if (width) (*width) = m_width;
1747 if (height) (*height) = m_height;
c801d85f
KB
1748 }
1749 else
1750 {
1ecc4d80
RR
1751 int dw = 0;
1752 int dh = 0;
1753
1754 if (!m_hasScrolling)
1755 {
1756 GtkStyleClass *window_class = m_wxwindow->style->klass;
1757
1758 if ((m_windowStyle & wxRAISED_BORDER) ||
1759 (m_windowStyle & wxSUNKEN_BORDER))
1760 {
1761 dw += 2 * window_class->xthickness;
1762 dh += 2 * window_class->ythickness;
1763 }
1764 }
1765 else
1766 {
1767 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1768 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1769
38c7b3d3 1770#ifdef NEW_GTK_SCROLL_CODE
1ecc4d80 1771 GtkWidget *viewport = scroll_window->child;
8bbe427f 1772#else
1ecc4d80 1773 GtkWidget *viewport = scroll_window->viewport;
38c7b3d3
RR
1774#endif
1775
1ecc4d80
RR
1776 GtkStyleClass *viewport_class = viewport->style->klass;
1777
1778 if ((m_windowStyle & wxRAISED_BORDER) ||
1779 (m_windowStyle & wxSUNKEN_BORDER))
1780 {
1781 dw += 2 * viewport_class->xthickness;
1782 dh += 2 * viewport_class->ythickness;
1783 }
1784
1785 if (scroll_window->vscrollbar_visible)
1786 {
1787// dw += vscrollbar->allocation.width;
1788 dw += 15; // range.slider_width = 11 + 2*2pts edge
1789 dw += scroll_class->scrollbar_spacing;
1790 }
1791
1792 if (scroll_window->hscrollbar_visible)
1793 {
1794// dh += hscrollbar->allocation.height;
1795 dh += 15;
1796 dh += scroll_class->scrollbar_spacing;
1797 }
1798 }
47d67540 1799
1ecc4d80
RR
1800 if (width) (*width) = m_width - dw;
1801 if (height) (*height) = m_height - dh;
1802 }
362c6693 1803}
c801d85f
KB
1804
1805void wxWindow::GetPosition( int *x, int *y ) const
1806{
1ecc4d80 1807 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1808
43a18898
RR
1809 if (x) (*x) = m_x;
1810 if (y) (*y) = m_y;
362c6693 1811}
c801d85f
KB
1812
1813void wxWindow::ClientToScreen( int *x, int *y )
1814{
1ecc4d80 1815 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1816
43a18898
RR
1817 GdkWindow *source = (GdkWindow *) NULL;
1818 if (m_wxwindow)
1819 source = m_wxwindow->window;
1820 else
1821 source = m_widget->window;
47d67540 1822
43a18898
RR
1823 int org_x = 0;
1824 int org_y = 0;
1825 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 1826
43a18898 1827 if (!m_wxwindow)
c801d85f 1828 {
43a18898
RR
1829 if (GTK_WIDGET_NO_WINDOW (m_widget))
1830 {
1831 org_x += m_widget->allocation.x;
1832 org_y += m_widget->allocation.y;
1833 }
362c6693 1834 }
47d67540 1835
43a18898
RR
1836 wxPoint pt(GetClientAreaOrigin());
1837 org_x += pt.x;
1838 org_y += pt.y;
8bbe427f 1839
43a18898
RR
1840 if (x) *x += org_x;
1841 if (y) *y += org_y;
362c6693 1842}
c801d85f
KB
1843
1844void wxWindow::ScreenToClient( int *x, int *y )
1845{
1ecc4d80 1846 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1847
1ecc4d80
RR
1848 GdkWindow *source = (GdkWindow *) NULL;
1849 if (m_wxwindow)
1850 source = m_wxwindow->window;
1851 else
1852 source = m_widget->window;
47d67540 1853
1ecc4d80
RR
1854 int org_x = 0;
1855 int org_y = 0;
1856 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 1857
1ecc4d80 1858 if (!m_wxwindow)
c801d85f 1859 {
1ecc4d80
RR
1860 if (GTK_WIDGET_NO_WINDOW (m_widget))
1861 {
1862 org_x += m_widget->allocation.x;
1863 org_y += m_widget->allocation.y;
1864 }
362c6693 1865 }
47d67540 1866
1ecc4d80
RR
1867 wxPoint pt(GetClientAreaOrigin());
1868 org_x -= pt.x;
1869 org_y -= pt.y;
8bbe427f 1870
1ecc4d80
RR
1871 if (x) *x -= org_x;
1872 if (y) *y -= org_y;
362c6693 1873}
c801d85f 1874
debe6624 1875void wxWindow::Centre( int direction )
c801d85f 1876{
1ecc4d80 1877 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1878
1ecc4d80
RR
1879 int x = m_x;
1880 int y = m_y;
8bbe427f 1881
1ecc4d80
RR
1882 if (m_parent)
1883 {
1884 int p_w = 0;
1885 int p_h = 0;
1886 m_parent->GetSize( &p_w, &p_h );
1887 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
1888 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
1889 }
1890 else
1891 {
1892 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
1893 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
1894 }
8bbe427f 1895
1ecc4d80 1896 Move( x, y );
362c6693 1897}
c801d85f 1898
68dda785 1899void wxWindow::Fit()
c801d85f 1900{
1ecc4d80 1901 wxCHECK_RET( (m_widget != NULL), "invalid window" );
5e0aa05a 1902
1ecc4d80
RR
1903 int maxX = 0;
1904 int maxY = 0;
1905 wxNode *node = m_children.First();
1906 while (node)
1907 {
1908 wxWindow *win = (wxWindow *)node->Data();
1909 int wx, wy, ww, wh;
1910 win->GetPosition(&wx, &wy);
1911 win->GetSize(&ww, &wh);
1912 if (wx + ww > maxX) maxX = wx + ww;
1913 if (wy + wh > maxY) maxY = wy + wh;
1914
1915 node = node->Next();
1916 }
1917
1918 SetClientSize(maxX + 7, maxY + 14);
362c6693 1919}
c801d85f 1920
2f2aa628
RR
1921void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1922{
1ecc4d80 1923 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1924
1ecc4d80
RR
1925 m_minWidth = minW;
1926 m_minHeight = minH;
1927 m_maxWidth = maxW;
1928 m_maxHeight = maxH;
2f2aa628
RR
1929}
1930
c801d85f
KB
1931void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1932{
f04371f0 1933// if (GetAutoLayout()) Layout();
362c6693 1934}
c801d85f 1935
debe6624 1936bool wxWindow::Show( bool show )
c801d85f 1937{
1ecc4d80 1938 wxCHECK_MSG( (m_widget != NULL), FALSE, "invalid window" );
47d67540 1939
1ecc4d80
RR
1940 if (show)
1941 gtk_widget_show( m_widget );
1942 else
1943 gtk_widget_hide( m_widget );
1944
1945 m_isShown = show;
1946
1947 return TRUE;
362c6693 1948}
c801d85f 1949
debe6624 1950void wxWindow::Enable( bool enable )
c801d85f 1951{
1ecc4d80 1952 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 1953
1ecc4d80
RR
1954 m_isEnabled = enable;
1955
1956 gtk_widget_set_sensitive( m_widget, enable );
1957 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
362c6693 1958}
c801d85f 1959
68dda785 1960int wxWindow::GetCharHeight() const
c33c4050 1961{
1ecc4d80 1962 wxCHECK_MSG( (m_widget != NULL), 12, "invalid window" );
47d67540 1963
1ecc4d80 1964 wxCHECK_MSG( m_font.Ok(), 12, "invalid font" );
47d67540 1965
1ecc4d80
RR
1966 GdkFont *font = m_font.GetInternalFont( 1.0 );
1967
1968 return font->ascent + font->descent;
c33c4050
RR
1969}
1970
68dda785 1971int wxWindow::GetCharWidth() const
c33c4050 1972{
1ecc4d80 1973 wxCHECK_MSG( (m_widget != NULL), 8, "invalid window" );
47d67540 1974
1ecc4d80 1975 wxCHECK_MSG( m_font.Ok(), 8, "invalid font" );
47d67540 1976
463c1fa1 1977 GdkFont *font = m_font.GetInternalFont( 1.0 );
1ecc4d80 1978
463c1fa1 1979 return gdk_string_width( font, "H" );
c33c4050
RR
1980}
1981
1982void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1983 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1984{
463c1fa1
RR
1985 wxFont fontToUse = m_font;
1986 if (theFont) fontToUse = *theFont;
47d67540 1987
1ecc4d80 1988 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
47d67540 1989
463c1fa1
RR
1990 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1991 if (x) (*x) = gdk_string_width( font, string );
1992 if (y) (*y) = font->ascent + font->descent;
1993 if (descent) (*descent) = font->descent;
1994 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
1995}
1996
debe6624 1997void wxWindow::MakeModal( bool modal )
c801d85f 1998{
1ecc4d80
RR
1999 return;
2000
2001 // Disable all other windows
2002 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
c801d85f 2003 {
1ecc4d80
RR
2004 wxNode *node = wxTopLevelWindows.First();
2005 while (node)
2006 {
2007 wxWindow *win = (wxWindow *)node->Data();
2008 if (win != this) win->Enable(!modal);
c801d85f 2009
1ecc4d80
RR
2010 node = node->Next();
2011 }
c801d85f 2012 }
c801d85f
KB
2013}
2014
68dda785 2015void wxWindow::SetFocus()
c801d85f 2016{
1ecc4d80 2017 wxCHECK_RET( (m_widget != NULL), "invalid window" );
b292e2f5 2018
463c1fa1
RR
2019 GtkWidget *connect_widget = GetConnectWidget();
2020 if (connect_widget)
c801d85f 2021 {
b292e2f5 2022 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2023 {
2024 gtk_widget_grab_focus (connect_widget);
2025 }
b292e2f5
RR
2026 else if (GTK_IS_CONTAINER(connect_widget))
2027 {
2028 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2029 }
2030 else
2031 {
2032 }
362c6693 2033 }
362c6693 2034}
c801d85f 2035
b292e2f5
RR
2036wxWindow *wxWindow::FindFocus()
2037{
2038 return g_focusWindow;
2039}
2040
2041bool wxWindow::AcceptsFocus() const
2042{
2043 return IsEnabled() && IsShown() && m_acceptsFocus;
2044}
2045
68dda785 2046bool wxWindow::OnClose()
c801d85f 2047{
463c1fa1 2048 return TRUE;
362c6693 2049}
c801d85f
KB
2050
2051void wxWindow::AddChild( wxWindow *child )
2052{
1ecc4d80
RR
2053 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2054 wxCHECK_RET( (child != NULL), "invalid child" );
47d67540 2055
463c1fa1 2056 m_children.Append( child );
362c6693 2057}
c801d85f 2058
463c1fa1
RR
2059wxWindow *wxWindow::ReParent( wxWindow *newParent )
2060{
1ecc4d80
RR
2061 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, "invalid window" );
2062
2063 wxWindow *oldParent = GetParent();
8bbe427f 2064
1ecc4d80 2065 if (oldParent) oldParent->RemoveChild( this );
8bbe427f 2066
1ecc4d80 2067 gtk_widget_unparent( m_widget );
8bbe427f 2068
1ecc4d80
RR
2069 if (newParent)
2070 {
2071 newParent->AddChild( this );
2072 (newParent->m_insertCallback)( newParent, this );
2073 }
8bbe427f 2074
1ecc4d80 2075 return oldParent;
362c6693 2076}
c801d85f
KB
2077
2078void wxWindow::RemoveChild( wxWindow *child )
2079{
db1b4961 2080 m_children.DeleteObject( child );
463c1fa1 2081 child->m_parent = (wxWindow *) NULL;
362c6693 2082}
c801d85f
KB
2083
2084void wxWindow::SetReturnCode( int retCode )
2085{
463c1fa1 2086 m_retCode = retCode;
362c6693 2087}
c801d85f 2088
68dda785 2089int wxWindow::GetReturnCode()
c801d85f 2090{
463c1fa1 2091 return m_retCode;
362c6693 2092}
c801d85f 2093
68dda785 2094void wxWindow::Raise()
362c6693 2095{
1ecc4d80 2096 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2097
463c1fa1 2098 if (m_widget) gdk_window_raise( m_widget->window );
362c6693
RR
2099}
2100
68dda785 2101void wxWindow::Lower()
362c6693 2102{
1ecc4d80 2103 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2104
463c1fa1 2105 if (m_widget) gdk_window_lower( m_widget->window );
362c6693 2106}
c801d85f 2107
8bbe427f 2108wxEvtHandler *wxWindow::GetEventHandler() const
c801d85f 2109{
463c1fa1 2110 return m_eventHandler;
362c6693 2111}
c801d85f 2112
86b29a61 2113void wxWindow::SetEventHandler( wxEvtHandler *handler )
c801d85f 2114{
463c1fa1 2115 m_eventHandler = handler;
362c6693 2116}
c801d85f 2117
86b29a61
RR
2118void wxWindow::PushEventHandler(wxEvtHandler *handler)
2119{
463c1fa1
RR
2120 handler->SetNextHandler(GetEventHandler());
2121 SetEventHandler(handler);
86b29a61
RR
2122}
2123
2124wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
2125{
463c1fa1 2126 if (GetEventHandler())
e55ad60e 2127 {
463c1fa1
RR
2128 wxEvtHandler *handlerA = GetEventHandler();
2129 wxEvtHandler *handlerB = handlerA->GetNextHandler();
2130 handlerA->SetNextHandler((wxEvtHandler *) NULL);
2131 SetEventHandler(handlerB);
2132 if (deleteHandler)
2133 {
2134 delete handlerA;
2135 return (wxEvtHandler*) NULL;
2136 }
2137 else
2138 return handlerA;
2139 }
2140 else
2141 return (wxEvtHandler *) NULL;
86b29a61
RR
2142}
2143
68dda785 2144wxValidator *wxWindow::GetValidator()
c801d85f 2145{
463c1fa1 2146 return m_windowValidator;
362c6693 2147}
c801d85f 2148
6de97a3b 2149void wxWindow::SetValidator( const wxValidator& validator )
c801d85f 2150{
1ecc4d80
RR
2151 if (m_windowValidator) delete m_windowValidator;
2152 m_windowValidator = validator.Clone();
2153 if (m_windowValidator) m_windowValidator->SetWindow(this);
362c6693 2154}
c801d85f 2155
fd0eed64
RR
2156void wxWindow::SetClientObject( wxClientData *data )
2157{
1ecc4d80
RR
2158 if (m_clientObject) delete m_clientObject;
2159 m_clientObject = data;
fd0eed64
RR
2160}
2161
2162wxClientData *wxWindow::GetClientObject()
2163{
1ecc4d80 2164 return m_clientObject;
fd0eed64
RR
2165}
2166
2167void wxWindow::SetClientData( void *data )
2168{
1ecc4d80 2169 m_clientData = data;
fd0eed64
RR
2170}
2171
2172void *wxWindow::GetClientData()
2173{
1ecc4d80 2174 return m_clientData;
fd0eed64
RR
2175}
2176
68dda785 2177bool wxWindow::IsBeingDeleted()
c801d85f 2178{
1ecc4d80 2179 return FALSE;
362c6693 2180}
c801d85f
KB
2181
2182void wxWindow::SetId( wxWindowID id )
2183{
1ecc4d80 2184 m_windowId = id;
362c6693 2185}
c801d85f 2186
8bbe427f 2187wxWindowID wxWindow::GetId() const
c801d85f 2188{
1ecc4d80 2189 return m_windowId;
362c6693 2190}
c801d85f
KB
2191
2192void wxWindow::SetCursor( const wxCursor &cursor )
2193{
1ecc4d80 2194 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2195
1ecc4d80
RR
2196 if (cursor.Ok())
2197 {
2198 if (cursor == *m_cursor) return;
2199 *m_cursor = cursor;
2200 }
2201 else
2202 {
2203 *m_cursor = *wxSTANDARD_CURSOR;
2204 }
a3622daa 2205
1ecc4d80
RR
2206 if ((m_widget) && (m_widget->window))
2207 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
47d67540 2208
1ecc4d80
RR
2209 if ((m_wxwindow) && (m_wxwindow->window))
2210 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
362c6693 2211}
c801d85f 2212
4f22cf8d
RR
2213void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2214{
2215 // TODO
2216}
2217
debe6624 2218void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2219{
139adb6a 2220 wxCHECK_RET( (m_widget != NULL), "invalid window" );
47d67540 2221
139adb6a 2222 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2223 {
139adb6a
RR
2224 if (rect)
2225 {
2226 gdk_window_clear_area( m_wxwindow->window,
2227 rect->x, rect->y,
2228 rect->width,
2229 rect->height );
2230 }
2231 else
2232 {
1ecc4d80 2233 Clear();
139adb6a
RR
2234 }
2235 }
2236
2237 if (!rect)
2238 {
2239 if (m_wxwindow)
2240 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2241 else
2242 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2243 }
c801d85f 2244 else
139adb6a
RR
2245 {
2246 GdkRectangle gdk_rect;
2247 gdk_rect.x = rect->x;
2248 gdk_rect.y = rect->y;
2249 gdk_rect.width = rect->width;
2250 gdk_rect.height = rect->height;
2251
2252 if (m_wxwindow)
2253 gtk_widget_draw( m_wxwindow, &gdk_rect );
2254 else
2255 gtk_widget_draw( m_widget, &gdk_rect );
2256 }
362c6693 2257}
c801d85f 2258
8429bec1
RR
2259wxRegion wxWindow::GetUpdateRegion() const
2260{
2261 return m_updateRegion;
2262}
2263
2264bool wxWindow::IsExposed( int x, int y) const
c801d85f 2265{
1ecc4d80 2266 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
362c6693 2267}
c801d85f 2268
8429bec1
RR
2269bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2270{
1ecc4d80 2271 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
8429bec1
RR
2272}
2273
2274bool wxWindow::IsExposed( const wxPoint& pt ) const
2275{
1ecc4d80 2276 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
8429bec1
RR
2277}
2278
2279bool wxWindow::IsExposed( const wxRect& rect ) const
c801d85f 2280{
1ecc4d80 2281 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
362c6693 2282}
c801d85f 2283
68dda785 2284void wxWindow::Clear()
c801d85f 2285{
3bc755fc 2286 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2287
3bc755fc 2288 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
362c6693 2289}
c801d85f 2290
68dda785 2291wxColour wxWindow::GetBackgroundColour() const
c801d85f 2292{
3bc755fc 2293 return m_backgroundColour;
362c6693 2294}
c801d85f
KB
2295
2296void wxWindow::SetBackgroundColour( const wxColour &colour )
2297{
3bc755fc 2298 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2299
3bc755fc 2300 if (m_backgroundColour == colour) return;
8bbe427f 2301
3bc755fc
RR
2302 m_backgroundColour = colour;
2303 if (!m_backgroundColour.Ok()) return;
8bbe427f 2304
3bc755fc
RR
2305 if (m_wxwindow)
2306 {
2307 GdkWindow *window = m_wxwindow->window;
2308 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2309 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2310 gdk_window_clear( window );
2311 }
8bbe427f 2312
ae0bdb01
RR
2313 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2314 if (sysbg.Red() == colour.Red() &&
2315 sysbg.Green() == colour.Green() &&
2316 sysbg.Blue() == colour.Blue())
2317 {
2318 m_backgroundColour = wxNullColour;
2319 ApplyWidgetStyle();
2320 m_backgroundColour = sysbg;
2321 }
2322 else
2323 {
2324 ApplyWidgetStyle();
2325 }
362c6693 2326}
c801d85f 2327
68dda785 2328wxColour wxWindow::GetForegroundColour() const
6de97a3b 2329{
3bc755fc 2330 return m_foregroundColour;
6de97a3b
RR
2331}
2332
2333void wxWindow::SetForegroundColour( const wxColour &colour )
2334{
3bc755fc 2335 wxCHECK_RET( m_widget != NULL, "invalid window" );
a81258be 2336
3bc755fc 2337 if (m_foregroundColour == colour) return;
8bbe427f 2338
3bc755fc
RR
2339 m_foregroundColour = colour;
2340 if (!m_foregroundColour.Ok()) return;
8bbe427f 2341
ae0bdb01
RR
2342 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2343 if (sysbg.Red() == colour.Red() &&
2344 sysbg.Green() == colour.Green() &&
2345 sysbg.Blue() == colour.Blue())
2346 {
2347 m_backgroundColour = wxNullColour;
2348 ApplyWidgetStyle();
2349 m_backgroundColour = sysbg;
2350 }
2351 else
2352 {
2353 ApplyWidgetStyle();
2354 }
58614078
RR
2355}
2356
2357GtkStyle *wxWindow::GetWidgetStyle()
2358{
1ecc4d80 2359 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2360
1ecc4d80
RR
2361 m_widgetStyle =
2362 gtk_style_copy(
2363 gtk_widget_get_style( m_widget ) );
8bbe427f 2364
1ecc4d80 2365 return m_widgetStyle;
58614078
RR
2366}
2367
2368void wxWindow::SetWidgetStyle()
2369{
1ecc4d80
RR
2370 GtkStyle *style = GetWidgetStyle();
2371
2372 gdk_font_unref( style->font );
2373 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2374
2375 if (m_foregroundColour.Ok())
2376 {
2377 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2378 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2379 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2380 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2381 }
2382
2383 if (m_backgroundColour.Ok())
2384 {
2385 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2386 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2387 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2388 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2389 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2390 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2391 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2392 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2393 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2394 }
a81258be
RR
2395}
2396
58614078 2397void wxWindow::ApplyWidgetStyle()
a81258be 2398{
6de97a3b
RR
2399}
2400
68dda785 2401bool wxWindow::Validate()
c801d85f 2402{
1ecc4d80 2403 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2404
1ecc4d80
RR
2405 wxNode *node = m_children.First();
2406 while (node)
2407 {
2408 wxWindow *child = (wxWindow *)node->Data();
2409 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2410 {
2411 return FALSE;
2412 }
2413 node = node->Next();
2414 }
2415 return TRUE;
362c6693 2416}
c801d85f 2417
68dda785 2418bool wxWindow::TransferDataToWindow()
c801d85f 2419{
1ecc4d80 2420 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2421
1ecc4d80
RR
2422 wxNode *node = m_children.First();
2423 while (node)
c801d85f 2424 {
1ecc4d80
RR
2425 wxWindow *child = (wxWindow *)node->Data();
2426 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2427 !child->GetValidator()->TransferToWindow() )
2428 {
2429 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2430 return FALSE;
2431 }
2432 node = node->Next();
362c6693 2433 }
1ecc4d80 2434 return TRUE;
362c6693 2435}
c801d85f 2436
68dda785 2437bool wxWindow::TransferDataFromWindow()
c801d85f 2438{
1ecc4d80 2439 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2440
1ecc4d80
RR
2441 wxNode *node = m_children.First();
2442 while (node)
2443 {
2444 wxWindow *child = (wxWindow *)node->Data();
2445 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2446 {
2447 return FALSE;
2448 }
2449 node = node->Next();
2450 }
2451 return TRUE;
362c6693 2452}
c801d85f 2453
bcf1fa6b
RR
2454void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2455{
1ecc4d80 2456 m_acceleratorTable = accel;
bcf1fa6b
RR
2457}
2458
c801d85f
KB
2459void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2460{
1ecc4d80 2461 TransferDataToWindow();
362c6693 2462}
c801d85f 2463
68dda785 2464void wxWindow::InitDialog()
c801d85f 2465{
1ecc4d80 2466 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2467
1ecc4d80
RR
2468 wxInitDialogEvent event(GetId());
2469 event.SetEventObject( this );
2470 GetEventHandler()->ProcessEvent(event);
362c6693 2471}
c801d85f 2472
30dea054
RR
2473static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2474{
1ecc4d80
RR
2475 menu->SetInvokingWindow( win );
2476 wxNode *node = menu->m_items.First();
2477 while (node)
2478 {
2479 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2480 if (menuitem->IsSubMenu())
2481 {
2482 SetInvokingWindow( menuitem->GetSubMenu(), win );
2483 }
2484 node = node->Next();
2485 }
362c6693 2486}
30dea054
RR
2487
2488bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2489{
1ecc4d80 2490 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
47d67540 2491
1ecc4d80 2492 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
8bbe427f 2493
1ecc4d80
RR
2494 SetInvokingWindow( menu, this );
2495 gtk_menu_popup(
47d67540
VZ
2496 GTK_MENU(menu->m_menu),
2497 (GtkWidget *)NULL, // parent menu shell
2498 (GtkWidget *)NULL, // parent menu item
2499 (GtkMenuPositionFunc)NULL,
2500 NULL, // client data
2501 0, // button used to activate it
2502 0//gs_timeLastClick // the time of activation
2503 );
1ecc4d80 2504 return TRUE;
30dea054
RR
2505}
2506
06cfab17 2507#if wxUSE_DRAG_AND_DROP
ac57418f 2508
c801d85f
KB
2509void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2510{
1ecc4d80 2511 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2512
1ecc4d80 2513 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2514
1ecc4d80 2515 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2516
1ecc4d80
RR
2517 if (m_dropTarget) delete m_dropTarget;
2518 m_dropTarget = dropTarget;
47d67540 2519
1ecc4d80 2520 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2521}
c801d85f
KB
2522
2523wxDropTarget *wxWindow::GetDropTarget() const
2524{
1ecc4d80 2525 return m_dropTarget;
362c6693 2526}
c801d85f 2527
ac57418f
RR
2528#endif
2529
68dda785 2530GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2531{
1ecc4d80
RR
2532 GtkWidget *connect_widget = m_widget;
2533 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2534
1ecc4d80 2535 return connect_widget;
e3e65dac 2536}
47d67540 2537
903f689b
RR
2538bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2539{
1ecc4d80
RR
2540 if (m_wxwindow) return (window == m_wxwindow->window);
2541 return (window == m_widget->window);
903f689b
RR
2542}
2543
c801d85f
KB
2544void wxWindow::SetFont( const wxFont &font )
2545{
1ecc4d80 2546 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2547
1ecc4d80
RR
2548 if (((wxFont*)&font)->Ok())
2549 m_font = font;
2550 else
2551 m_font = *wxSWISS_FONT;
c801d85f 2552
ae0bdb01
RR
2553 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2554 if (sysbg.Red() == m_backgroundColour.Red() &&
2555 sysbg.Green() == m_backgroundColour.Green() &&
2556 sysbg.Blue() == m_backgroundColour.Blue())
2557 {
2558 m_backgroundColour = wxNullColour;
2559 ApplyWidgetStyle();
2560 m_backgroundColour = sysbg;
2561 }
2562 else
2563 {
2564 ApplyWidgetStyle();
2565 }
362c6693 2566}
c801d85f
KB
2567
2568void wxWindow::SetWindowStyleFlag( long flag )
2569{
1ecc4d80 2570 m_windowStyle = flag;
362c6693 2571}
c801d85f 2572
68dda785 2573long wxWindow::GetWindowStyleFlag() const
c801d85f 2574{
1ecc4d80 2575 return m_windowStyle;
362c6693 2576}
c801d85f 2577
68dda785 2578void wxWindow::CaptureMouse()
c801d85f 2579{
1ecc4d80 2580 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2581
1ecc4d80 2582 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
47d67540 2583
1ecc4d80
RR
2584 GtkWidget *connect_widget = GetConnectWidget();
2585 gtk_grab_add( connect_widget );
2586 gdk_pointer_grab( connect_widget->window, FALSE,
2587 (GdkEventMask)
2588 (GDK_BUTTON_PRESS_MASK |
2589 GDK_BUTTON_RELEASE_MASK |
2590 GDK_POINTER_MOTION_MASK),
2591 (GdkWindow *) NULL,
2592 (GdkCursor *) NULL,
2593 GDK_CURRENT_TIME );
2594 g_capturing = TRUE;
362c6693 2595}
c801d85f 2596
68dda785 2597void wxWindow::ReleaseMouse()
c801d85f 2598{
1ecc4d80 2599 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2600
1ecc4d80 2601 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
47d67540 2602
1ecc4d80
RR
2603 GtkWidget *connect_widget = GetConnectWidget();
2604 gtk_grab_remove( connect_widget );
2605 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2606 g_capturing = FALSE;
362c6693 2607}
c801d85f
KB
2608
2609void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2610{
362c6693 2611}
c801d85f 2612
68dda785 2613wxString wxWindow::GetTitle() const
c801d85f 2614{
1ecc4d80 2615 return (wxString&)m_windowName;
362c6693 2616}
c801d85f 2617
68dda785 2618wxString wxWindow::GetLabel() const
c801d85f 2619{
1ecc4d80 2620 return GetTitle();
362c6693 2621}
c801d85f
KB
2622
2623void wxWindow::SetName( const wxString &name )
2624{
1ecc4d80 2625 m_windowName = name;
362c6693 2626}
c801d85f 2627
68dda785 2628wxString wxWindow::GetName() const
c801d85f 2629{
1ecc4d80 2630 return (wxString&)m_windowName;
362c6693 2631}
c801d85f 2632
68dda785 2633bool wxWindow::IsShown() const
c801d85f 2634{
1ecc4d80 2635 return m_isShown;
362c6693 2636}
c801d85f 2637
68dda785 2638bool wxWindow::IsRetained()
c801d85f 2639{
1ecc4d80 2640 return FALSE;
362c6693 2641}
c801d85f 2642
debe6624 2643wxWindow *wxWindow::FindWindow( long id )
c801d85f 2644{
1ecc4d80
RR
2645 if (id == m_windowId) return this;
2646 wxNode *node = m_children.First();
2647 while (node)
2648 {
2649 wxWindow *child = (wxWindow*)node->Data();
2650 wxWindow *res = child->FindWindow( id );
2651 if (res) return res;
2652 node = node->Next();
2653 }
2654 return (wxWindow *) NULL;
362c6693 2655}
c801d85f
KB
2656
2657wxWindow *wxWindow::FindWindow( const wxString& name )
2658{
1ecc4d80
RR
2659 if (name == m_windowName) return this;
2660 wxNode *node = m_children.First();
2661 while (node)
2662 {
2663 wxWindow *child = (wxWindow*)node->Data();
2664 wxWindow *res = child->FindWindow( name );
2665 if (res) return res;
2666 node = node->Next();
2667 }
2668 return (wxWindow *) NULL;
362c6693 2669}
c801d85f 2670
debe6624 2671void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2672 int range, bool refresh )
c801d85f 2673{
1ecc4d80 2674 wxCHECK_RET( m_widget != NULL, "invalid window" );
8bbe427f 2675
1ecc4d80 2676 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f 2677
1ecc4d80 2678 m_hasScrolling = TRUE;
47d67540 2679
1ecc4d80 2680 if (orient == wxHORIZONTAL)
cb43b372 2681 {
1ecc4d80
RR
2682 float fpos = (float)pos;
2683 float frange = (float)range;
2684 float fthumb = (float)thumbVisible;
2685 if (fpos > frange-fthumb) fpos = frange-fthumb;
2686 if (fpos < 0.0) fpos = 0.0;
2687
2688 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2689 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2690 {
2691 SetScrollPos( orient, pos, refresh );
2692 return;
2693 }
47d67540 2694
1ecc4d80 2695 m_oldHorizontalPos = fpos;
47d67540 2696
1ecc4d80
RR
2697 m_hAdjust->lower = 0.0;
2698 m_hAdjust->upper = frange;
2699 m_hAdjust->value = fpos;
2700 m_hAdjust->step_increment = 1.0;
2701 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2702 m_hAdjust->page_size = fthumb;
cb43b372 2703 }
1ecc4d80
RR
2704 else
2705 {
2706 float fpos = (float)pos;
2707 float frange = (float)range;
2708 float fthumb = (float)thumbVisible;
2709 if (fpos > frange-fthumb) fpos = frange-fthumb;
2710 if (fpos < 0.0) fpos = 0.0;
2711
2712 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2713 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2714 {
2715 SetScrollPos( orient, pos, refresh );
2716 return;
2717 }
47d67540 2718
1ecc4d80 2719 m_oldVerticalPos = fpos;
47d67540 2720
1ecc4d80
RR
2721 m_vAdjust->lower = 0.0;
2722 m_vAdjust->upper = frange;
2723 m_vAdjust->value = fpos;
2724 m_vAdjust->step_increment = 1.0;
2725 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2726 m_vAdjust->page_size = fthumb;
2727 }
47d67540 2728
1ecc4d80
RR
2729 if (m_wxwindow->window)
2730 {
2731 if (orient == wxHORIZONTAL)
2732 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2733 else
2734 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
47d67540 2735
1ecc4d80
RR
2736 gtk_widget_set_usize( m_widget, m_width, m_height );
2737 }
362c6693 2738}
c801d85f 2739
debe6624 2740void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 2741{
1ecc4d80
RR
2742 wxCHECK_RET( m_widget != NULL, "invalid window" );
2743
2744 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2745
2746 if (orient == wxHORIZONTAL)
2747 {
2748 float fpos = (float)pos;
2749 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2750 if (fpos < 0.0) fpos = 0.0;
2751 m_oldHorizontalPos = fpos;
2752
2753 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2754 m_hAdjust->value = fpos;
2755 }
2756 else
2757 {
2758 float fpos = (float)pos;
2759 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2760 if (fpos < 0.0) fpos = 0.0;
2761 m_oldVerticalPos = fpos;
92976ab6 2762
1ecc4d80
RR
2763 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2764 m_vAdjust->value = fpos;
2765 }
47d67540 2766
1ecc4d80 2767 if (!m_isScrolling)
47d67540 2768 {
1ecc4d80
RR
2769 if (m_wxwindow->window)
2770 {
2771 if (orient == wxHORIZONTAL)
2772 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2773 else
2774 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2775 }
cb43b372 2776 }
362c6693 2777}
c801d85f 2778
debe6624 2779int wxWindow::GetScrollThumb( int orient ) const
c801d85f 2780{
1ecc4d80 2781 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 2782
1ecc4d80 2783 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
47d67540 2784
1ecc4d80
RR
2785 if (orient == wxHORIZONTAL)
2786 return (int)(m_hAdjust->page_size+0.5);
2787 else
2788 return (int)(m_vAdjust->page_size+0.5);
362c6693 2789}
c801d85f 2790
debe6624 2791int wxWindow::GetScrollPos( int orient ) const
c801d85f 2792{
1ecc4d80 2793 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 2794
1ecc4d80 2795 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 2796
1ecc4d80
RR
2797 if (orient == wxHORIZONTAL)
2798 return (int)(m_hAdjust->value+0.5);
2799 else
2800 return (int)(m_vAdjust->value+0.5);
362c6693 2801}
c801d85f 2802
debe6624 2803int wxWindow::GetScrollRange( int orient ) const
c801d85f 2804{
1ecc4d80 2805 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
47d67540 2806
1ecc4d80 2807 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
c801d85f 2808
1ecc4d80
RR
2809 if (orient == wxHORIZONTAL)
2810 return (int)(m_hAdjust->upper+0.5);
2811 else
2812 return (int)(m_vAdjust->upper+0.5);
362c6693 2813}
c801d85f 2814
debe6624 2815void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 2816{
1ecc4d80 2817 wxCHECK_RET( m_widget != NULL, "invalid window" );
47d67540 2818
1ecc4d80 2819 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
c801d85f
KB
2820
2821 int cw = 0;
2822 int ch = 0;
2823 GetClientSize( &cw, &ch );
47d67540 2824
c801d85f
KB
2825 int w = cw - abs(dx);
2826 int h = ch - abs(dy);
2827 if ((h < 0) || (w < 0))
2828 {
1ecc4d80
RR
2829 Refresh();
2830 return;
362c6693 2831 }
c801d85f
KB
2832 int s_x = 0;
2833 int s_y = 0;
2834 if (dx < 0) s_x = -dx;
2835 if (dy < 0) s_y = -dy;
2836 int d_x = 0;
2837 int d_y = 0;
2838 if (dx > 0) d_x = dx;
2839 if (dy > 0) d_y = dy;
8bbe427f 2840
32e9da8b
RR
2841 if (!m_scrollGC)
2842 {
1ecc4d80
RR
2843 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2844 gdk_gc_set_exposures( m_scrollGC, TRUE );
32e9da8b 2845 }
8bbe427f 2846
32e9da8b 2847 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
1ecc4d80 2848 m_wxwindow->window, s_x, s_y, w, h );
47d67540 2849
c801d85f
KB
2850 wxRect rect;
2851 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2852 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2853 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2854 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
47d67540 2855
c801d85f 2856 Refresh( TRUE, &rect );
362c6693 2857}
c801d85f
KB
2858
2859//-------------------------------------------------------------------------------------
2860// Layout
2861//-------------------------------------------------------------------------------------
2862
68dda785 2863wxLayoutConstraints *wxWindow::GetConstraints() const
c801d85f
KB
2864{
2865 return m_constraints;
362c6693 2866}
c801d85f
KB
2867
2868void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2869{
2870 if (m_constraints)
2871 {
2872 UnsetConstraints(m_constraints);
2873 delete m_constraints;
2874 }
2875 m_constraints = constraints;
2876 if (m_constraints)
2877 {
2878 // Make sure other windows know they're part of a 'meaningful relationship'
2879 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2880 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2881 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2882 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2883 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2884 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2885 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2886 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2887 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2888 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2889 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2890 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2891 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2892 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2893 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2894 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2895 }
2896;
2897}
2898;
2899
debe6624 2900void wxWindow::SetAutoLayout( bool autoLayout )
c801d85f
KB
2901{
2902 m_autoLayout = autoLayout;
362c6693 2903}
c801d85f 2904
68dda785 2905bool wxWindow::GetAutoLayout() const
c801d85f
KB
2906{
2907 return m_autoLayout;
362c6693 2908}
c801d85f 2909
68dda785 2910wxSizer *wxWindow::GetSizer() const
c801d85f
KB
2911{
2912 return m_windowSizer;
362c6693 2913}
c801d85f
KB
2914
2915void wxWindow::SetSizerParent( wxWindow *win )
2916{
2917 m_sizerParent = win;
362c6693 2918}
c801d85f 2919
68dda785 2920wxWindow *wxWindow::GetSizerParent() const
c801d85f
KB
2921{
2922 return m_sizerParent;
362c6693 2923}
c801d85f
KB
2924
2925// This removes any dangling pointers to this window
2926// in other windows' constraintsInvolvedIn lists.
2927void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2928{
2929 if (c)
2930 {
2931 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2932 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2933 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2934 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2935 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2936 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2937 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2938 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2939 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2940 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2941 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2942 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2943 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2944 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2945 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2946 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2947 }
2948}
2949
2950// Back-pointer to other windows we're involved with, so if we delete
2951// this window, we must delete any constraints we're involved with.
2952void wxWindow::AddConstraintReference(wxWindow *otherWin)
2953{
2954 if (!m_constraintsInvolvedIn)
2955 m_constraintsInvolvedIn = new wxList;
2956 if (!m_constraintsInvolvedIn->Member(otherWin))
2957 m_constraintsInvolvedIn->Append(otherWin);
2958}
2959
2960// REMOVE back-pointer to other windows we're involved with.
2961void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2962{
2963 if (m_constraintsInvolvedIn)
2964 m_constraintsInvolvedIn->DeleteObject(otherWin);
2965}
2966
2967// Reset any constraints that mention this window
68dda785 2968void wxWindow::DeleteRelatedConstraints()
c801d85f
KB
2969{
2970 if (m_constraintsInvolvedIn)
2971 {
2972 wxNode *node = m_constraintsInvolvedIn->First();
2973 while (node)
2974 {
2975 wxWindow *win = (wxWindow *)node->Data();
2976 wxNode *next = node->Next();
2977 wxLayoutConstraints *constr = win->GetConstraints();
2978
2979 // Reset any constraints involving this window
2980 if (constr)
2981 {
2982 constr->left.ResetIfWin((wxWindow *)this);
2983 constr->top.ResetIfWin((wxWindow *)this);
2984 constr->right.ResetIfWin((wxWindow *)this);
2985 constr->bottom.ResetIfWin((wxWindow *)this);
2986 constr->width.ResetIfWin((wxWindow *)this);
2987 constr->height.ResetIfWin((wxWindow *)this);
2988 constr->centreX.ResetIfWin((wxWindow *)this);
2989 constr->centreY.ResetIfWin((wxWindow *)this);
2990 }
2991 delete node;
2992 node = next;
2993 }
2994 delete m_constraintsInvolvedIn;
c67daf87 2995 m_constraintsInvolvedIn = (wxList *) NULL;
c801d85f
KB
2996 }
2997}
2998
2999void wxWindow::SetSizer(wxSizer *sizer)
3000{
3001 m_windowSizer = sizer;
3002 if (sizer)
3003 sizer->SetSizerParent((wxWindow *)this);
3004}
3005
3006/*
3007 * New version
3008 */
3009
68dda785 3010bool wxWindow::Layout()
c801d85f
KB
3011{
3012 if (GetConstraints())
3013 {
3014 int w, h;
3015 GetClientSize(&w, &h);
3016 GetConstraints()->width.SetValue(w);
3017 GetConstraints()->height.SetValue(h);
3018 }
47d67540 3019
c801d85f
KB
3020 // If top level (one sizer), evaluate the sizer's constraints.
3021 if (GetSizer())
3022 {
3023 int noChanges;
3024 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3025 GetSizer()->LayoutPhase1(&noChanges);
3026 GetSizer()->LayoutPhase2(&noChanges);
3027 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3028 return TRUE;
3029 }
3030 else
3031 {
3032 // Otherwise, evaluate child constraints
3033 ResetConstraints(); // Mark all constraints as unevaluated
3034 DoPhase(1); // Just one phase need if no sizers involved
3035 DoPhase(2);
3036 SetConstraintSizes(); // Recursively set the real window sizes
3037 }
3038 return TRUE;
3039}
3040
3041
3042// Do a phase of evaluating constraints:
3043// the default behaviour. wxSizers may do a similar
3044// thing, but also impose their own 'constraints'
3045// and order the evaluation differently.
3046bool wxWindow::LayoutPhase1(int *noChanges)
3047{
3048 wxLayoutConstraints *constr = GetConstraints();
3049 if (constr)
3050 {
3051 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3052 }
3053 else
3054 return TRUE;
3055}
3056
3057bool wxWindow::LayoutPhase2(int *noChanges)
3058{
3059 *noChanges = 0;
47d67540 3060
c801d85f
KB
3061 // Layout children
3062 DoPhase(1);
3063 DoPhase(2);
3064 return TRUE;
3065}
3066
3067// Do a phase of evaluating child constraints
debe6624 3068bool wxWindow::DoPhase(int phase)
c801d85f
KB
3069{
3070 int noIterations = 0;
3071 int maxIterations = 500;
3072 int noChanges = 1;
3073 int noFailures = 0;
3074 wxList succeeded;
3075 while ((noChanges > 0) && (noIterations < maxIterations))
3076 {
3077 noChanges = 0;
3078 noFailures = 0;
8bbe427f 3079 wxNode *node = m_children.First();
c801d85f
KB
3080 while (node)
3081 {
3082 wxWindow *child = (wxWindow *)node->Data();
3083 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3084 {
3085 wxLayoutConstraints *constr = child->GetConstraints();
3086 if (constr)
3087 {
3088 if (succeeded.Member(child))
3089 {
3090 }
3091 else
3092 {
3093 int tempNoChanges = 0;
3094 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3095 noChanges += tempNoChanges;
3096 if (success)
3097 {
3098 succeeded.Append(child);
3099 }
3100 }
3101 }
3102 }
3103 node = node->Next();
3104 }
3105 noIterations ++;
3106 }
3107 return TRUE;
3108}
3109
68dda785 3110void wxWindow::ResetConstraints()
c801d85f
KB
3111{
3112 wxLayoutConstraints *constr = GetConstraints();
3113 if (constr)
3114 {
3115 constr->left.SetDone(FALSE);
3116 constr->top.SetDone(FALSE);
3117 constr->right.SetDone(FALSE);
3118 constr->bottom.SetDone(FALSE);
3119 constr->width.SetDone(FALSE);
3120 constr->height.SetDone(FALSE);
3121 constr->centreX.SetDone(FALSE);
3122 constr->centreY.SetDone(FALSE);
3123 }
db1b4961 3124 wxNode *node = m_children.First();
c801d85f
KB
3125 while (node)
3126 {
3127 wxWindow *win = (wxWindow *)node->Data();
3128 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3129 win->ResetConstraints();
3130 node = node->Next();
3131 }
3132}
3133
3134// Need to distinguish between setting the 'fake' size for
3135// windows and sizers, and setting the real values.
debe6624 3136void wxWindow::SetConstraintSizes(bool recurse)
c801d85f
KB
3137{
3138 wxLayoutConstraints *constr = GetConstraints();
3139 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3140 constr->width.GetDone() && constr->height.GetDone())
3141 {
3142 int x = constr->left.GetValue();
3143 int y = constr->top.GetValue();
3144 int w = constr->width.GetValue();
3145 int h = constr->height.GetValue();
3146
3147 // If we don't want to resize this window, just move it...
3148 if ((constr->width.GetRelationship() != wxAsIs) ||
3149 (constr->height.GetRelationship() != wxAsIs))
3150 {
3151 // Calls Layout() recursively. AAAGH. How can we stop that.
3152 // Simply take Layout() out of non-top level OnSizes.
3153 SizerSetSize(x, y, w, h);
3154 }
3155 else
3156 {
3157 SizerMove(x, y);
3158 }
3159 }
3160 else if (constr)
3161 {
3162 char *windowClass = this->GetClassInfo()->GetClassName();
3163
3164 wxString winName;
5e0aa05a 3165 if (GetName() == "")
3069ac4e 3166 winName = "unnamed";
5e0aa05a
VZ
3167 else
3168 winName = GetName();
3069ac4e
RR
3169 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3170 (const char *)windowClass,
3171 (const char *)winName);
3172 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3173 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3174 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3175 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3176 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
c801d85f
KB
3177 }
3178
3179 if (recurse)
3180 {
db1b4961 3181 wxNode *node = m_children.First();
c801d85f
KB
3182 while (node)
3183 {
3184 wxWindow *win = (wxWindow *)node->Data();
3185 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3186 win->SetConstraintSizes();
3187 node = node->Next();
3188 }
3189 }
3190}
3191
3192// This assumes that all sizers are 'on' the same
3193// window, i.e. the parent of this window.
3194void wxWindow::TransformSizerToActual(int *x, int *y) const
3195{
3196 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
5e0aa05a 3197 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
c801d85f 3198 return;
47d67540 3199
c801d85f
KB
3200 int xp, yp;
3201 m_sizerParent->GetPosition(&xp, &yp);
3202 m_sizerParent->TransformSizerToActual(&xp, &yp);
3203 *x += xp;
3204 *y += yp;
3205}
3206
debe6624 3207void wxWindow::SizerSetSize(int x, int y, int w, int h)
c801d85f 3208{
5e0aa05a
VZ
3209 int xx = x;
3210 int yy = y;
c801d85f
KB
3211 TransformSizerToActual(&xx, &yy);
3212 SetSize(xx, yy, w, h);
3213}
3214
debe6624 3215void wxWindow::SizerMove(int x, int y)
c801d85f 3216{
5e0aa05a
VZ
3217 int xx = x;
3218 int yy = y;
c801d85f
KB
3219 TransformSizerToActual(&xx, &yy);
3220 Move(xx, yy);
3221}
3222
3223// Only set the size/position of the constraint (if any)
debe6624 3224void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
c801d85f
KB
3225{
3226 wxLayoutConstraints *constr = GetConstraints();
3227 if (constr)
3228 {
3229 if (x != -1)
3230 {
3231 constr->left.SetValue(x);
3232 constr->left.SetDone(TRUE);
3233 }
3234 if (y != -1)
3235 {
3236 constr->top.SetValue(y);
3237 constr->top.SetDone(TRUE);
3238 }
3239 if (w != -1)
3240 {
3241 constr->width.SetValue(w);
3242 constr->width.SetDone(TRUE);
3243 }
3244 if (h != -1)
3245 {
3246 constr->height.SetValue(h);
3247 constr->height.SetDone(TRUE);
3248 }
3249 }
3250}
3251
debe6624 3252void wxWindow::MoveConstraint(int x, int y)
c801d85f
KB
3253{
3254 wxLayoutConstraints *constr = GetConstraints();
3255 if (constr)
3256 {
3257 if (x != -1)
3258 {
3259 constr->left.SetValue(x);
3260 constr->left.SetDone(TRUE);
3261 }
3262 if (y != -1)
3263 {
3264 constr->top.SetValue(y);
3265 constr->top.SetDone(TRUE);
3266 }
3267 }
3268}
3269
3270void wxWindow::GetSizeConstraint(int *w, int *h) const
3271{
3272 wxLayoutConstraints *constr = GetConstraints();
3273 if (constr)
3274 {
3275 *w = constr->width.GetValue();
3276 *h = constr->height.GetValue();
3277 }
3278 else
3279 GetSize(w, h);
3280}
3281
3282void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3283{
3284 wxLayoutConstraints *constr = GetConstraints();
3285 if (constr)
3286 {
3287 *w = constr->width.GetValue();
3288 *h = constr->height.GetValue();
3289 }
3290 else
3291 GetClientSize(w, h);
3292}
3293
3294void wxWindow::GetPositionConstraint(int *x, int *y) const
3295{
b292e2f5
RR
3296 wxLayoutConstraints *constr = GetConstraints();
3297 if (constr)
c801d85f
KB
3298 {
3299 *x = constr->left.GetValue();
3300 *y = constr->top.GetValue();
3301 }
3302 else
3303 GetPosition(x, y);
3304}
3305
e3e65dac 3306void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
5e0aa05a 3307{
b292e2f5 3308 UpdateWindowUI();
5e0aa05a 3309}