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