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