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