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