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