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