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