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