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