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