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