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