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