]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/window.cpp
Font fixes and icons in report view for list control
[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 win->GetDropTarget()->m_size = event->data_numbytes;
854 win->GetDropTarget()->Drop( event, x, y );
855 }
856
857 /*
858 g_free (event->dropdataavailable.data);
859 g_free (event->dropdataavailable.data_type);
860 */
861 }
862
863 //-----------------------------------------------------------------------------
864 // wxWindow
865 //-----------------------------------------------------------------------------
866
867 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
868
869 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
870 EVT_SIZE(wxWindow::OnSize)
871 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
872 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
873 EVT_IDLE(wxWindow::OnIdle)
874 END_EVENT_TABLE()
875
876 wxWindow::wxWindow()
877 {
878 m_widget = (GtkWidget *) NULL;
879 m_wxwindow = (GtkWidget *) NULL;
880 m_parent = (wxWindow *) NULL;
881 m_children.DeleteContents( FALSE );
882 m_x = 0;
883 m_y = 0;
884 m_width = 0;
885 m_height = 0;
886 m_minWidth = -1;
887 m_minHeight = -1;
888 m_maxWidth = -1;
889 m_maxHeight = -1;
890 m_retCode = 0;
891 m_eventHandler = this;
892 m_windowValidator = (wxValidator *) NULL;
893 m_windowId = -1;
894 m_cursor = (wxCursor *) NULL;
895 m_font = *wxSWISS_FONT;
896 m_windowStyle = 0;
897 m_windowName = "noname";
898 m_constraints = (wxLayoutConstraints *) NULL;
899 m_constraintsInvolvedIn = (wxList *) NULL;
900 m_windowSizer = (wxSizer *) NULL;
901 m_sizerParent = (wxWindow *) NULL;
902 m_autoLayout = FALSE;
903 m_sizeSet = FALSE;
904 m_hasVMT = FALSE;
905 m_needParent = TRUE;
906 m_hasScrolling = FALSE;
907 m_isScrolling = FALSE;
908 m_hAdjust = (GtkAdjustment *) NULL;
909 m_vAdjust = (GtkAdjustment *) NULL;
910 m_oldHorizontalPos = 0.0;
911 m_oldVerticalPos = 0.0;
912 m_isShown = FALSE;
913 m_isEnabled = TRUE;
914 m_pDropTarget = (wxDropTarget *) NULL;
915 m_resizing = FALSE;
916 m_scrollGC = (GdkGC*) NULL;
917 m_widgetStyle = (GtkStyle*) NULL;
918 }
919
920 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
921 const wxPoint &pos, const wxSize &size,
922 long style, const wxString &name )
923 {
924 m_isShown = FALSE;
925 m_isEnabled = TRUE;
926 m_needParent = TRUE;
927
928 m_cursor = (wxCursor *) NULL;
929
930 PreCreation( parent, id, pos, size, style, name );
931
932 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
933 m_hasScrolling = TRUE;
934
935 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
936
937 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
938 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
939
940 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
941 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
942
943 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
944 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
945
946 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
947 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
948
949 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
950 scroll_class->scrollbar_spacing = 0;
951
952 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
953
954 m_oldHorizontalPos = 0.0;
955 m_oldVerticalPos = 0.0;
956
957 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
958 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
959
960 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
961 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
962 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
963 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
964
965 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
966 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
967 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
968 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
969
970 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
971
972 if (m_windowStyle & wxRAISED_BORDER)
973 {
974 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
975 }
976 else if (m_windowStyle & wxSUNKEN_BORDER)
977 {
978 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
979 }
980 else
981 {
982 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
983 }
984
985 m_wxwindow = gtk_myfixed_new();
986
987 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
988
989 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
990 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
991 else
992 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
993
994 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
995
996 // shut the viewport up
997 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
998 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
999
1000 // I _really_ don't want scrollbars in the beginning
1001 m_vAdjust->lower = 0.0;
1002 m_vAdjust->upper = 1.0;
1003 m_vAdjust->value = 0.0;
1004 m_vAdjust->step_increment = 1.0;
1005 m_vAdjust->page_increment = 1.0;
1006 m_vAdjust->page_size = 5.0;
1007 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1008 m_hAdjust->lower = 0.0;
1009 m_hAdjust->upper = 1.0;
1010 m_hAdjust->value = 0.0;
1011 m_hAdjust->step_increment = 1.0;
1012 m_hAdjust->page_increment = 1.0;
1013 m_hAdjust->page_size = 5.0;
1014 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1015
1016 gtk_widget_show( m_wxwindow );
1017
1018 PostCreation();
1019
1020 Show( TRUE );
1021
1022 return TRUE;
1023 }
1024
1025 wxWindow::~wxWindow()
1026 {
1027 m_hasVMT = FALSE;
1028
1029 if (m_pDropTarget) delete m_pDropTarget;
1030
1031 if (m_parent) m_parent->RemoveChild( this );
1032 if (m_widget) Show( FALSE );
1033
1034 DestroyChildren();
1035
1036 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1037
1038 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1039
1040 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1041
1042 if (m_widget) gtk_widget_destroy( m_widget );
1043
1044 wxDELETE(m_cursor);
1045
1046 DeleteRelatedConstraints();
1047 if (m_constraints)
1048 {
1049 // This removes any dangling pointers to this window
1050 // in other windows' constraintsInvolvedIn lists.
1051 UnsetConstraints(m_constraints);
1052 delete m_constraints;
1053 m_constraints = (wxLayoutConstraints *) NULL;
1054 }
1055 if (m_windowSizer)
1056 {
1057 delete m_windowSizer;
1058 m_windowSizer = (wxSizer *) NULL;
1059 }
1060 // If this is a child of a sizer, remove self from parent
1061 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1062
1063 // Just in case the window has been Closed, but
1064 // we're then deleting immediately: don't leave
1065 // dangling pointers.
1066 wxPendingDelete.DeleteObject(this);
1067
1068 // Just in case we've loaded a top-level window via
1069 // wxWindow::LoadNativeDialog but we weren't a dialog
1070 // class
1071 wxTopLevelWindows.DeleteObject(this);
1072
1073 if (m_windowValidator) delete m_windowValidator;
1074 }
1075
1076 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1077 const wxPoint &pos, const wxSize &size,
1078 long style, const wxString &name )
1079 {
1080 if (m_needParent && (parent == NULL))
1081 wxFatalError( "Need complete parent.", name );
1082
1083 m_widget = (GtkWidget *) NULL;
1084 m_hasVMT = FALSE;
1085 m_parent = parent;
1086 m_children.DeleteContents( FALSE );
1087 m_x = (int)pos.x;
1088 m_y = (int)pos.y;
1089 m_width = size.x;
1090 if (m_width == -1) m_width = 20;
1091 m_height = size.y;
1092 if (m_height == -1) m_height = 20;
1093 m_minWidth = -1;
1094 m_minHeight = -1;
1095 m_maxWidth = -1;
1096 m_maxHeight = -1;
1097 m_retCode = 0;
1098 m_eventHandler = this;
1099 m_windowId = id;
1100 m_sizeSet = FALSE;
1101 if (m_cursor == NULL)
1102 m_cursor = new wxCursor( wxCURSOR_ARROW );
1103 m_font = *wxSWISS_FONT;
1104 // m_backgroundColour = wxWHITE;
1105 // m_foregroundColour = wxBLACK;
1106 m_windowStyle = style;
1107 m_windowName = name;
1108 m_constraints = (wxLayoutConstraints *) NULL;
1109 m_constraintsInvolvedIn = (wxList *) NULL;
1110 m_windowSizer = (wxSizer *) NULL;
1111 m_sizerParent = (wxWindow *) NULL;
1112 m_autoLayout = FALSE;
1113 m_hasScrolling = FALSE;
1114 m_isScrolling = FALSE;
1115 m_pDropTarget = (wxDropTarget *) NULL;
1116 m_resizing = FALSE;
1117 m_windowValidator = (wxValidator *) NULL;
1118 m_scrollGC = (GdkGC*) NULL;
1119 m_widgetStyle = (GtkStyle*) NULL;
1120 }
1121
1122 void wxWindow::PostCreation()
1123 {
1124 if (m_parent) m_parent->AddChild( this );
1125
1126 if (m_wxwindow)
1127 {
1128 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1129 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1130
1131 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1132 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1133 }
1134
1135 ConnectWidget( GetConnectWidget() );
1136
1137 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1138
1139 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1140
1141 SetCursor( *wxSTANDARD_CURSOR );
1142
1143 m_hasVMT = TRUE;
1144 }
1145
1146 void wxWindow::ConnectWidget( GtkWidget *widget )
1147 {
1148 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1149 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1150
1151 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1152 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1153
1154 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1155 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1156
1157 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1158 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1159
1160 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1161 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1162
1163 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1164 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1165
1166 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1167 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1168
1169 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1170 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1171 }
1172
1173 bool wxWindow::HasVMT()
1174 {
1175 return m_hasVMT;
1176 }
1177
1178 bool wxWindow::Close( bool force )
1179 {
1180 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1181
1182 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1183 event.SetEventObject(this);
1184 event.SetForce(force);
1185
1186 return GetEventHandler()->ProcessEvent(event);
1187 }
1188
1189 bool wxWindow::Destroy()
1190 {
1191 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1192
1193 m_hasVMT = FALSE;
1194 delete this;
1195 return TRUE;
1196 }
1197
1198 bool wxWindow::DestroyChildren()
1199 {
1200 if (GetChildren())
1201 {
1202 wxNode *node;
1203 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1204 {
1205 wxWindow *child;
1206 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1207 {
1208 delete child;
1209 if (GetChildren()->Member(child)) delete node;
1210 }
1211 }
1212 }
1213 return TRUE;
1214 }
1215
1216 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1217 {
1218 // are we to set fonts here ?
1219 }
1220
1221 void wxWindow::ImplementSetSize()
1222 {
1223 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1224 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1225 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1226 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1227 gtk_widget_set_usize( m_widget, m_width, m_height );
1228 }
1229
1230 void wxWindow::ImplementSetPosition()
1231 {
1232 if (IS_KIND_OF(this,wxFrame) || IS_KIND_OF(this,wxDialog))
1233 {
1234 if ((m_x != -1) || (m_y != -1))
1235 gtk_widget_set_uposition( m_widget, m_x, m_y );
1236 return;
1237 }
1238
1239 if (!m_parent)
1240 {
1241 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1242 return;
1243 }
1244
1245 if ((m_parent) && (m_parent->m_wxwindow))
1246 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1247
1248 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1249 }
1250
1251 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1252 {
1253 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1254
1255 if (m_resizing) return; // I don't like recursions
1256 m_resizing = TRUE;
1257
1258 int newX = x;
1259 int newY = y;
1260 int newW = width;
1261 int newH = height;
1262
1263 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1264 {
1265 if (newX == -1) newX = m_x;
1266 if (newY == -1) newY = m_y;
1267 if (newW == -1) newW = m_width;
1268 if (newH == -1) newH = m_height;
1269 }
1270
1271 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1272 {
1273 if (newW == -1) newW = 80;
1274 }
1275
1276 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1277 {
1278 if (newH == -1) newH = 26;
1279 }
1280
1281 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1282 {
1283 m_x = newX;
1284 m_y = newY;
1285 ImplementSetPosition();
1286 }
1287 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1288 {
1289 m_width = newW;
1290 m_height = newH;
1291 ImplementSetSize();
1292 }
1293 m_sizeSet = TRUE;
1294
1295 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1296 event.SetEventObject( this );
1297 ProcessEvent( event );
1298
1299 m_resizing = FALSE;
1300 }
1301
1302 void wxWindow::SetSize( int width, int height )
1303 {
1304 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1305 }
1306
1307 void wxWindow::Move( int x, int y )
1308 {
1309 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1310 }
1311
1312 void wxWindow::GetSize( int *width, int *height ) const
1313 {
1314 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1315
1316 if (width) (*width) = m_width;
1317 if (height) (*height) = m_height;
1318 }
1319
1320 void wxWindow::SetClientSize( int width, int height )
1321 {
1322 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1323
1324 if (!m_wxwindow)
1325 {
1326 SetSize( width, height );
1327 }
1328 else
1329 {
1330 int dw = 0;
1331 int dh = 0;
1332
1333 if (!m_hasScrolling)
1334 {
1335 /*
1336 do we have sunken dialogs ?
1337
1338 GtkStyleClass *window_class = m_wxwindow->style->klass;
1339
1340 dw += 2 * window_class->xthickness;
1341 dh += 2 * window_class->ythickness;
1342 */
1343 }
1344 else
1345 {
1346 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1347 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1348
1349 GtkWidget *viewport = scroll_window->viewport;
1350 GtkStyleClass *viewport_class = viewport->style->klass;
1351
1352 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1353 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1354
1355 if ((m_windowStyle & wxRAISED_BORDER) ||
1356 (m_windowStyle & wxSUNKEN_BORDER))
1357 {
1358 dw += 2 * viewport_class->xthickness;
1359 dh += 2 * viewport_class->ythickness;
1360 }
1361
1362 if (GTK_WIDGET_VISIBLE(vscrollbar))
1363 {
1364 dw += vscrollbar->allocation.width;
1365 dw += scroll_class->scrollbar_spacing;
1366 }
1367
1368 if (GTK_WIDGET_VISIBLE(hscrollbar))
1369 {
1370 dh += hscrollbar->allocation.height;
1371 dw += scroll_class->scrollbar_spacing;
1372 }
1373 }
1374
1375 SetSize( width+dw, height+dh );
1376 }
1377 }
1378
1379 void wxWindow::GetClientSize( int *width, int *height ) const
1380 {
1381 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1382
1383 if (!m_wxwindow)
1384 {
1385 if (width) (*width) = m_width;
1386 if (height) (*height) = m_height;
1387 }
1388 else
1389 {
1390 int dw = 0;
1391 int dh = 0;
1392
1393 if (!m_hasScrolling)
1394 {
1395 /*
1396 do we have sunken dialogs ?
1397
1398 GtkStyleClass *window_class = m_wxwindow->style->klass;
1399
1400 dw += 2 * window_class->xthickness;
1401 dh += 2 * window_class->ythickness;
1402 */
1403 }
1404 else
1405 {
1406 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1407 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1408
1409 GtkWidget *viewport = scroll_window->viewport;
1410 GtkStyleClass *viewport_class = viewport->style->klass;
1411
1412 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1413 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1414
1415 if ((m_windowStyle & wxRAISED_BORDER) ||
1416 (m_windowStyle & wxSUNKEN_BORDER))
1417 {
1418 dw += 2 * viewport_class->xthickness;
1419 dh += 2 * viewport_class->ythickness;
1420 }
1421
1422 if (GTK_WIDGET_VISIBLE(vscrollbar))
1423 {
1424 // dw += vscrollbar->allocation.width;
1425 dw += 15; // range.slider_width = 11 + 2*2pts edge
1426 dw += scroll_class->scrollbar_spacing;
1427 }
1428
1429 if (GTK_WIDGET_VISIBLE(hscrollbar))
1430 {
1431 // dh += hscrollbar->allocation.height;
1432 dh += 15;
1433 dh += scroll_class->scrollbar_spacing;
1434 }
1435 }
1436
1437 if (width) (*width) = m_width - dw;
1438 if (height) (*height) = m_height - dh;
1439 }
1440 }
1441
1442 void wxWindow::GetPosition( int *x, int *y ) const
1443 {
1444 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1445
1446 if (x) (*x) = m_x;
1447 if (y) (*y) = m_y;
1448 }
1449
1450 void wxWindow::ClientToScreen( int *x, int *y )
1451 {
1452 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1453
1454 GdkWindow *source = (GdkWindow *) NULL;
1455 if (m_wxwindow)
1456 source = m_wxwindow->window;
1457 else
1458 source = m_widget->window;
1459
1460 int org_x = 0;
1461 int org_y = 0;
1462 gdk_window_get_origin( source, &org_x, &org_y );
1463
1464 if (!m_wxwindow)
1465 {
1466 if (GTK_WIDGET_NO_WINDOW (m_widget))
1467 {
1468 org_x += m_widget->allocation.x;
1469 org_y += m_widget->allocation.y;
1470 }
1471 }
1472
1473 if (x) *x += org_x;
1474 if (y) *y += org_y;
1475 }
1476
1477 void wxWindow::ScreenToClient( int *x, int *y )
1478 {
1479 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1480
1481 GdkWindow *source = (GdkWindow *) NULL;
1482 if (m_wxwindow)
1483 source = m_wxwindow->window;
1484 else
1485 source = m_widget->window;
1486
1487 int org_x = 0;
1488 int org_y = 0;
1489 gdk_window_get_origin( source, &org_x, &org_y );
1490
1491 if (!m_wxwindow)
1492 {
1493 if (GTK_WIDGET_NO_WINDOW (m_widget))
1494 {
1495 org_x += m_widget->allocation.x;
1496 org_y += m_widget->allocation.y;
1497 }
1498 }
1499
1500 if (x) *x -= org_x;
1501 if (y) *y -= org_y;
1502 }
1503
1504 void wxWindow::Centre( int direction )
1505 {
1506 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1507
1508 if (IS_KIND_OF(this,wxDialog) || IS_KIND_OF(this,wxFrame))
1509 {
1510 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
1511 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
1512 ImplementSetPosition();
1513 }
1514 else
1515 {
1516 if (m_parent)
1517 {
1518 int p_w = 0;
1519 int p_h = 0;
1520 m_parent->GetSize( &p_w, &p_h );
1521 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (p_w - m_width) / 2;
1522 if (direction & wxVERTICAL == wxVERTICAL) m_y = (p_h - m_height) / 2;
1523 ImplementSetPosition();
1524 }
1525 }
1526 }
1527
1528 void wxWindow::Fit()
1529 {
1530 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1531
1532 int maxX = 0;
1533 int maxY = 0;
1534 wxNode *node = GetChildren()->First();
1535 while ( node )
1536 {
1537 wxWindow *win = (wxWindow *)node->Data();
1538 int wx, wy, ww, wh;
1539 win->GetPosition(&wx, &wy);
1540 win->GetSize(&ww, &wh);
1541 if ( wx + ww > maxX )
1542 maxX = wx + ww;
1543 if ( wy + wh > maxY )
1544 maxY = wy + wh;
1545
1546 node = node->Next();
1547 }
1548 SetClientSize(maxX + 5, maxY + 10);
1549 }
1550
1551 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1552 {
1553 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1554
1555 m_minWidth = minW;
1556 m_minHeight = minH;
1557 m_maxWidth = maxW;
1558 m_maxHeight = maxH;
1559 }
1560
1561 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1562 {
1563 //if (GetAutoLayout()) Layout();
1564 }
1565
1566 bool wxWindow::Show( bool show )
1567 {
1568 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1569
1570 if (show)
1571 gtk_widget_show( m_widget );
1572 else
1573 gtk_widget_hide( m_widget );
1574 m_isShown = show;
1575 return TRUE;
1576 }
1577
1578 void wxWindow::Enable( bool enable )
1579 {
1580 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1581
1582 m_isEnabled = enable;
1583 gtk_widget_set_sensitive( m_widget, enable );
1584 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1585 }
1586
1587 int wxWindow::GetCharHeight() const
1588 {
1589 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1590
1591 if (!m_font.Ok())
1592 {
1593 wxFAIL_MSG( "invalid font" );
1594 return -1;
1595 }
1596
1597 GdkFont *font = m_font.GetInternalFont( 1.0 );
1598 return font->ascent + font->descent;
1599 }
1600
1601 int wxWindow::GetCharWidth() const
1602 {
1603 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1604
1605 if (!m_font.Ok())
1606 {
1607 wxFAIL_MSG( "invalid font" );
1608 return -1;
1609 }
1610
1611 GdkFont *font = m_font.GetInternalFont( 1.0 );
1612 return gdk_string_width( font, "H" );
1613 }
1614
1615 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1616 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1617 {
1618 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1619
1620 wxFont fontToUse = m_font;
1621 if (theFont) fontToUse = *theFont;
1622
1623 if (!fontToUse.Ok())
1624 {
1625 wxFAIL_MSG( "invalid font" );
1626 return;
1627 }
1628 wxASSERT_MSG( (m_font.Ok()), "invalid font" );
1629
1630 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1631 if (x) (*x) = gdk_string_width( font, string );
1632 if (y) (*y) = font->ascent + font->descent;
1633 if (descent) (*descent) = font->descent;
1634 if (externalLeading) (*externalLeading) = 0; // ??
1635 }
1636
1637 void wxWindow::MakeModal( bool modal )
1638 {
1639 return;
1640 // Disable all other windows
1641 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1642 {
1643 wxNode *node = wxTopLevelWindows.First();
1644 while (node)
1645 {
1646 wxWindow *win = (wxWindow *)node->Data();
1647 if (win != this)
1648 win->Enable(!modal);
1649
1650 node = node->Next();
1651 }
1652 }
1653 }
1654
1655 void wxWindow::SetFocus()
1656 {
1657 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1658
1659 GtkWidget *connect_widget = GetConnectWidget();
1660 if (connect_widget)
1661 {
1662 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1663 {
1664 gtk_widget_grab_focus (connect_widget);
1665 }
1666 }
1667 }
1668
1669 bool wxWindow::OnClose()
1670 {
1671 return TRUE;
1672 }
1673
1674 void wxWindow::AddChild( wxWindow *child )
1675 {
1676 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1677 wxASSERT_MSG( (m_wxwindow != NULL), "window need client area" );
1678 wxASSERT_MSG( (child != NULL), "invalid child" );
1679 wxASSERT_MSG( (child->m_widget != NULL), "invalid child" );
1680
1681 // Addchild is (often) called before the program
1682 // has left the parents constructor so that no
1683 // virtual tables work yet. The approach below
1684 // practically imitates virtual tables, i.e. it
1685 // implements a different AddChild() behaviour
1686 // for wxFrame, wxDialog, wxWindow and
1687 // wxMDIParentFrame.
1688
1689 // wxFrame and wxDialog as children aren't placed into the parents
1690
1691 if (( IS_KIND_OF(child,wxFrame) || IS_KIND_OF(child,wxDialog) ) &&
1692 (!IS_KIND_OF(child,wxMDIChildFrame)))
1693 {
1694 m_children.Append( child );
1695
1696 if ((child->m_x != -1) && (child->m_y != -1))
1697 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1698
1699 return;
1700 }
1701
1702 // In the case of an wxMDIChildFrame descendant, we use the
1703 // client windows's AddChild()
1704
1705 if (IS_KIND_OF(this,wxMDIParentFrame))
1706 {
1707 if (IS_KIND_OF(child,wxMDIChildFrame))
1708 {
1709 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1710 if (client)
1711 {
1712 client->AddChild( child );
1713 return;
1714 }
1715 }
1716 }
1717
1718 // wxNotebook is very special, so it has a private AddChild()
1719
1720 if (IS_KIND_OF(this,wxNotebook))
1721 {
1722 wxNotebook *tab = (wxNotebook*)this;
1723 tab->AddChild( child );
1724 return;
1725 }
1726
1727 // wxFrame has a private AddChild
1728
1729 if (IS_KIND_OF(this,wxFrame) && !IS_KIND_OF(this,wxMDIChildFrame))
1730 {
1731 wxFrame *frame = (wxFrame*)this;
1732 frame->AddChild( child );
1733 return;
1734 }
1735
1736 // All the rest
1737
1738 m_children.Append( child );
1739 if (m_wxwindow) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget,
1740 child->m_x, child->m_y );
1741
1742 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
1743 }
1744
1745 wxList *wxWindow::GetChildren()
1746 {
1747 return (&m_children);
1748 }
1749
1750 void wxWindow::RemoveChild( wxWindow *child )
1751 {
1752 if (GetChildren())
1753 GetChildren()->DeleteObject( child );
1754 child->m_parent = (wxWindow *) NULL;
1755 }
1756
1757 void wxWindow::SetReturnCode( int retCode )
1758 {
1759 m_retCode = retCode;
1760 }
1761
1762 int wxWindow::GetReturnCode()
1763 {
1764 return m_retCode;
1765 }
1766
1767 void wxWindow::Raise()
1768 {
1769 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1770
1771 if (m_widget) gdk_window_raise( m_widget->window );
1772 }
1773
1774 void wxWindow::Lower()
1775 {
1776 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1777
1778 if (m_widget) gdk_window_lower( m_widget->window );
1779 }
1780
1781 wxEvtHandler *wxWindow::GetEventHandler()
1782 {
1783 return m_eventHandler;
1784 }
1785
1786 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1787 {
1788 m_eventHandler = handler;
1789 }
1790
1791 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1792 {
1793 handler->SetNextHandler(GetEventHandler());
1794 SetEventHandler(handler);
1795 }
1796
1797 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1798 {
1799 if (GetEventHandler())
1800 {
1801 wxEvtHandler *handlerA = GetEventHandler();
1802 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1803 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1804 SetEventHandler(handlerB);
1805 if (deleteHandler)
1806 {
1807 delete handlerA;
1808 return (wxEvtHandler*) NULL;
1809 }
1810 else
1811 return handlerA;
1812 }
1813 else
1814 return (wxEvtHandler *) NULL;
1815 }
1816
1817 wxValidator *wxWindow::GetValidator()
1818 {
1819 return m_windowValidator;
1820 }
1821
1822 void wxWindow::SetValidator( const wxValidator& validator )
1823 {
1824 if (m_windowValidator) delete m_windowValidator;
1825 m_windowValidator = validator.Clone();
1826 if (m_windowValidator) m_windowValidator->SetWindow(this);
1827 }
1828
1829 bool wxWindow::IsBeingDeleted()
1830 {
1831 return FALSE;
1832 }
1833
1834 void wxWindow::SetId( wxWindowID id )
1835 {
1836 m_windowId = id;
1837 }
1838
1839 wxWindowID wxWindow::GetId()
1840 {
1841 return m_windowId;
1842 }
1843
1844 void wxWindow::SetCursor( const wxCursor &cursor )
1845 {
1846 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1847
1848 if (m_cursor == NULL)
1849 {
1850 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1851 m_cursor = new wxCursor( wxCURSOR_ARROW );
1852 }
1853
1854 if (cursor.Ok())
1855 {
1856 if (*((wxCursor*)&cursor) == m_cursor) return;
1857 *m_cursor = cursor;
1858 }
1859 else
1860 {
1861 *m_cursor = *wxSTANDARD_CURSOR;
1862 }
1863
1864 if ((m_widget) && (m_widget->window))
1865 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1866
1867 if ((m_wxwindow) && (m_wxwindow->window))
1868 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1869 }
1870
1871 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1872 {
1873 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1874
1875 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1876 {
1877 if (rect)
1878 gdk_window_clear_area( m_wxwindow->window,
1879 rect->x,
1880 rect->y,
1881 rect->width,
1882 rect->height );
1883 else
1884 Clear();
1885 }
1886 if (!rect)
1887 {
1888 if (m_wxwindow)
1889 {
1890 int w = 0;
1891 int h = 0;
1892 GetClientSize( &w, &h );
1893
1894 GdkRectangle gdk_rect;
1895 gdk_rect.x = 0;
1896 gdk_rect.y = 0;
1897 gdk_rect.width = w;
1898 gdk_rect.height = h;
1899 gtk_widget_draw( m_wxwindow, &gdk_rect );
1900 }
1901 }
1902 else
1903 {
1904 GdkRectangle gdk_rect;
1905 gdk_rect.x = rect->x;
1906 gdk_rect.y = rect->y;
1907 gdk_rect.width = rect->width;
1908 gdk_rect.height = rect->height;
1909
1910 if (m_wxwindow)
1911 gtk_widget_draw( m_wxwindow, &gdk_rect );
1912 else
1913 gtk_widget_draw( m_widget, &gdk_rect );
1914 }
1915 }
1916
1917 wxRegion wxWindow::GetUpdateRegion() const
1918 {
1919 return m_updateRegion;
1920 }
1921
1922 bool wxWindow::IsExposed( int x, int y) const
1923 {
1924 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1925 }
1926
1927 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
1928 {
1929 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
1930 }
1931
1932 bool wxWindow::IsExposed( const wxPoint& pt ) const
1933 {
1934 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
1935 }
1936
1937 bool wxWindow::IsExposed( const wxRect& rect ) const
1938 {
1939 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
1940 }
1941
1942 void wxWindow::Clear()
1943 {
1944 wxCHECK_RET( m_widget != NULL, "invalid window" );
1945
1946 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
1947 }
1948
1949 wxColour wxWindow::GetBackgroundColour() const
1950 {
1951 return m_backgroundColour;
1952 }
1953
1954 void wxWindow::SetBackgroundColour( const wxColour &colour )
1955 {
1956 wxCHECK_RET( m_widget != NULL, "invalid window" );
1957
1958 m_backgroundColour = colour;
1959 if (!m_backgroundColour.Ok()) return;
1960
1961 if (m_wxwindow)
1962 {
1963 GdkWindow *window = m_wxwindow->window;
1964 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
1965 gdk_window_set_background( window, m_backgroundColour.GetColor() );
1966 gdk_window_clear( window );
1967 }
1968
1969 ApplyWidgetStyle();
1970 }
1971
1972 wxColour wxWindow::GetForegroundColour() const
1973 {
1974 return m_foregroundColour;
1975 }
1976
1977 void wxWindow::SetForegroundColour( const wxColour &colour )
1978 {
1979 wxCHECK_RET( m_widget != NULL, "invalid window" );
1980
1981 m_foregroundColour = colour;
1982 if (!m_foregroundColour.Ok()) return;
1983
1984 ApplyWidgetStyle();
1985 }
1986
1987 GtkStyle *wxWindow::GetWidgetStyle()
1988 {
1989 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1990
1991 m_widgetStyle =
1992 gtk_style_copy(
1993 gtk_widget_get_style( m_widget ) );
1994
1995 return m_widgetStyle;
1996 }
1997
1998 void wxWindow::SetWidgetStyle()
1999 {
2000 GtkStyle *style = GetWidgetStyle();
2001
2002 gdk_font_unref( style->font );
2003 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2004
2005 if (m_foregroundColour.Ok())
2006 {
2007 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2008 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2009 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2010 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2011 }
2012
2013 if (m_backgroundColour.Ok())
2014 {
2015 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2016 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2017 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2018 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2019 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2020 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2021 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2022 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2023 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2024 }
2025 }
2026
2027 void wxWindow::ApplyWidgetStyle()
2028 {
2029 }
2030
2031 bool wxWindow::Validate()
2032 {
2033 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2034
2035 wxNode *node = GetChildren()->First();
2036 while (node)
2037 {
2038 wxWindow *child = (wxWindow *)node->Data();
2039 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2040 { return FALSE; }
2041 node = node->Next();
2042 }
2043 return TRUE;
2044 }
2045
2046 bool wxWindow::TransferDataToWindow()
2047 {
2048 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2049
2050 wxNode *node = GetChildren()->First();
2051 while (node)
2052 {
2053 wxWindow *child = (wxWindow *)node->Data();
2054 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2055 !child->GetValidator()->TransferToWindow() )
2056 {
2057 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2058 return FALSE;
2059 }
2060 node = node->Next();
2061 }
2062 return TRUE;
2063 }
2064
2065 bool wxWindow::TransferDataFromWindow()
2066 {
2067 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2068
2069 wxNode *node = GetChildren()->First();
2070 while (node)
2071 {
2072 wxWindow *child = (wxWindow *)node->Data();
2073 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2074 { return FALSE; }
2075 node = node->Next();
2076 }
2077 return TRUE;
2078 }
2079
2080 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2081 {
2082 m_acceleratorTable = accel;
2083 }
2084
2085 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2086 {
2087 TransferDataToWindow();
2088 }
2089
2090 void wxWindow::InitDialog()
2091 {
2092 wxCHECK_RET( m_widget != NULL, "invalid window" );
2093
2094 wxInitDialogEvent event(GetId());
2095 event.SetEventObject( this );
2096 GetEventHandler()->ProcessEvent(event);
2097 }
2098
2099 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2100 {
2101 menu->SetInvokingWindow( win );
2102 wxNode *node = menu->m_items.First();
2103 while (node)
2104 {
2105 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2106 if (menuitem->IsSubMenu())
2107 SetInvokingWindow( menuitem->GetSubMenu(), win );
2108 node = node->Next();
2109 }
2110 }
2111
2112 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2113 {
2114 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2115
2116 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2117
2118 SetInvokingWindow( menu, this );
2119 gtk_menu_popup(
2120 GTK_MENU(menu->m_menu),
2121 (GtkWidget *)NULL, // parent menu shell
2122 (GtkWidget *)NULL, // parent menu item
2123 (GtkMenuPositionFunc)NULL,
2124 NULL, // client data
2125 0, // button used to activate it
2126 0//gs_timeLastClick // the time of activation
2127 );
2128 return TRUE;
2129 }
2130
2131 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2132 {
2133 wxCHECK_RET( m_widget != NULL, "invalid window" );
2134
2135 GtkWidget *dnd_widget = GetConnectWidget();
2136
2137 DisconnectDnDWidget( dnd_widget );
2138
2139 if (m_pDropTarget) delete m_pDropTarget;
2140 m_pDropTarget = dropTarget;
2141
2142 ConnectDnDWidget( dnd_widget );
2143 }
2144
2145 wxDropTarget *wxWindow::GetDropTarget() const
2146 {
2147 return m_pDropTarget;
2148 }
2149
2150 void wxWindow::ConnectDnDWidget( GtkWidget *widget )
2151 {
2152 if (!m_pDropTarget) return;
2153
2154 m_pDropTarget->RegisterWidget( widget );
2155
2156 gtk_signal_connect( GTK_OBJECT(widget), "drop_data_available_event",
2157 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2158 }
2159
2160 void wxWindow::DisconnectDnDWidget( GtkWidget *widget )
2161 {
2162 if (!m_pDropTarget) return;
2163
2164 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
2165 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2166
2167 m_pDropTarget->UnregisterWidget( widget );
2168 }
2169
2170 GtkWidget* wxWindow::GetConnectWidget()
2171 {
2172 GtkWidget *connect_widget = m_widget;
2173 if (m_wxwindow) connect_widget = m_wxwindow;
2174
2175 return connect_widget;
2176 }
2177
2178 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2179 {
2180 if (m_wxwindow) return (window == m_wxwindow->window);
2181 return (window == m_widget->window);
2182 }
2183
2184 void wxWindow::SetFont( const wxFont &font )
2185 {
2186 wxCHECK_RET( m_widget != NULL, "invalid window" );
2187
2188 if (((wxFont*)&font)->Ok())
2189 m_font = font;
2190 else
2191 m_font = *wxSWISS_FONT;
2192
2193 ApplyWidgetStyle();
2194 }
2195
2196 wxFont *wxWindow::GetFont()
2197 {
2198 return &m_font;
2199 }
2200
2201 void wxWindow::SetWindowStyleFlag( long flag )
2202 {
2203 m_windowStyle = flag;
2204 }
2205
2206 long wxWindow::GetWindowStyleFlag() const
2207 {
2208 return m_windowStyle;
2209 }
2210
2211 void wxWindow::CaptureMouse()
2212 {
2213 wxCHECK_RET( m_widget != NULL, "invalid window" );
2214
2215 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2216
2217 GtkWidget *connect_widget = GetConnectWidget();
2218 gtk_grab_add( connect_widget );
2219 gdk_pointer_grab ( connect_widget->window, FALSE,
2220 (GdkEventMask)
2221 (GDK_BUTTON_PRESS_MASK |
2222 GDK_BUTTON_RELEASE_MASK |
2223 GDK_POINTER_MOTION_MASK),
2224 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2225 g_capturing = TRUE;
2226 }
2227
2228 void wxWindow::ReleaseMouse()
2229 {
2230 wxCHECK_RET( m_widget != NULL, "invalid window" );
2231
2232 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2233
2234 GtkWidget *connect_widget = GetConnectWidget();
2235 gtk_grab_remove( connect_widget );
2236 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2237 g_capturing = FALSE;
2238 }
2239
2240 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2241 {
2242 }
2243
2244 wxString wxWindow::GetTitle() const
2245 {
2246 return (wxString&)m_windowName;
2247 }
2248
2249 wxString wxWindow::GetLabel() const
2250 {
2251 return GetTitle();
2252 }
2253
2254 void wxWindow::SetName( const wxString &name )
2255 {
2256 m_windowName = name;
2257 }
2258
2259 wxString wxWindow::GetName() const
2260 {
2261 return (wxString&)m_windowName;
2262 }
2263
2264 bool wxWindow::IsShown() const
2265 {
2266 return m_isShown;
2267 }
2268
2269 bool wxWindow::IsRetained()
2270 {
2271 return FALSE;
2272 }
2273
2274 wxWindow *wxWindow::FindWindow( long id )
2275 {
2276 if (id == m_windowId) return this;
2277 wxNode *node = m_children.First();
2278 while (node)
2279 {
2280 wxWindow *child = (wxWindow*)node->Data();
2281 wxWindow *res = child->FindWindow( id );
2282 if (res) return res;
2283 node = node->Next();
2284 }
2285 return (wxWindow *) NULL;
2286 }
2287
2288 wxWindow *wxWindow::FindWindow( const wxString& name )
2289 {
2290 if (name == m_windowName) return this;
2291 wxNode *node = m_children.First();
2292 while (node)
2293 {
2294 wxWindow *child = (wxWindow*)node->Data();
2295 wxWindow *res = child->FindWindow( name );
2296 if (res) return res;
2297 node = node->Next();
2298 }
2299 return (wxWindow *) NULL;
2300 }
2301
2302 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2303 int range, bool refresh )
2304 {
2305 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2306
2307 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2308
2309 if (!m_wxwindow) return;
2310
2311 if (orient == wxHORIZONTAL)
2312 {
2313 float fpos = (float)pos;
2314 float frange = (float)range;
2315 float fthumb = (float)thumbVisible;
2316
2317 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2318 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2319 {
2320 SetScrollPos( orient, pos, refresh );
2321 return;
2322 }
2323
2324 m_oldHorizontalPos = fpos;
2325
2326 m_hAdjust->lower = 0.0;
2327 m_hAdjust->upper = frange;
2328 m_hAdjust->value = fpos;
2329 m_hAdjust->step_increment = 1.0;
2330 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2331 m_hAdjust->page_size = fthumb;
2332 }
2333 else
2334 {
2335 float fpos = (float)pos;
2336 float frange = (float)range;
2337 float fthumb = (float)thumbVisible;
2338
2339 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2340 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2341 {
2342 SetScrollPos( orient, pos, refresh );
2343 return;
2344 }
2345
2346 m_oldVerticalPos = fpos;
2347
2348 m_vAdjust->lower = 0.0;
2349 m_vAdjust->upper = frange;
2350 m_vAdjust->value = fpos;
2351 m_vAdjust->step_increment = 1.0;
2352 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2353 m_vAdjust->page_size = fthumb;
2354 }
2355
2356 if (m_wxwindow->window)
2357 {
2358 if (orient == wxHORIZONTAL)
2359 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2360 else
2361 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2362
2363 gtk_widget_set_usize( m_widget, m_width, m_height );
2364 }
2365 }
2366
2367 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2368 {
2369 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2370
2371 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2372
2373 if (!m_wxwindow) return;
2374
2375 if (orient == wxHORIZONTAL)
2376 {
2377 float fpos = (float)pos;
2378 m_oldHorizontalPos = fpos;
2379
2380 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2381 m_hAdjust->value = fpos;
2382 }
2383 else
2384 {
2385 float fpos = (float)pos;
2386 m_oldVerticalPos = fpos;
2387 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2388 m_vAdjust->value = fpos;
2389 }
2390
2391 if (!m_isScrolling)
2392 {
2393 if (m_wxwindow->window)
2394 {
2395 if (orient == wxHORIZONTAL)
2396 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2397 else
2398 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2399 }
2400 }
2401 }
2402
2403 int wxWindow::GetScrollThumb( int orient ) const
2404 {
2405 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2406
2407 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2408
2409 if (!m_wxwindow) return 0;
2410
2411 if (orient == wxHORIZONTAL)
2412 return (int)(m_hAdjust->page_size+0.5);
2413 else
2414 return (int)(m_vAdjust->page_size+0.5);
2415 }
2416
2417 int wxWindow::GetScrollPos( int orient ) const
2418 {
2419 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2420
2421 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2422
2423 if (!m_wxwindow) return 0;
2424
2425 if (orient == wxHORIZONTAL)
2426 return (int)(m_hAdjust->value+0.5);
2427 else
2428 return (int)(m_vAdjust->value+0.5);
2429 }
2430
2431 int wxWindow::GetScrollRange( int orient ) const
2432 {
2433 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2434
2435 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2436
2437 if (!m_wxwindow) return 0;
2438
2439 if (orient == wxHORIZONTAL)
2440 return (int)(m_hAdjust->upper+0.5);
2441 else
2442 return (int)(m_vAdjust->upper+0.5);
2443 }
2444
2445 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2446 {
2447 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2448
2449 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2450
2451 if (!m_wxwindow) return;
2452
2453 int cw = 0;
2454 int ch = 0;
2455 GetClientSize( &cw, &ch );
2456
2457 int w = cw - abs(dx);
2458 int h = ch - abs(dy);
2459 if ((h < 0) || (w < 0))
2460 {
2461 Refresh();
2462 return;
2463 }
2464 int s_x = 0;
2465 int s_y = 0;
2466 if (dx < 0) s_x = -dx;
2467 if (dy < 0) s_y = -dy;
2468 int d_x = 0;
2469 int d_y = 0;
2470 if (dx > 0) d_x = dx;
2471 if (dy > 0) d_y = dy;
2472
2473 if (!m_scrollGC)
2474 {
2475 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2476 gdk_gc_set_exposures( m_scrollGC, TRUE );
2477 }
2478
2479 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2480 m_wxwindow->window, s_x, s_y, w, h );
2481
2482 wxRect rect;
2483 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2484 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2485 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2486 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2487
2488 Refresh( TRUE, &rect );
2489 }
2490
2491 //-------------------------------------------------------------------------------------
2492 // Layout
2493 //-------------------------------------------------------------------------------------
2494
2495 wxLayoutConstraints *wxWindow::GetConstraints() const
2496 {
2497 return m_constraints;
2498 }
2499
2500 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2501 {
2502 if (m_constraints)
2503 {
2504 UnsetConstraints(m_constraints);
2505 delete m_constraints;
2506 }
2507 m_constraints = constraints;
2508 if (m_constraints)
2509 {
2510 // Make sure other windows know they're part of a 'meaningful relationship'
2511 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2512 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2513 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2514 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2515 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2516 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2517 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2518 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2519 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2520 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2521 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2522 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2523 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2524 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2525 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2526 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2527 }
2528 ;
2529 }
2530 ;
2531
2532 void wxWindow::SetAutoLayout( bool autoLayout )
2533 {
2534 m_autoLayout = autoLayout;
2535 }
2536
2537 bool wxWindow::GetAutoLayout() const
2538 {
2539 return m_autoLayout;
2540 }
2541
2542 wxSizer *wxWindow::GetSizer() const
2543 {
2544 return m_windowSizer;
2545 }
2546
2547 void wxWindow::SetSizerParent( wxWindow *win )
2548 {
2549 m_sizerParent = win;
2550 }
2551
2552 wxWindow *wxWindow::GetSizerParent() const
2553 {
2554 return m_sizerParent;
2555 }
2556
2557 // This removes any dangling pointers to this window
2558 // in other windows' constraintsInvolvedIn lists.
2559 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2560 {
2561 if (c)
2562 {
2563 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2564 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2565 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2566 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2567 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2568 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2569 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2570 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2571 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2572 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2573 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2574 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2575 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2576 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2577 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2578 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2579 }
2580 }
2581
2582 // Back-pointer to other windows we're involved with, so if we delete
2583 // this window, we must delete any constraints we're involved with.
2584 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2585 {
2586 if (!m_constraintsInvolvedIn)
2587 m_constraintsInvolvedIn = new wxList;
2588 if (!m_constraintsInvolvedIn->Member(otherWin))
2589 m_constraintsInvolvedIn->Append(otherWin);
2590 }
2591
2592 // REMOVE back-pointer to other windows we're involved with.
2593 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2594 {
2595 if (m_constraintsInvolvedIn)
2596 m_constraintsInvolvedIn->DeleteObject(otherWin);
2597 }
2598
2599 // Reset any constraints that mention this window
2600 void wxWindow::DeleteRelatedConstraints()
2601 {
2602 if (m_constraintsInvolvedIn)
2603 {
2604 wxNode *node = m_constraintsInvolvedIn->First();
2605 while (node)
2606 {
2607 wxWindow *win = (wxWindow *)node->Data();
2608 wxNode *next = node->Next();
2609 wxLayoutConstraints *constr = win->GetConstraints();
2610
2611 // Reset any constraints involving this window
2612 if (constr)
2613 {
2614 constr->left.ResetIfWin((wxWindow *)this);
2615 constr->top.ResetIfWin((wxWindow *)this);
2616 constr->right.ResetIfWin((wxWindow *)this);
2617 constr->bottom.ResetIfWin((wxWindow *)this);
2618 constr->width.ResetIfWin((wxWindow *)this);
2619 constr->height.ResetIfWin((wxWindow *)this);
2620 constr->centreX.ResetIfWin((wxWindow *)this);
2621 constr->centreY.ResetIfWin((wxWindow *)this);
2622 }
2623 delete node;
2624 node = next;
2625 }
2626 delete m_constraintsInvolvedIn;
2627 m_constraintsInvolvedIn = (wxList *) NULL;
2628 }
2629 }
2630
2631 void wxWindow::SetSizer(wxSizer *sizer)
2632 {
2633 m_windowSizer = sizer;
2634 if (sizer)
2635 sizer->SetSizerParent((wxWindow *)this);
2636 }
2637
2638 /*
2639 * New version
2640 */
2641
2642 bool wxWindow::Layout()
2643 {
2644 if (GetConstraints())
2645 {
2646 int w, h;
2647 GetClientSize(&w, &h);
2648 GetConstraints()->width.SetValue(w);
2649 GetConstraints()->height.SetValue(h);
2650 }
2651
2652 // If top level (one sizer), evaluate the sizer's constraints.
2653 if (GetSizer())
2654 {
2655 int noChanges;
2656 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2657 GetSizer()->LayoutPhase1(&noChanges);
2658 GetSizer()->LayoutPhase2(&noChanges);
2659 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2660 return TRUE;
2661 }
2662 else
2663 {
2664 // Otherwise, evaluate child constraints
2665 ResetConstraints(); // Mark all constraints as unevaluated
2666 DoPhase(1); // Just one phase need if no sizers involved
2667 DoPhase(2);
2668 SetConstraintSizes(); // Recursively set the real window sizes
2669 }
2670 return TRUE;
2671 }
2672
2673
2674 // Do a phase of evaluating constraints:
2675 // the default behaviour. wxSizers may do a similar
2676 // thing, but also impose their own 'constraints'
2677 // and order the evaluation differently.
2678 bool wxWindow::LayoutPhase1(int *noChanges)
2679 {
2680 wxLayoutConstraints *constr = GetConstraints();
2681 if (constr)
2682 {
2683 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2684 }
2685 else
2686 return TRUE;
2687 }
2688
2689 bool wxWindow::LayoutPhase2(int *noChanges)
2690 {
2691 *noChanges = 0;
2692
2693 // Layout children
2694 DoPhase(1);
2695 DoPhase(2);
2696 return TRUE;
2697 }
2698
2699 // Do a phase of evaluating child constraints
2700 bool wxWindow::DoPhase(int phase)
2701 {
2702 int noIterations = 0;
2703 int maxIterations = 500;
2704 int noChanges = 1;
2705 int noFailures = 0;
2706 wxList succeeded;
2707 while ((noChanges > 0) && (noIterations < maxIterations))
2708 {
2709 noChanges = 0;
2710 noFailures = 0;
2711 wxNode *node = GetChildren()->First();
2712 while (node)
2713 {
2714 wxWindow *child = (wxWindow *)node->Data();
2715 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2716 {
2717 wxLayoutConstraints *constr = child->GetConstraints();
2718 if (constr)
2719 {
2720 if (succeeded.Member(child))
2721 {
2722 }
2723 else
2724 {
2725 int tempNoChanges = 0;
2726 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2727 noChanges += tempNoChanges;
2728 if (success)
2729 {
2730 succeeded.Append(child);
2731 }
2732 }
2733 }
2734 }
2735 node = node->Next();
2736 }
2737 noIterations ++;
2738 }
2739 return TRUE;
2740 }
2741
2742 void wxWindow::ResetConstraints()
2743 {
2744 wxLayoutConstraints *constr = GetConstraints();
2745 if (constr)
2746 {
2747 constr->left.SetDone(FALSE);
2748 constr->top.SetDone(FALSE);
2749 constr->right.SetDone(FALSE);
2750 constr->bottom.SetDone(FALSE);
2751 constr->width.SetDone(FALSE);
2752 constr->height.SetDone(FALSE);
2753 constr->centreX.SetDone(FALSE);
2754 constr->centreY.SetDone(FALSE);
2755 }
2756 wxNode *node = GetChildren()->First();
2757 while (node)
2758 {
2759 wxWindow *win = (wxWindow *)node->Data();
2760 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2761 win->ResetConstraints();
2762 node = node->Next();
2763 }
2764 }
2765
2766 // Need to distinguish between setting the 'fake' size for
2767 // windows and sizers, and setting the real values.
2768 void wxWindow::SetConstraintSizes(bool recurse)
2769 {
2770 wxLayoutConstraints *constr = GetConstraints();
2771 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2772 constr->width.GetDone() && constr->height.GetDone())
2773 {
2774 int x = constr->left.GetValue();
2775 int y = constr->top.GetValue();
2776 int w = constr->width.GetValue();
2777 int h = constr->height.GetValue();
2778
2779 // If we don't want to resize this window, just move it...
2780 if ((constr->width.GetRelationship() != wxAsIs) ||
2781 (constr->height.GetRelationship() != wxAsIs))
2782 {
2783 // Calls Layout() recursively. AAAGH. How can we stop that.
2784 // Simply take Layout() out of non-top level OnSizes.
2785 SizerSetSize(x, y, w, h);
2786 }
2787 else
2788 {
2789 SizerMove(x, y);
2790 }
2791 }
2792 else if (constr)
2793 {
2794 char *windowClass = this->GetClassInfo()->GetClassName();
2795
2796 wxString winName;
2797 if (GetName() == "")
2798 winName = _("unnamed");
2799 else
2800 winName = GetName();
2801 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2802 if (!constr->left.GetDone())
2803 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2804 if (!constr->right.GetDone())
2805 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2806 if (!constr->width.GetDone())
2807 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2808 if (!constr->height.GetDone())
2809 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2810 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2811 }
2812
2813 if (recurse)
2814 {
2815 wxNode *node = GetChildren()->First();
2816 while (node)
2817 {
2818 wxWindow *win = (wxWindow *)node->Data();
2819 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2820 win->SetConstraintSizes();
2821 node = node->Next();
2822 }
2823 }
2824 }
2825
2826 // This assumes that all sizers are 'on' the same
2827 // window, i.e. the parent of this window.
2828 void wxWindow::TransformSizerToActual(int *x, int *y) const
2829 {
2830 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2831 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2832 return;
2833
2834 int xp, yp;
2835 m_sizerParent->GetPosition(&xp, &yp);
2836 m_sizerParent->TransformSizerToActual(&xp, &yp);
2837 *x += xp;
2838 *y += yp;
2839 }
2840
2841 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2842 {
2843 int xx = x;
2844 int yy = y;
2845 TransformSizerToActual(&xx, &yy);
2846 SetSize(xx, yy, w, h);
2847 }
2848
2849 void wxWindow::SizerMove(int x, int y)
2850 {
2851 int xx = x;
2852 int yy = y;
2853 TransformSizerToActual(&xx, &yy);
2854 Move(xx, yy);
2855 }
2856
2857 // Only set the size/position of the constraint (if any)
2858 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2859 {
2860 wxLayoutConstraints *constr = GetConstraints();
2861 if (constr)
2862 {
2863 if (x != -1)
2864 {
2865 constr->left.SetValue(x);
2866 constr->left.SetDone(TRUE);
2867 }
2868 if (y != -1)
2869 {
2870 constr->top.SetValue(y);
2871 constr->top.SetDone(TRUE);
2872 }
2873 if (w != -1)
2874 {
2875 constr->width.SetValue(w);
2876 constr->width.SetDone(TRUE);
2877 }
2878 if (h != -1)
2879 {
2880 constr->height.SetValue(h);
2881 constr->height.SetDone(TRUE);
2882 }
2883 }
2884 }
2885
2886 void wxWindow::MoveConstraint(int x, int y)
2887 {
2888 wxLayoutConstraints *constr = GetConstraints();
2889 if (constr)
2890 {
2891 if (x != -1)
2892 {
2893 constr->left.SetValue(x);
2894 constr->left.SetDone(TRUE);
2895 }
2896 if (y != -1)
2897 {
2898 constr->top.SetValue(y);
2899 constr->top.SetDone(TRUE);
2900 }
2901 }
2902 }
2903
2904 void wxWindow::GetSizeConstraint(int *w, int *h) const
2905 {
2906 wxLayoutConstraints *constr = GetConstraints();
2907 if (constr)
2908 {
2909 *w = constr->width.GetValue();
2910 *h = constr->height.GetValue();
2911 }
2912 else
2913 GetSize(w, h);
2914 }
2915
2916 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2917 {
2918 wxLayoutConstraints *constr = GetConstraints();
2919 if (constr)
2920 {
2921 *w = constr->width.GetValue();
2922 *h = constr->height.GetValue();
2923 }
2924 else
2925 GetClientSize(w, h);
2926 }
2927
2928 void wxWindow::GetPositionConstraint(int *x, int *y) const
2929 {
2930 wxLayoutConstraints *constr = GetConstraints();
2931 if (constr)
2932 {
2933 *x = constr->left.GetValue();
2934 *y = constr->top.GetValue();
2935 }
2936 else
2937 GetPosition(x, y);
2938 }
2939
2940 bool wxWindow::AcceptsFocus() const
2941 {
2942 return IsEnabled() && IsShown();
2943 }
2944
2945 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
2946 {
2947 UpdateWindowUI();
2948 }