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