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