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