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