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