]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
wxToolTip
[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))
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 m_toolTip = (wxToolTip*) NULL;
1355 }
1356
1357 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
1358 const wxPoint &pos, const wxSize &size,
1359 long style, const wxString &name )
1360 {
1361 m_insertCallback = wxInsertChildInWindow;
1362 Create( parent, id, pos, size, style, name );
1363 }
1364
1365 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
1366 const wxPoint &pos, const wxSize &size,
1367 long style, const wxString &name )
1368 {
1369 m_isShown = FALSE;
1370 m_isEnabled = TRUE;
1371 m_needParent = TRUE;
1372
1373 PreCreation( parent, id, pos, size, style, name );
1374
1375 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
1376 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
1377
1378 #ifdef __WXDEBUG__
1379 debug_focus_in( m_widget, "wxWindow::m_widget", name );
1380 #endif
1381
1382 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
1383
1384 #ifdef __WXDEBUG__
1385 debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
1386 debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
1387 #endif
1388
1389 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1390 scroll_class->scrollbar_spacing = 0;
1391
1392 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1393
1394 m_oldHorizontalPos = 0.0;
1395 m_oldVerticalPos = 0.0;
1396
1397 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1398 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
1399
1400 m_wxwindow = gtk_myfixed_new();
1401
1402 #ifdef __WXDEBUG__
1403 debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
1404 #endif
1405
1406 #ifdef NEW_GTK_SCROLL_CODE
1407 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1408 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1409 #else
1410 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1411 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
1412 #endif
1413
1414 #ifdef __WXDEBUG__
1415 debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
1416 #endif
1417
1418 if (m_windowStyle & wxRAISED_BORDER)
1419 {
1420 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1421 }
1422 else if (m_windowStyle & wxSUNKEN_BORDER)
1423 {
1424 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1425 }
1426 else
1427 {
1428 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1429 }
1430
1431 if (m_windowStyle & wxTAB_TRAVERSAL)
1432 {
1433 /* we now allow a window to get the focus as long as it
1434 doesn't have any children. */
1435 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1436 m_acceptsFocus = FALSE;
1437 }
1438 else
1439 {
1440 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1441 m_acceptsFocus = TRUE;
1442 }
1443
1444 // shut the viewport up
1445 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1446 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1447
1448 // I _really_ don't want scrollbars in the beginning
1449 m_vAdjust->lower = 0.0;
1450 m_vAdjust->upper = 1.0;
1451 m_vAdjust->value = 0.0;
1452 m_vAdjust->step_increment = 1.0;
1453 m_vAdjust->page_increment = 1.0;
1454 m_vAdjust->page_size = 5.0;
1455 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1456 m_hAdjust->lower = 0.0;
1457 m_hAdjust->upper = 1.0;
1458 m_hAdjust->value = 0.0;
1459 m_hAdjust->step_increment = 1.0;
1460 m_hAdjust->page_increment = 1.0;
1461 m_hAdjust->page_size = 5.0;
1462 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1463
1464 // these handlers block mouse events to any window during scrolling
1465 // such as motion events and prevent GTK and wxWindows from fighting
1466 // over where the slider should be
1467
1468 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1469 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1470
1471 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1472 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1473
1474 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1475 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1476
1477 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1478 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1479
1480 // these handers het notified when screen updates are required either when
1481 // scrolling or when the window size (and therefore scrollbar configuration)
1482 // has changed
1483
1484 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1485 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1486 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1487 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1488
1489 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1490 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1491 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1492 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1493
1494 gtk_widget_show( m_wxwindow );
1495
1496 if (m_parent) m_parent->AddChild( this );
1497
1498 (m_parent->m_insertCallback)( m_parent, this );
1499
1500 PostCreation();
1501
1502 Show( TRUE );
1503
1504 return TRUE;
1505 }
1506
1507 wxWindow::~wxWindow()
1508 {
1509 m_hasVMT = FALSE;
1510
1511 #if wxUSE_DRAG_AND_DROP
1512 if (m_dropTarget) delete m_dropTarget;
1513 #endif
1514
1515 if (m_toolTip) delete m_toolTip;
1516
1517 if (m_parent) m_parent->RemoveChild( this );
1518 if (m_widget) Show( FALSE );
1519
1520 DestroyChildren();
1521
1522 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1523
1524 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1525
1526 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1527
1528 if (m_widget) gtk_widget_destroy( m_widget );
1529
1530 if (m_cursor) delete m_cursor;
1531
1532 DeleteRelatedConstraints();
1533 if (m_constraints)
1534 {
1535 // This removes any dangling pointers to this window
1536 // in other windows' constraintsInvolvedIn lists.
1537 UnsetConstraints(m_constraints);
1538 delete m_constraints;
1539 m_constraints = (wxLayoutConstraints *) NULL;
1540 }
1541 if (m_windowSizer)
1542 {
1543 delete m_windowSizer;
1544 m_windowSizer = (wxSizer *) NULL;
1545 }
1546 // If this is a child of a sizer, remove self from parent
1547 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1548
1549 // Just in case the window has been Closed, but
1550 // we're then deleting immediately: don't leave
1551 // dangling pointers.
1552 wxPendingDelete.DeleteObject(this);
1553
1554 // Just in case we've loaded a top-level window via
1555 // wxWindow::LoadNativeDialog but we weren't a dialog
1556 // class
1557 wxTopLevelWindows.DeleteObject(this);
1558
1559 if (m_windowValidator) delete m_windowValidator;
1560
1561 if (m_clientObject) delete m_clientObject;
1562 }
1563
1564 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1565 const wxPoint &pos, const wxSize &size,
1566 long style, const wxString &name )
1567 {
1568 wxASSERT_MSG( (!m_needParent) || (parent), "Need complete parent." );
1569
1570 m_widget = (GtkWidget*) NULL;
1571 m_wxwindow = (GtkWidget*) NULL;
1572 m_hasVMT = FALSE;
1573 m_parent = parent;
1574 m_children.DeleteContents( FALSE );
1575
1576 m_width = size.x;
1577 if (m_width == -1) m_width = 20;
1578 m_height = size.y;
1579 if (m_height == -1) m_height = 20;
1580
1581 m_x = (int)pos.x;
1582 m_y = (int)pos.y;
1583
1584 if (!m_needParent) // some reasonable defaults
1585 {
1586 if (m_x == -1)
1587 {
1588 m_x = (gdk_screen_width () - m_width) / 2;
1589 if (m_x < 10) m_x = 10;
1590 }
1591 if (m_y == -1)
1592 {
1593 m_y = (gdk_screen_height () - m_height) / 2;
1594 if (m_y < 10) m_y = 10;
1595 }
1596 }
1597
1598 m_minWidth = -1;
1599 m_minHeight = -1;
1600 m_maxWidth = -1;
1601 m_maxHeight = -1;
1602
1603 m_retCode = 0;
1604
1605 m_eventHandler = this;
1606
1607 m_windowId = id == -1 ? wxNewId() : id;
1608
1609 m_sizeSet = FALSE;
1610
1611 m_cursor = new wxCursor( wxCURSOR_ARROW );
1612 m_font = *wxSWISS_FONT;
1613 m_backgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
1614 m_foregroundColour = *wxBLACK;
1615 m_windowStyle = style;
1616 m_windowName = name;
1617
1618 m_constraints = (wxLayoutConstraints *) NULL;
1619 m_constraintsInvolvedIn = (wxList *) NULL;
1620 m_windowSizer = (wxSizer *) NULL;
1621 m_sizerParent = (wxWindow *) NULL;
1622 m_autoLayout = FALSE;
1623
1624 m_hasScrolling = FALSE;
1625 m_isScrolling = FALSE;
1626 m_hAdjust = (GtkAdjustment *) NULL;
1627 m_vAdjust = (GtkAdjustment *) NULL;
1628 m_oldHorizontalPos = 0.0;
1629 m_oldVerticalPos = 0.0;
1630
1631 m_isShown = FALSE;
1632 m_isEnabled = TRUE;
1633
1634 #if wxUSE_DRAG_AND_DROP
1635 m_dropTarget = (wxDropTarget *) NULL;
1636 #endif
1637 m_resizing = FALSE;
1638 m_windowValidator = (wxValidator *) NULL;
1639 m_scrollGC = (GdkGC*) NULL;
1640 m_widgetStyle = (GtkStyle*) NULL;
1641
1642 m_clientObject = (wxClientData*)NULL;
1643 m_clientData = NULL;
1644
1645 m_isStaticBox = FALSE;
1646 m_toolTip = (wxToolTip*) NULL;
1647 }
1648
1649 void wxWindow::PostCreation()
1650 {
1651 if (m_wxwindow)
1652 {
1653 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1654 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1655
1656 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1657 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1658 }
1659
1660 ConnectWidget( GetConnectWidget() );
1661
1662 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1663
1664 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1665
1666 SetCursor( *wxSTANDARD_CURSOR );
1667
1668 m_hasVMT = TRUE;
1669 }
1670
1671 void wxWindow::ConnectWidget( GtkWidget *widget )
1672 {
1673 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1674 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1675
1676 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1677 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1678
1679 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1680 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1681
1682 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1683 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1684
1685 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1686 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1687
1688 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1689 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1690
1691 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1692 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1693
1694 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1695 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1696
1697 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1698 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1699 }
1700
1701 bool wxWindow::HasVMT()
1702 {
1703 return m_hasVMT;
1704 }
1705
1706 bool wxWindow::Close( bool force )
1707 {
1708 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1709
1710 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1711 event.SetEventObject(this);
1712 event.SetForce(force);
1713
1714 return GetEventHandler()->ProcessEvent(event);
1715 }
1716
1717 bool wxWindow::Destroy()
1718 {
1719 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1720
1721 m_hasVMT = FALSE;
1722 delete this;
1723 return TRUE;
1724 }
1725
1726 bool wxWindow::DestroyChildren()
1727 {
1728 wxNode *node;
1729 while ((node = m_children.First()) != (wxNode *)NULL)
1730 {
1731 wxWindow *child;
1732 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1733 {
1734 delete child;
1735 if (m_children.Member(child)) delete node;
1736 }
1737 }
1738 return TRUE;
1739 }
1740
1741 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1742 {
1743 // are we to set fonts here ?
1744 }
1745
1746 wxPoint wxWindow::GetClientAreaOrigin() const
1747 {
1748 return wxPoint(0,0);
1749 }
1750
1751 void wxWindow::AdjustForParentClientOrigin( int& x, int& y, int sizeFlags )
1752 {
1753 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
1754 {
1755 wxPoint pt(GetParent()->GetClientAreaOrigin());
1756 x += pt.x;
1757 y += pt.y;
1758 }
1759 }
1760
1761 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1762 {
1763 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1764 wxASSERT_MSG( (m_parent != NULL), "wxWindow::SetSize requires parent.\n" );
1765
1766 if (m_resizing) return; // I don't like recursions
1767 m_resizing = TRUE;
1768
1769 if (m_parent->m_wxwindow == NULL) // i.e. wxNotebook
1770 {
1771 // don't set the size for children of wxNotebook, just take the values.
1772 m_x = x;
1773 m_y = y;
1774 m_width = width;
1775 m_height = height;
1776 }
1777 else
1778 {
1779 int old_width = m_width;
1780 int old_height = m_height;
1781
1782 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1783 {
1784 if (x != -1) m_x = x;
1785 if (y != -1) m_y = y;
1786 if (width != -1) m_width = width;
1787 if (height != -1) m_height = height;
1788 }
1789 else
1790 {
1791 m_x = x;
1792 m_y = y;
1793 m_width = width;
1794 m_height = height;
1795 }
1796
1797 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1798 {
1799 if (width == -1) m_width = 80;
1800 }
1801
1802 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1803 {
1804 if (height == -1) m_height = 26;
1805 }
1806
1807 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1808 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1809 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1810 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
1811
1812 wxPoint pt( m_parent->GetClientAreaOrigin() );
1813 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
1814
1815 if ((old_width != m_width) || (old_height != m_height))
1816 gtk_widget_set_usize( m_widget, m_width, m_height );
1817 }
1818
1819 m_sizeSet = TRUE;
1820
1821 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1822 event.SetEventObject( this );
1823 GetEventHandler()->ProcessEvent( event );
1824
1825 m_resizing = FALSE;
1826 }
1827
1828 void wxWindow::OnInternalIdle()
1829 {
1830 UpdateWindowUI();
1831 }
1832
1833 void wxWindow::SetSize( int width, int height )
1834 {
1835 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1836 }
1837
1838 void wxWindow::Move( int x, int y )
1839 {
1840 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1841 }
1842
1843 void wxWindow::GetSize( int *width, int *height ) const
1844 {
1845 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1846
1847 if (width) (*width) = m_width;
1848 if (height) (*height) = m_height;
1849 }
1850
1851 void wxWindow::SetClientSize( int width, int height )
1852 {
1853 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1854
1855 if (!m_wxwindow)
1856 {
1857 SetSize( width, height );
1858 }
1859 else
1860 {
1861 int dw = 0;
1862 int dh = 0;
1863
1864 if (!m_hasScrolling)
1865 {
1866 GtkStyleClass *window_class = m_wxwindow->style->klass;
1867
1868 if ((m_windowStyle & wxRAISED_BORDER) ||
1869 (m_windowStyle & wxSUNKEN_BORDER))
1870 {
1871 dw += 2 * window_class->xthickness;
1872 dh += 2 * window_class->ythickness;
1873 }
1874 }
1875 else
1876 {
1877 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1878 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1879
1880 #ifdef NEW_GTK_SCROLL_CODE
1881 GtkWidget *viewport = scroll_window->child;
1882 #else
1883 GtkWidget *viewport = scroll_window->viewport;
1884 #endif
1885
1886 GtkStyleClass *viewport_class = viewport->style->klass;
1887
1888 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1889 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1890
1891 if ((m_windowStyle & wxRAISED_BORDER) ||
1892 (m_windowStyle & wxSUNKEN_BORDER))
1893 {
1894 dw += 2 * viewport_class->xthickness;
1895 dh += 2 * viewport_class->ythickness;
1896 }
1897
1898 if (scroll_window->vscrollbar_visible)
1899 {
1900 dw += vscrollbar->allocation.width;
1901 dw += scroll_class->scrollbar_spacing;
1902 }
1903
1904 if (scroll_window->hscrollbar_visible)
1905 {
1906 dh += hscrollbar->allocation.height;
1907 dw += scroll_class->scrollbar_spacing;
1908 }
1909 }
1910
1911 SetSize( width+dw, height+dh );
1912 }
1913 }
1914
1915 void wxWindow::GetClientSize( int *width, int *height ) const
1916 {
1917 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1918
1919 if (!m_wxwindow)
1920 {
1921 if (width) (*width) = m_width;
1922 if (height) (*height) = m_height;
1923 }
1924 else
1925 {
1926 int dw = 0;
1927 int dh = 0;
1928
1929 if (!m_hasScrolling)
1930 {
1931 GtkStyleClass *window_class = m_wxwindow->style->klass;
1932
1933 if ((m_windowStyle & wxRAISED_BORDER) ||
1934 (m_windowStyle & wxSUNKEN_BORDER))
1935 {
1936 dw += 2 * window_class->xthickness;
1937 dh += 2 * window_class->ythickness;
1938 }
1939 }
1940 else
1941 {
1942 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1943 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1944
1945 #ifdef NEW_GTK_SCROLL_CODE
1946 GtkWidget *viewport = scroll_window->child;
1947 #else
1948 GtkWidget *viewport = scroll_window->viewport;
1949 #endif
1950
1951 GtkStyleClass *viewport_class = viewport->style->klass;
1952
1953 if ((m_windowStyle & wxRAISED_BORDER) ||
1954 (m_windowStyle & wxSUNKEN_BORDER))
1955 {
1956 dw += 2 * viewport_class->xthickness;
1957 dh += 2 * viewport_class->ythickness;
1958 }
1959
1960 if (scroll_window->vscrollbar_visible)
1961 {
1962 // dw += vscrollbar->allocation.width;
1963 dw += 15; // range.slider_width = 11 + 2*2pts edge
1964 dw += scroll_class->scrollbar_spacing;
1965 }
1966
1967 if (scroll_window->hscrollbar_visible)
1968 {
1969 // dh += hscrollbar->allocation.height;
1970 dh += 15;
1971 dh += scroll_class->scrollbar_spacing;
1972 }
1973 }
1974
1975 if (width) (*width) = m_width - dw;
1976 if (height) (*height) = m_height - dh;
1977 }
1978 }
1979
1980 void wxWindow::GetPosition( int *x, int *y ) const
1981 {
1982 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1983
1984 if (x) (*x) = m_x;
1985 if (y) (*y) = m_y;
1986 }
1987
1988 void wxWindow::ClientToScreen( int *x, int *y )
1989 {
1990 wxCHECK_RET( (m_widget != NULL), "invalid window" );
1991
1992 GdkWindow *source = (GdkWindow *) NULL;
1993 if (m_wxwindow)
1994 source = m_wxwindow->window;
1995 else
1996 source = m_widget->window;
1997
1998 int org_x = 0;
1999 int org_y = 0;
2000 gdk_window_get_origin( source, &org_x, &org_y );
2001
2002 if (!m_wxwindow)
2003 {
2004 if (GTK_WIDGET_NO_WINDOW (m_widget))
2005 {
2006 org_x += m_widget->allocation.x;
2007 org_y += m_widget->allocation.y;
2008 }
2009 }
2010
2011 wxPoint pt(GetClientAreaOrigin());
2012 org_x += pt.x;
2013 org_y += pt.y;
2014
2015 if (x) *x += org_x;
2016 if (y) *y += org_y;
2017 }
2018
2019 void wxWindow::ScreenToClient( int *x, int *y )
2020 {
2021 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2022
2023 GdkWindow *source = (GdkWindow *) NULL;
2024 if (m_wxwindow)
2025 source = m_wxwindow->window;
2026 else
2027 source = m_widget->window;
2028
2029 int org_x = 0;
2030 int org_y = 0;
2031 gdk_window_get_origin( source, &org_x, &org_y );
2032
2033 if (!m_wxwindow)
2034 {
2035 if (GTK_WIDGET_NO_WINDOW (m_widget))
2036 {
2037 org_x += m_widget->allocation.x;
2038 org_y += m_widget->allocation.y;
2039 }
2040 }
2041
2042 wxPoint pt(GetClientAreaOrigin());
2043 org_x -= pt.x;
2044 org_y -= pt.y;
2045
2046 if (x) *x -= org_x;
2047 if (y) *y -= org_y;
2048 }
2049
2050 void wxWindow::Centre( int direction )
2051 {
2052 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2053
2054 int x = m_x;
2055 int y = m_y;
2056
2057 if (m_parent)
2058 {
2059 int p_w = 0;
2060 int p_h = 0;
2061 m_parent->GetSize( &p_w, &p_h );
2062 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (p_w - m_width) / 2;
2063 if (direction & wxVERTICAL == wxVERTICAL) y = (p_h - m_height) / 2;
2064 }
2065 else
2066 {
2067 if (direction & wxHORIZONTAL == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
2068 if (direction & wxVERTICAL == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
2069 }
2070
2071 Move( x, y );
2072 }
2073
2074 void wxWindow::Fit()
2075 {
2076 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2077
2078 int maxX = 0;
2079 int maxY = 0;
2080 wxNode *node = m_children.First();
2081 while (node)
2082 {
2083 wxWindow *win = (wxWindow *)node->Data();
2084 int wx, wy, ww, wh;
2085 win->GetPosition(&wx, &wy);
2086 win->GetSize(&ww, &wh);
2087 if (wx + ww > maxX) maxX = wx + ww;
2088 if (wy + wh > maxY) maxY = wy + wh;
2089
2090 node = node->Next();
2091 }
2092
2093 SetClientSize(maxX + 7, maxY + 14);
2094 }
2095
2096 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
2097 {
2098 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2099
2100 m_minWidth = minW;
2101 m_minHeight = minH;
2102 m_maxWidth = maxW;
2103 m_maxHeight = maxH;
2104 }
2105
2106 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
2107 {
2108 // if (GetAutoLayout()) Layout();
2109 }
2110
2111 bool wxWindow::Show( bool show )
2112 {
2113 wxCHECK_MSG( (m_widget != NULL), FALSE, "invalid window" );
2114
2115 if (show)
2116 gtk_widget_show( m_widget );
2117 else
2118 gtk_widget_hide( m_widget );
2119
2120 m_isShown = show;
2121
2122 return TRUE;
2123 }
2124
2125 void wxWindow::Enable( bool enable )
2126 {
2127 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2128
2129 m_isEnabled = enable;
2130
2131 gtk_widget_set_sensitive( m_widget, enable );
2132 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
2133 }
2134
2135 int wxWindow::GetCharHeight() const
2136 {
2137 wxCHECK_MSG( (m_widget != NULL), 12, "invalid window" );
2138
2139 wxCHECK_MSG( m_font.Ok(), 12, "invalid font" );
2140
2141 GdkFont *font = m_font.GetInternalFont( 1.0 );
2142
2143 return font->ascent + font->descent;
2144 }
2145
2146 int wxWindow::GetCharWidth() const
2147 {
2148 wxCHECK_MSG( (m_widget != NULL), 8, "invalid window" );
2149
2150 wxCHECK_MSG( m_font.Ok(), 8, "invalid font" );
2151
2152 GdkFont *font = m_font.GetInternalFont( 1.0 );
2153
2154 return gdk_string_width( font, "H" );
2155 }
2156
2157 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
2158 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
2159 {
2160 wxFont fontToUse = m_font;
2161 if (theFont) fontToUse = *theFont;
2162
2163 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
2164
2165 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
2166 if (x) (*x) = gdk_string_width( font, string );
2167 if (y) (*y) = font->ascent + font->descent;
2168 if (descent) (*descent) = font->descent;
2169 if (externalLeading) (*externalLeading) = 0; // ??
2170 }
2171
2172 void wxWindow::MakeModal( bool modal )
2173 {
2174 return;
2175
2176 // Disable all other windows
2177 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
2178 {
2179 wxNode *node = wxTopLevelWindows.First();
2180 while (node)
2181 {
2182 wxWindow *win = (wxWindow *)node->Data();
2183 if (win != this) win->Enable(!modal);
2184
2185 node = node->Next();
2186 }
2187 }
2188 }
2189
2190 void wxWindow::OnKeyDown( wxKeyEvent &event )
2191 {
2192 event.SetEventType( wxEVT_CHAR );
2193
2194 if (!GetEventHandler()->ProcessEvent( event ))
2195 {
2196 event.Skip();
2197 }
2198 }
2199
2200 void wxWindow::SetFocus()
2201 {
2202 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2203
2204 GtkWidget *connect_widget = GetConnectWidget();
2205 if (connect_widget)
2206 {
2207 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2208 {
2209 gtk_widget_grab_focus (connect_widget);
2210 }
2211 else if (GTK_IS_CONTAINER(connect_widget))
2212 {
2213 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2214 }
2215 else
2216 {
2217 }
2218 }
2219 }
2220
2221 wxWindow *wxWindow::FindFocus()
2222 {
2223 return g_focusWindow;
2224 }
2225
2226 bool wxWindow::AcceptsFocus() const
2227 {
2228 return IsEnabled() && IsShown() && m_acceptsFocus;
2229 }
2230
2231 bool wxWindow::OnClose()
2232 {
2233 return TRUE;
2234 }
2235
2236 void wxWindow::AddChild( wxWindow *child )
2237 {
2238 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2239 wxCHECK_RET( (child != NULL), "invalid child" );
2240
2241 m_children.Append( child );
2242 }
2243
2244 wxWindow *wxWindow::ReParent( wxWindow *newParent )
2245 {
2246 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, "invalid window" );
2247
2248 wxWindow *oldParent = GetParent();
2249
2250 if (oldParent) oldParent->RemoveChild( this );
2251
2252 gtk_widget_unparent( m_widget );
2253
2254 if (newParent)
2255 {
2256 newParent->AddChild( this );
2257 (newParent->m_insertCallback)( newParent, this );
2258 }
2259
2260 return oldParent;
2261 }
2262
2263 void wxWindow::RemoveChild( wxWindow *child )
2264 {
2265 m_children.DeleteObject( child );
2266 child->m_parent = (wxWindow *) NULL;
2267 }
2268
2269 void wxWindow::SetReturnCode( int retCode )
2270 {
2271 m_retCode = retCode;
2272 }
2273
2274 int wxWindow::GetReturnCode()
2275 {
2276 return m_retCode;
2277 }
2278
2279 void wxWindow::Raise()
2280 {
2281 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2282
2283 if (m_widget) gdk_window_raise( m_widget->window );
2284 }
2285
2286 void wxWindow::Lower()
2287 {
2288 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2289
2290 if (m_widget) gdk_window_lower( m_widget->window );
2291 }
2292
2293 wxEvtHandler *wxWindow::GetEventHandler() const
2294 {
2295 return m_eventHandler;
2296 }
2297
2298 void wxWindow::SetEventHandler( wxEvtHandler *handler )
2299 {
2300 m_eventHandler = handler;
2301 }
2302
2303 void wxWindow::PushEventHandler(wxEvtHandler *handler)
2304 {
2305 handler->SetNextHandler(GetEventHandler());
2306 SetEventHandler(handler);
2307 }
2308
2309 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
2310 {
2311 if (GetEventHandler())
2312 {
2313 wxEvtHandler *handlerA = GetEventHandler();
2314 wxEvtHandler *handlerB = handlerA->GetNextHandler();
2315 handlerA->SetNextHandler((wxEvtHandler *) NULL);
2316 SetEventHandler(handlerB);
2317 if (deleteHandler)
2318 {
2319 delete handlerA;
2320 return (wxEvtHandler*) NULL;
2321 }
2322 else
2323 return handlerA;
2324 }
2325 else
2326 return (wxEvtHandler *) NULL;
2327 }
2328
2329 wxValidator *wxWindow::GetValidator()
2330 {
2331 return m_windowValidator;
2332 }
2333
2334 void wxWindow::SetValidator( const wxValidator& validator )
2335 {
2336 if (m_windowValidator) delete m_windowValidator;
2337 m_windowValidator = validator.Clone();
2338 if (m_windowValidator) m_windowValidator->SetWindow(this);
2339 }
2340
2341 void wxWindow::SetClientObject( wxClientData *data )
2342 {
2343 if (m_clientObject) delete m_clientObject;
2344 m_clientObject = data;
2345 }
2346
2347 wxClientData *wxWindow::GetClientObject()
2348 {
2349 return m_clientObject;
2350 }
2351
2352 void wxWindow::SetClientData( void *data )
2353 {
2354 m_clientData = data;
2355 }
2356
2357 void *wxWindow::GetClientData()
2358 {
2359 return m_clientData;
2360 }
2361
2362 bool wxWindow::IsBeingDeleted()
2363 {
2364 return FALSE;
2365 }
2366
2367 void wxWindow::SetId( wxWindowID id )
2368 {
2369 m_windowId = id;
2370 }
2371
2372 wxWindowID wxWindow::GetId() const
2373 {
2374 return m_windowId;
2375 }
2376
2377 void wxWindow::SetCursor( const wxCursor &cursor )
2378 {
2379 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2380
2381 if (cursor.Ok())
2382 {
2383 if (cursor == *m_cursor) return;
2384 *m_cursor = cursor;
2385 }
2386 else
2387 {
2388 *m_cursor = *wxSTANDARD_CURSOR;
2389 }
2390
2391 if ((m_widget) && (m_widget->window))
2392 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
2393
2394 if ((m_wxwindow) && (m_wxwindow->window))
2395 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
2396 }
2397
2398 void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2399 {
2400 // TODO
2401 }
2402
2403 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
2404 {
2405 wxCHECK_RET( (m_widget != NULL), "invalid window" );
2406
2407 if (eraseBackground && m_wxwindow && m_wxwindow->window)
2408 {
2409 if (rect)
2410 {
2411 gdk_window_clear_area( m_wxwindow->window,
2412 rect->x, rect->y,
2413 rect->width,
2414 rect->height );
2415 }
2416 else
2417 {
2418 Clear();
2419 }
2420 }
2421
2422 if (!rect)
2423 {
2424 if (m_wxwindow)
2425 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
2426 else
2427 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
2428 }
2429 else
2430 {
2431 GdkRectangle gdk_rect;
2432 gdk_rect.x = rect->x;
2433 gdk_rect.y = rect->y;
2434 gdk_rect.width = rect->width;
2435 gdk_rect.height = rect->height;
2436
2437 if (m_wxwindow)
2438 gtk_widget_draw( m_wxwindow, &gdk_rect );
2439 else
2440 gtk_widget_draw( m_widget, &gdk_rect );
2441 }
2442 }
2443
2444 wxRegion wxWindow::GetUpdateRegion() const
2445 {
2446 return m_updateRegion;
2447 }
2448
2449 bool wxWindow::IsExposed( int x, int y) const
2450 {
2451 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
2452 }
2453
2454 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2455 {
2456 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
2457 }
2458
2459 bool wxWindow::IsExposed( const wxPoint& pt ) const
2460 {
2461 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
2462 }
2463
2464 bool wxWindow::IsExposed( const wxRect& rect ) const
2465 {
2466 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
2467 }
2468
2469 void wxWindow::Clear()
2470 {
2471 wxCHECK_RET( m_widget != NULL, "invalid window" );
2472
2473 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
2474 }
2475
2476 void wxWindow::SetToolTip( const wxString &tip )
2477 {
2478 if (m_toolTip)
2479 {
2480 m_toolTip->SetTip( tip );
2481 }
2482 else
2483 {
2484 m_toolTip = new wxToolTip( tip );
2485 m_toolTip->Apply( this );
2486 }
2487
2488 if (tip.IsEmpty())
2489 {
2490 delete m_toolTip;
2491 m_toolTip = (wxToolTip*) NULL;
2492 }
2493 }
2494
2495 void wxWindow::SetToolTip( wxToolTip *tip )
2496 {
2497 if (m_toolTip)
2498 {
2499 m_toolTip->SetTip( (char*) NULL );
2500 delete m_toolTip;
2501 }
2502
2503 m_toolTip = tip;
2504
2505 if (m_toolTip) m_toolTip->Apply( this );
2506 }
2507
2508 void wxWindow::ApplyToolTip( GtkTooltips *tips, const char *tip )
2509 {
2510 gtk_tooltips_set_tip( tips, GetConnectWidget(), tip, (gchar*) NULL );
2511 }
2512
2513 wxToolTip* wxWindow::GetToolTip()
2514 {
2515 return m_toolTip;
2516 }
2517
2518 wxColour wxWindow::GetBackgroundColour() const
2519 {
2520 return m_backgroundColour;
2521 }
2522
2523 void wxWindow::SetBackgroundColour( const wxColour &colour )
2524 {
2525 wxCHECK_RET( m_widget != NULL, "invalid window" );
2526
2527 if (m_backgroundColour == colour) return;
2528
2529 m_backgroundColour = colour;
2530 if (!m_backgroundColour.Ok()) return;
2531
2532 if (m_wxwindow)
2533 {
2534 GdkWindow *window = m_wxwindow->window;
2535 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2536 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2537 gdk_window_clear( window );
2538 }
2539
2540 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2541 if (sysbg.Red() == colour.Red() &&
2542 sysbg.Green() == colour.Green() &&
2543 sysbg.Blue() == colour.Blue())
2544 {
2545 m_backgroundColour = wxNullColour;
2546 ApplyWidgetStyle();
2547 m_backgroundColour = sysbg;
2548 }
2549 else
2550 {
2551 ApplyWidgetStyle();
2552 }
2553 }
2554
2555 wxColour wxWindow::GetForegroundColour() const
2556 {
2557 return m_foregroundColour;
2558 }
2559
2560 void wxWindow::SetForegroundColour( const wxColour &colour )
2561 {
2562 wxCHECK_RET( m_widget != NULL, "invalid window" );
2563
2564 if (m_foregroundColour == colour) return;
2565
2566 m_foregroundColour = colour;
2567 if (!m_foregroundColour.Ok()) return;
2568
2569 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2570 if (sysbg.Red() == colour.Red() &&
2571 sysbg.Green() == colour.Green() &&
2572 sysbg.Blue() == colour.Blue())
2573 {
2574 m_backgroundColour = wxNullColour;
2575 ApplyWidgetStyle();
2576 m_backgroundColour = sysbg;
2577 }
2578 else
2579 {
2580 ApplyWidgetStyle();
2581 }
2582 }
2583
2584 GtkStyle *wxWindow::GetWidgetStyle()
2585 {
2586 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2587
2588 m_widgetStyle =
2589 gtk_style_copy(
2590 gtk_widget_get_style( m_widget ) );
2591
2592 return m_widgetStyle;
2593 }
2594
2595 void wxWindow::SetWidgetStyle()
2596 {
2597 GtkStyle *style = GetWidgetStyle();
2598
2599 gdk_font_unref( style->font );
2600 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2601
2602 if (m_foregroundColour.Ok())
2603 {
2604 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2605 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2606 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2607 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2608 }
2609
2610 if (m_backgroundColour.Ok())
2611 {
2612 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2613 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2614 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2615 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2616 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2617 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2618 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2619 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2620 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2621 }
2622 }
2623
2624 void wxWindow::ApplyWidgetStyle()
2625 {
2626 }
2627
2628 bool wxWindow::Validate()
2629 {
2630 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2631
2632 wxNode *node = m_children.First();
2633 while (node)
2634 {
2635 wxWindow *child = (wxWindow *)node->Data();
2636 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2637 {
2638 return FALSE;
2639 }
2640 node = node->Next();
2641 }
2642 return TRUE;
2643 }
2644
2645 bool wxWindow::TransferDataToWindow()
2646 {
2647 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2648
2649 wxNode *node = m_children.First();
2650 while (node)
2651 {
2652 wxWindow *child = (wxWindow *)node->Data();
2653 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2654 !child->GetValidator()->TransferToWindow() )
2655 {
2656 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2657 return FALSE;
2658 }
2659 node = node->Next();
2660 }
2661 return TRUE;
2662 }
2663
2664 bool wxWindow::TransferDataFromWindow()
2665 {
2666 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2667
2668 wxNode *node = m_children.First();
2669 while (node)
2670 {
2671 wxWindow *child = (wxWindow *)node->Data();
2672 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2673 {
2674 return FALSE;
2675 }
2676 node = node->Next();
2677 }
2678 return TRUE;
2679 }
2680
2681 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2682 {
2683 m_acceleratorTable = accel;
2684 }
2685
2686 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2687 {
2688 TransferDataToWindow();
2689 }
2690
2691 void wxWindow::InitDialog()
2692 {
2693 wxCHECK_RET( m_widget != NULL, "invalid window" );
2694
2695 wxInitDialogEvent event(GetId());
2696 event.SetEventObject( this );
2697 GetEventHandler()->ProcessEvent(event);
2698 }
2699
2700 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2701 {
2702 menu->SetInvokingWindow( win );
2703 wxNode *node = menu->m_items.First();
2704 while (node)
2705 {
2706 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2707 if (menuitem->IsSubMenu())
2708 {
2709 SetInvokingWindow( menuitem->GetSubMenu(), win );
2710 }
2711 node = node->Next();
2712 }
2713 }
2714
2715 static gint gs_pop_x = 0;
2716 static gint gs_pop_y = 0;
2717
2718 static void pop_pos_callback( GtkMenu *menu, gint *x, gint *y, wxWindow *win )
2719 {
2720 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2721 *x = gs_pop_x;
2722 *y = gs_pop_y;
2723 }
2724
2725 bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
2726 {
2727 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2728
2729 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2730
2731 SetInvokingWindow( menu, this );
2732
2733 gs_pop_x = x;
2734 gs_pop_y = y;
2735
2736 gtk_menu_popup(
2737 GTK_MENU(menu->m_menu),
2738 (GtkWidget *) NULL, // parent menu shell
2739 (GtkWidget *) NULL, // parent menu item
2740 (GtkMenuPositionFunc) pop_pos_callback,
2741 (gpointer) this, // client data
2742 0, // button used to activate it
2743 0 //gs_timeLastClick // the time of activation
2744 );
2745 return TRUE;
2746 }
2747
2748 #if wxUSE_DRAG_AND_DROP
2749
2750 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2751 {
2752 wxCHECK_RET( m_widget != NULL, "invalid window" );
2753
2754 GtkWidget *dnd_widget = GetConnectWidget();
2755
2756 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2757
2758 if (m_dropTarget) delete m_dropTarget;
2759 m_dropTarget = dropTarget;
2760
2761 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2762 }
2763
2764 wxDropTarget *wxWindow::GetDropTarget() const
2765 {
2766 return m_dropTarget;
2767 }
2768
2769 #endif
2770
2771 GtkWidget* wxWindow::GetConnectWidget()
2772 {
2773 GtkWidget *connect_widget = m_widget;
2774 if (m_wxwindow) connect_widget = m_wxwindow;
2775
2776 return connect_widget;
2777 }
2778
2779 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2780 {
2781 if (m_wxwindow) return (window == m_wxwindow->window);
2782 return (window == m_widget->window);
2783 }
2784
2785 void wxWindow::SetFont( const wxFont &font )
2786 {
2787 wxCHECK_RET( m_widget != NULL, "invalid window" );
2788
2789 if (((wxFont*)&font)->Ok())
2790 m_font = font;
2791 else
2792 m_font = *wxSWISS_FONT;
2793
2794 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2795 if (sysbg.Red() == m_backgroundColour.Red() &&
2796 sysbg.Green() == m_backgroundColour.Green() &&
2797 sysbg.Blue() == m_backgroundColour.Blue())
2798 {
2799 m_backgroundColour = wxNullColour;
2800 ApplyWidgetStyle();
2801 m_backgroundColour = sysbg;
2802 }
2803 else
2804 {
2805 ApplyWidgetStyle();
2806 }
2807 }
2808
2809 void wxWindow::SetWindowStyleFlag( long flag )
2810 {
2811 m_windowStyle = flag;
2812 }
2813
2814 long wxWindow::GetWindowStyleFlag() const
2815 {
2816 return m_windowStyle;
2817 }
2818
2819 void wxWindow::CaptureMouse()
2820 {
2821 wxCHECK_RET( m_widget != NULL, "invalid window" );
2822
2823 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2824
2825 GtkWidget *connect_widget = GetConnectWidget();
2826 gtk_grab_add( connect_widget );
2827 gdk_pointer_grab( connect_widget->window, FALSE,
2828 (GdkEventMask)
2829 (GDK_BUTTON_PRESS_MASK |
2830 GDK_BUTTON_RELEASE_MASK |
2831 GDK_POINTER_MOTION_MASK),
2832 (GdkWindow *) NULL,
2833 (GdkCursor *) NULL,
2834 GDK_CURRENT_TIME );
2835 g_capturing = TRUE;
2836 }
2837
2838 void wxWindow::ReleaseMouse()
2839 {
2840 wxCHECK_RET( m_widget != NULL, "invalid window" );
2841
2842 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2843
2844 GtkWidget *connect_widget = GetConnectWidget();
2845 gtk_grab_remove( connect_widget );
2846 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2847 g_capturing = FALSE;
2848 }
2849
2850 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2851 {
2852 }
2853
2854 wxString wxWindow::GetTitle() const
2855 {
2856 return (wxString&)m_windowName;
2857 }
2858
2859 wxString wxWindow::GetLabel() const
2860 {
2861 return GetTitle();
2862 }
2863
2864 void wxWindow::SetName( const wxString &name )
2865 {
2866 m_windowName = name;
2867 }
2868
2869 wxString wxWindow::GetName() const
2870 {
2871 return (wxString&)m_windowName;
2872 }
2873
2874 bool wxWindow::IsShown() const
2875 {
2876 return m_isShown;
2877 }
2878
2879 bool wxWindow::IsRetained()
2880 {
2881 return FALSE;
2882 }
2883
2884 wxWindow *wxWindow::FindWindow( long id )
2885 {
2886 if (id == m_windowId) return this;
2887 wxNode *node = m_children.First();
2888 while (node)
2889 {
2890 wxWindow *child = (wxWindow*)node->Data();
2891 wxWindow *res = child->FindWindow( id );
2892 if (res) return res;
2893 node = node->Next();
2894 }
2895 return (wxWindow *) NULL;
2896 }
2897
2898 wxWindow *wxWindow::FindWindow( const wxString& name )
2899 {
2900 if (name == m_windowName) return this;
2901 wxNode *node = m_children.First();
2902 while (node)
2903 {
2904 wxWindow *child = (wxWindow*)node->Data();
2905 wxWindow *res = child->FindWindow( name );
2906 if (res) return res;
2907 node = node->Next();
2908 }
2909 return (wxWindow *) NULL;
2910 }
2911
2912 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2913 int range, bool refresh )
2914 {
2915 wxCHECK_RET( m_widget != NULL, "invalid window" );
2916
2917 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2918
2919 m_hasScrolling = TRUE;
2920
2921 if (orient == wxHORIZONTAL)
2922 {
2923 float fpos = (float)pos;
2924 float frange = (float)range;
2925 float fthumb = (float)thumbVisible;
2926 if (fpos > frange-fthumb) fpos = frange-fthumb;
2927 if (fpos < 0.0) fpos = 0.0;
2928
2929 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2930 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2931 {
2932 SetScrollPos( orient, pos, refresh );
2933 return;
2934 }
2935
2936 m_oldHorizontalPos = fpos;
2937
2938 m_hAdjust->lower = 0.0;
2939 m_hAdjust->upper = frange;
2940 m_hAdjust->value = fpos;
2941 m_hAdjust->step_increment = 1.0;
2942 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2943 m_hAdjust->page_size = fthumb;
2944 }
2945 else
2946 {
2947 float fpos = (float)pos;
2948 float frange = (float)range;
2949 float fthumb = (float)thumbVisible;
2950 if (fpos > frange-fthumb) fpos = frange-fthumb;
2951 if (fpos < 0.0) fpos = 0.0;
2952
2953 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2954 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2955 {
2956 SetScrollPos( orient, pos, refresh );
2957 return;
2958 }
2959
2960 m_oldVerticalPos = fpos;
2961
2962 m_vAdjust->lower = 0.0;
2963 m_vAdjust->upper = frange;
2964 m_vAdjust->value = fpos;
2965 m_vAdjust->step_increment = 1.0;
2966 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2967 m_vAdjust->page_size = fthumb;
2968 }
2969
2970 if (m_wxwindow->window)
2971 {
2972 if (orient == wxHORIZONTAL)
2973 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2974 else
2975 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2976
2977 gtk_widget_set_usize( m_widget, m_width, m_height );
2978 }
2979 }
2980
2981 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2982 {
2983 wxCHECK_RET( m_widget != NULL, "invalid window" );
2984
2985 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
2986
2987 if (orient == wxHORIZONTAL)
2988 {
2989 float fpos = (float)pos;
2990 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2991 if (fpos < 0.0) fpos = 0.0;
2992 m_oldHorizontalPos = fpos;
2993
2994 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2995 m_hAdjust->value = fpos;
2996 }
2997 else
2998 {
2999 float fpos = (float)pos;
3000 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3001 if (fpos < 0.0) fpos = 0.0;
3002 m_oldVerticalPos = fpos;
3003
3004 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3005 m_vAdjust->value = fpos;
3006 }
3007
3008 if (!m_isScrolling)
3009 {
3010 if (m_wxwindow->window)
3011 {
3012 if (orient == wxHORIZONTAL)
3013 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3014 else
3015 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3016 }
3017 }
3018 }
3019
3020 int wxWindow::GetScrollThumb( int orient ) const
3021 {
3022 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3023
3024 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3025
3026 if (orient == wxHORIZONTAL)
3027 return (int)(m_hAdjust->page_size+0.5);
3028 else
3029 return (int)(m_vAdjust->page_size+0.5);
3030 }
3031
3032 int wxWindow::GetScrollPos( int orient ) const
3033 {
3034 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3035
3036 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3037
3038 if (orient == wxHORIZONTAL)
3039 return (int)(m_hAdjust->value+0.5);
3040 else
3041 return (int)(m_vAdjust->value+0.5);
3042 }
3043
3044 int wxWindow::GetScrollRange( int orient ) const
3045 {
3046 wxCHECK_MSG( m_widget != NULL, 0, "invalid window" );
3047
3048 wxCHECK_MSG( m_wxwindow != NULL, 0, "window needs client area for scrolling" );
3049
3050 if (orient == wxHORIZONTAL)
3051 return (int)(m_hAdjust->upper+0.5);
3052 else
3053 return (int)(m_vAdjust->upper+0.5);
3054 }
3055
3056 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
3057 {
3058 wxCHECK_RET( m_widget != NULL, "invalid window" );
3059
3060 wxCHECK_RET( m_wxwindow != NULL, "window needs client area for scrolling" );
3061
3062 int cw = 0;
3063 int ch = 0;
3064 GetClientSize( &cw, &ch );
3065
3066 int w = cw - abs(dx);
3067 int h = ch - abs(dy);
3068 if ((h < 0) || (w < 0))
3069 {
3070 Refresh();
3071 return;
3072 }
3073 int s_x = 0;
3074 int s_y = 0;
3075 if (dx < 0) s_x = -dx;
3076 if (dy < 0) s_y = -dy;
3077 int d_x = 0;
3078 int d_y = 0;
3079 if (dx > 0) d_x = dx;
3080 if (dy > 0) d_y = dy;
3081
3082 if (!m_scrollGC)
3083 {
3084 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3085 gdk_gc_set_exposures( m_scrollGC, TRUE );
3086 }
3087
3088 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3089 m_wxwindow->window, s_x, s_y, w, h );
3090
3091 wxRect rect;
3092 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3093 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3094 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3095 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3096
3097 Refresh( TRUE, &rect );
3098 }
3099
3100 //-------------------------------------------------------------------------------------
3101 // Layout
3102 //-------------------------------------------------------------------------------------
3103
3104 wxLayoutConstraints *wxWindow::GetConstraints() const
3105 {
3106 return m_constraints;
3107 }
3108
3109 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
3110 {
3111 if (m_constraints)
3112 {
3113 UnsetConstraints(m_constraints);
3114 delete m_constraints;
3115 }
3116 m_constraints = constraints;
3117 if (m_constraints)
3118 {
3119 // Make sure other windows know they're part of a 'meaningful relationship'
3120 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3121 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3122 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3123 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3124 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3125 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3126 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3127 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3128 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3129 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3130 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3131 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3132 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3133 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3134 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3135 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3136 }
3137 ;
3138 }
3139 ;
3140
3141 void wxWindow::SetAutoLayout( bool autoLayout )
3142 {
3143 m_autoLayout = autoLayout;
3144 }
3145
3146 bool wxWindow::GetAutoLayout() const
3147 {
3148 return m_autoLayout;
3149 }
3150
3151 wxSizer *wxWindow::GetSizer() const
3152 {
3153 return m_windowSizer;
3154 }
3155
3156 void wxWindow::SetSizerParent( wxWindow *win )
3157 {
3158 m_sizerParent = win;
3159 }
3160
3161 wxWindow *wxWindow::GetSizerParent() const
3162 {
3163 return m_sizerParent;
3164 }
3165
3166 // This removes any dangling pointers to this window
3167 // in other windows' constraintsInvolvedIn lists.
3168 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3169 {
3170 if (c)
3171 {
3172 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3173 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3174 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3175 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3176 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3177 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3178 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3179 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3180 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3181 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3182 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3183 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3184 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3185 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3186 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3187 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3188 }
3189 }
3190
3191 // Back-pointer to other windows we're involved with, so if we delete
3192 // this window, we must delete any constraints we're involved with.
3193 void wxWindow::AddConstraintReference(wxWindow *otherWin)
3194 {
3195 if (!m_constraintsInvolvedIn)
3196 m_constraintsInvolvedIn = new wxList;
3197 if (!m_constraintsInvolvedIn->Member(otherWin))
3198 m_constraintsInvolvedIn->Append(otherWin);
3199 }
3200
3201 // REMOVE back-pointer to other windows we're involved with.
3202 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3203 {
3204 if (m_constraintsInvolvedIn)
3205 m_constraintsInvolvedIn->DeleteObject(otherWin);
3206 }
3207
3208 // Reset any constraints that mention this window
3209 void wxWindow::DeleteRelatedConstraints()
3210 {
3211 if (m_constraintsInvolvedIn)
3212 {
3213 wxNode *node = m_constraintsInvolvedIn->First();
3214 while (node)
3215 {
3216 wxWindow *win = (wxWindow *)node->Data();
3217 wxNode *next = node->Next();
3218 wxLayoutConstraints *constr = win->GetConstraints();
3219
3220 // Reset any constraints involving this window
3221 if (constr)
3222 {
3223 constr->left.ResetIfWin((wxWindow *)this);
3224 constr->top.ResetIfWin((wxWindow *)this);
3225 constr->right.ResetIfWin((wxWindow *)this);
3226 constr->bottom.ResetIfWin((wxWindow *)this);
3227 constr->width.ResetIfWin((wxWindow *)this);
3228 constr->height.ResetIfWin((wxWindow *)this);
3229 constr->centreX.ResetIfWin((wxWindow *)this);
3230 constr->centreY.ResetIfWin((wxWindow *)this);
3231 }
3232 delete node;
3233 node = next;
3234 }
3235 delete m_constraintsInvolvedIn;
3236 m_constraintsInvolvedIn = (wxList *) NULL;
3237 }
3238 }
3239
3240 void wxWindow::SetSizer(wxSizer *sizer)
3241 {
3242 m_windowSizer = sizer;
3243 if (sizer)
3244 sizer->SetSizerParent((wxWindow *)this);
3245 }
3246
3247 /*
3248 * New version
3249 */
3250
3251 bool wxWindow::Layout()
3252 {
3253 if (GetConstraints())
3254 {
3255 int w, h;
3256 GetClientSize(&w, &h);
3257 GetConstraints()->width.SetValue(w);
3258 GetConstraints()->height.SetValue(h);
3259 }
3260
3261 // If top level (one sizer), evaluate the sizer's constraints.
3262 if (GetSizer())
3263 {
3264 int noChanges;
3265 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3266 GetSizer()->LayoutPhase1(&noChanges);
3267 GetSizer()->LayoutPhase2(&noChanges);
3268 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3269 return TRUE;
3270 }
3271 else
3272 {
3273 // Otherwise, evaluate child constraints
3274 ResetConstraints(); // Mark all constraints as unevaluated
3275 DoPhase(1); // Just one phase need if no sizers involved
3276 DoPhase(2);
3277 SetConstraintSizes(); // Recursively set the real window sizes
3278 }
3279 return TRUE;
3280 }
3281
3282
3283 // Do a phase of evaluating constraints:
3284 // the default behaviour. wxSizers may do a similar
3285 // thing, but also impose their own 'constraints'
3286 // and order the evaluation differently.
3287 bool wxWindow::LayoutPhase1(int *noChanges)
3288 {
3289 wxLayoutConstraints *constr = GetConstraints();
3290 if (constr)
3291 {
3292 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
3293 }
3294 else
3295 return TRUE;
3296 }
3297
3298 bool wxWindow::LayoutPhase2(int *noChanges)
3299 {
3300 *noChanges = 0;
3301
3302 // Layout children
3303 DoPhase(1);
3304 DoPhase(2);
3305 return TRUE;
3306 }
3307
3308 // Do a phase of evaluating child constraints
3309 bool wxWindow::DoPhase(int phase)
3310 {
3311 int noIterations = 0;
3312 int maxIterations = 500;
3313 int noChanges = 1;
3314 int noFailures = 0;
3315 wxList succeeded;
3316 while ((noChanges > 0) && (noIterations < maxIterations))
3317 {
3318 noChanges = 0;
3319 noFailures = 0;
3320 wxNode *node = m_children.First();
3321 while (node)
3322 {
3323 wxWindow *child = (wxWindow *)node->Data();
3324 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
3325 {
3326 wxLayoutConstraints *constr = child->GetConstraints();
3327 if (constr)
3328 {
3329 if (succeeded.Member(child))
3330 {
3331 }
3332 else
3333 {
3334 int tempNoChanges = 0;
3335 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
3336 noChanges += tempNoChanges;
3337 if (success)
3338 {
3339 succeeded.Append(child);
3340 }
3341 }
3342 }
3343 }
3344 node = node->Next();
3345 }
3346 noIterations ++;
3347 }
3348 return TRUE;
3349 }
3350
3351 void wxWindow::ResetConstraints()
3352 {
3353 wxLayoutConstraints *constr = GetConstraints();
3354 if (constr)
3355 {
3356 constr->left.SetDone(FALSE);
3357 constr->top.SetDone(FALSE);
3358 constr->right.SetDone(FALSE);
3359 constr->bottom.SetDone(FALSE);
3360 constr->width.SetDone(FALSE);
3361 constr->height.SetDone(FALSE);
3362 constr->centreX.SetDone(FALSE);
3363 constr->centreY.SetDone(FALSE);
3364 }
3365 wxNode *node = m_children.First();
3366 while (node)
3367 {
3368 wxWindow *win = (wxWindow *)node->Data();
3369 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3370 win->ResetConstraints();
3371 node = node->Next();
3372 }
3373 }
3374
3375 // Need to distinguish between setting the 'fake' size for
3376 // windows and sizers, and setting the real values.
3377 void wxWindow::SetConstraintSizes(bool recurse)
3378 {
3379 wxLayoutConstraints *constr = GetConstraints();
3380 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
3381 constr->width.GetDone() && constr->height.GetDone())
3382 {
3383 int x = constr->left.GetValue();
3384 int y = constr->top.GetValue();
3385 int w = constr->width.GetValue();
3386 int h = constr->height.GetValue();
3387
3388 // If we don't want to resize this window, just move it...
3389 if ((constr->width.GetRelationship() != wxAsIs) ||
3390 (constr->height.GetRelationship() != wxAsIs))
3391 {
3392 // Calls Layout() recursively. AAAGH. How can we stop that.
3393 // Simply take Layout() out of non-top level OnSizes.
3394 SizerSetSize(x, y, w, h);
3395 }
3396 else
3397 {
3398 SizerMove(x, y);
3399 }
3400 }
3401 else if (constr)
3402 {
3403 char *windowClass = this->GetClassInfo()->GetClassName();
3404
3405 wxString winName;
3406 if (GetName() == "")
3407 winName = "unnamed";
3408 else
3409 winName = GetName();
3410 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3411 (const char *)windowClass,
3412 (const char *)winName);
3413 if (!constr->left.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3414 if (!constr->right.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3415 if (!constr->width.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3416 if (!constr->height.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3417 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3418 }
3419
3420 if (recurse)
3421 {
3422 wxNode *node = m_children.First();
3423 while (node)
3424 {
3425 wxWindow *win = (wxWindow *)node->Data();
3426 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
3427 win->SetConstraintSizes();
3428 node = node->Next();
3429 }
3430 }
3431 }
3432
3433 // This assumes that all sizers are 'on' the same
3434 // window, i.e. the parent of this window.
3435 void wxWindow::TransformSizerToActual(int *x, int *y) const
3436 {
3437 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
3438 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
3439 return;
3440
3441 int xp, yp;
3442 m_sizerParent->GetPosition(&xp, &yp);
3443 m_sizerParent->TransformSizerToActual(&xp, &yp);
3444 *x += xp;
3445 *y += yp;
3446 }
3447
3448 void wxWindow::SizerSetSize(int x, int y, int w, int h)
3449 {
3450 int xx = x;
3451 int yy = y;
3452 TransformSizerToActual(&xx, &yy);
3453 SetSize(xx, yy, w, h);
3454 }
3455
3456 void wxWindow::SizerMove(int x, int y)
3457 {
3458 int xx = x;
3459 int yy = y;
3460 TransformSizerToActual(&xx, &yy);
3461 Move(xx, yy);
3462 }
3463
3464 // Only set the size/position of the constraint (if any)
3465 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
3466 {
3467 wxLayoutConstraints *constr = GetConstraints();
3468 if (constr)
3469 {
3470 if (x != -1)
3471 {
3472 constr->left.SetValue(x);
3473 constr->left.SetDone(TRUE);
3474 }
3475 if (y != -1)
3476 {
3477 constr->top.SetValue(y);
3478 constr->top.SetDone(TRUE);
3479 }
3480 if (w != -1)
3481 {
3482 constr->width.SetValue(w);
3483 constr->width.SetDone(TRUE);
3484 }
3485 if (h != -1)
3486 {
3487 constr->height.SetValue(h);
3488 constr->height.SetDone(TRUE);
3489 }
3490 }
3491 }
3492
3493 void wxWindow::MoveConstraint(int x, int y)
3494 {
3495 wxLayoutConstraints *constr = GetConstraints();
3496 if (constr)
3497 {
3498 if (x != -1)
3499 {
3500 constr->left.SetValue(x);
3501 constr->left.SetDone(TRUE);
3502 }
3503 if (y != -1)
3504 {
3505 constr->top.SetValue(y);
3506 constr->top.SetDone(TRUE);
3507 }
3508 }
3509 }
3510
3511 void wxWindow::GetSizeConstraint(int *w, int *h) const
3512 {
3513 wxLayoutConstraints *constr = GetConstraints();
3514 if (constr)
3515 {
3516 *w = constr->width.GetValue();
3517 *h = constr->height.GetValue();
3518 }
3519 else
3520 GetSize(w, h);
3521 }
3522
3523 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3524 {
3525 wxLayoutConstraints *constr = GetConstraints();
3526 if (constr)
3527 {
3528 *w = constr->width.GetValue();
3529 *h = constr->height.GetValue();
3530 }
3531 else
3532 GetClientSize(w, h);
3533 }
3534
3535 void wxWindow::GetPositionConstraint(int *x, int *y) const
3536 {
3537 wxLayoutConstraints *constr = GetConstraints();
3538 if (constr)
3539 {
3540 *x = constr->left.GetValue();
3541 *y = constr->top.GetValue();
3542 }
3543 else
3544 GetPosition(x, y);
3545 }
3546