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