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