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