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