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