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