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