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