]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/window.cpp
Clipboard update
[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 "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 extern bool g_blockEventsOnScroll;
130 static bool g_capturing = FALSE;
131
132 // hack: we need something to pass to gtk_menu_popup, so we store the time of
133 // the last click here
134 static guint32 gs_timeLastClick = 0;
135
136 //-----------------------------------------------------------------------------
137 // "expose_event" (of m_wxwindow, not of m_widget)
138 //-----------------------------------------------------------------------------
139
140 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
141 {
142 if (!win->HasVMT()) 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
173 win->m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height );
174
175 wxPaintEvent event( win->GetId() );
176 event.SetEventObject( win );
177 win->GetEventHandler()->ProcessEvent( event );
178
179 win->m_updateRegion.Clear();
180 }
181
182 //-----------------------------------------------------------------------------
183 // "key_press_event"
184 //-----------------------------------------------------------------------------
185
186 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
187 {
188 if (!win->HasVMT()) return FALSE;
189 if (g_blockEventsOnDrag) return FALSE;
190
191 /*
192 printf( "OnKeyPress from " );
193 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
194 printf( win->GetClassInfo()->GetClassName() );
195 printf( ".\n" );
196 */
197
198 long key_code = 0;
199 switch (gdk_event->keyval)
200 {
201 case GDK_BackSpace: key_code = WXK_BACK; break;
202 case GDK_Tab: key_code = WXK_TAB; break;
203 case GDK_Linefeed: key_code = WXK_RETURN; break;
204 case GDK_Clear: key_code = WXK_CLEAR; break;
205 case GDK_Return: key_code = WXK_RETURN; break;
206 case GDK_Pause: key_code = WXK_PAUSE; break;
207 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
208 case GDK_Escape: key_code = WXK_ESCAPE; break;
209 case GDK_Delete: key_code = WXK_DELETE; break;
210 case GDK_Home: key_code = WXK_HOME; break;
211 case GDK_Left: key_code = WXK_LEFT; break;
212 case GDK_Up: key_code = WXK_UP; break;
213 case GDK_Right: key_code = WXK_RIGHT; break;
214 case GDK_Down: key_code = WXK_DOWN; break;
215 case GDK_Prior: key_code = WXK_PRIOR; break;
216 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
217 case GDK_Next: key_code = WXK_NEXT; break;
218 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
219 case GDK_End: key_code = WXK_END; break;
220 case GDK_Begin: key_code = WXK_HOME; break;
221 case GDK_Select: key_code = WXK_SELECT; break;
222 case GDK_Print: key_code = WXK_PRINT; break;
223 case GDK_Execute: key_code = WXK_EXECUTE; break;
224 case GDK_Insert: key_code = WXK_INSERT; break;
225 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
226 case GDK_KP_Tab: key_code = WXK_TAB; break;
227 case GDK_KP_Enter: key_code = WXK_RETURN; break;
228 case GDK_KP_Home: key_code = WXK_HOME; break;
229 case GDK_KP_Left: key_code = WXK_LEFT; break;
230 case GDK_KP_Up: key_code = WXK_UP; break;
231 case GDK_KP_Right: key_code = WXK_RIGHT; break;
232 case GDK_KP_Down: key_code = WXK_DOWN; break;
233 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
234 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
235 case GDK_KP_Next: key_code = WXK_NEXT; break;
236 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
237 case GDK_KP_End: key_code = WXK_END; break;
238 case GDK_KP_Begin: key_code = WXK_HOME; break;
239 case GDK_KP_Insert: key_code = WXK_INSERT; break;
240 case GDK_KP_Delete: key_code = WXK_DELETE; break;
241 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
242 case GDK_KP_Add: key_code = WXK_ADD; break;
243 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
244 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
245 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
246 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
247 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
248 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
249 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
250 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
251 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
252 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
253 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
254 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
255 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
256 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
257 case GDK_F1: key_code = WXK_F1; break;
258 case GDK_F2: key_code = WXK_F2; break;
259 case GDK_F3: key_code = WXK_F3; break;
260 case GDK_F4: key_code = WXK_F4; break;
261 case GDK_F5: key_code = WXK_F5; break;
262 case GDK_F6: key_code = WXK_F6; break;
263 case GDK_F7: key_code = WXK_F7; break;
264 case GDK_F8: key_code = WXK_F8; break;
265 case GDK_F9: key_code = WXK_F9; break;
266 case GDK_F10: key_code = WXK_F10; break;
267 case GDK_F11: key_code = WXK_F11; break;
268 case GDK_F12: key_code = WXK_F12; break;
269 default:
270 {
271 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
272 key_code = gdk_event->keyval;
273 }
274 }
275
276 if (!key_code) return FALSE;
277
278 wxKeyEvent event( wxEVT_CHAR );
279 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
280 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
281 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
282 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
283 event.m_keyCode = key_code;
284 event.m_x = 0;
285 event.m_y = 0;
286 event.SetEventObject( win );
287
288 bool ret = win->GetEventHandler()->ProcessEvent( event );
289
290 if (!ret)
291 {
292 wxWindow *ancestor = win;
293 while (ancestor)
294 {
295 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
296 if (command != -1)
297 {
298 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
299 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
300 break;
301 }
302 ancestor = ancestor->GetParent();
303 }
304 }
305
306 if (ret)
307 {
308 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
309 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
310 }
311
312 return ret;
313 }
314
315 //-----------------------------------------------------------------------------
316 // "button_press_event"
317 //-----------------------------------------------------------------------------
318
319 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
320 {
321 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
322
323 if (g_blockEventsOnDrag) return TRUE;
324 if (g_blockEventsOnScroll) 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 if (g_blockEventsOnScroll) return TRUE;
436
437 if (!win->HasVMT()) return TRUE;
438
439 /*
440 printf( "OnButtonRelease from " );
441 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
442 printf( win->GetClassInfo()->GetClassName() );
443 printf( ".\n" );
444 */
445
446 wxEventType event_type = wxEVT_NULL;
447
448 switch (gdk_event->button)
449 {
450 case 1: event_type = wxEVT_LEFT_UP; break;
451 case 2: event_type = wxEVT_MIDDLE_UP; break;
452 case 3: event_type = wxEVT_RIGHT_UP; break;
453 }
454
455 wxMouseEvent event( event_type );
456 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
457 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
458 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
459 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
460 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
461 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
462 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
463 event.m_x = (long)gdk_event->x;
464 event.m_y = (long)gdk_event->y;
465
466 // Some control don't have their own X window and thus cannot get
467 // any events.
468
469 if (!g_capturing)
470 {
471 wxNode *node = win->GetChildren().First();
472 while (node)
473 {
474 wxWindow *child = (wxWindow*)node->Data();
475 if ((child->m_x <= event.m_x) &&
476 (child->m_y <= event.m_y) &&
477 (child->m_x+child->m_width >= event.m_x) &&
478 (child->m_y+child->m_height >= event.m_y))
479 {
480 win = child;
481 event.m_x -= child->m_x;
482 event.m_y -= child->m_y;
483 break;
484 }
485 node = node->Next();
486 }
487 }
488
489 event.SetEventObject( win );
490
491 if (win->GetEventHandler()->ProcessEvent( event ))
492 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
493
494 return TRUE;
495 }
496
497 //-----------------------------------------------------------------------------
498 // "motion_notify_event"
499 //-----------------------------------------------------------------------------
500
501 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
502 {
503 if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
504
505 if (g_blockEventsOnDrag) return TRUE;
506 if (g_blockEventsOnScroll) return TRUE;
507
508 if (!win->HasVMT()) return TRUE;
509
510 /*
511 printf( "OnMotion from " );
512 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
513 printf( win->GetClassInfo()->GetClassName() );
514 printf( ".\n" );
515 */
516
517 wxMouseEvent event( wxEVT_MOTION );
518 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
519 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
520 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
521 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
522 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
523 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
524 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
525
526 event.m_x = (long)gdk_event->x;
527 event.m_y = (long)gdk_event->y;
528
529 // Some control don't have their own X window and thus cannot get
530 // any events.
531
532 if (!g_capturing)
533 {
534 wxNode *node = win->GetChildren().First();
535 while (node)
536 {
537 wxWindow *child = (wxWindow*)node->Data();
538 if ((child->m_x <= event.m_x) &&
539 (child->m_y <= event.m_y) &&
540 (child->m_x+child->m_width >= event.m_x) &&
541 (child->m_y+child->m_height >= event.m_y))
542 {
543 win = child;
544 event.m_x -= child->m_x;
545 event.m_y -= child->m_y;
546 break;
547 }
548 node = node->Next();
549 }
550 }
551
552 event.SetEventObject( win );
553
554 if (win->GetEventHandler()->ProcessEvent( event ))
555 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
556
557 return TRUE;
558 }
559
560 //-----------------------------------------------------------------------------
561 // "focus_in_event"
562 //-----------------------------------------------------------------------------
563
564 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
565 {
566 if (g_blockEventsOnDrag) return TRUE;
567 if (win->m_wxwindow)
568 {
569 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
570 {
571 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
572 /*
573 printf( "SetFocus flag from " );
574 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
575 printf( win->GetClassInfo()->GetClassName() );
576 printf( ".\n" );
577 */
578 }
579 }
580
581 if (!win->HasVMT()) return TRUE;
582
583 /*
584 printf( "OnSetFocus from " );
585 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
586 printf( win->GetClassInfo()->GetClassName() );
587 printf( " " );
588 printf( WXSTRINGCAST win->GetLabel() );
589 printf( ".\n" );
590 */
591
592 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
593 event.SetEventObject( win );
594
595 if (win->GetEventHandler()->ProcessEvent( event ))
596 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
597
598 return TRUE;
599 }
600
601 //-----------------------------------------------------------------------------
602 // "focus_out_event"
603 //-----------------------------------------------------------------------------
604
605 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
606 {
607 if (g_blockEventsOnDrag) return TRUE;
608 if (win->m_wxwindow)
609 {
610 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
611 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
612 }
613
614 if (!win->HasVMT()) return TRUE;
615
616 /*
617 printf( "OnKillFocus from " );
618 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
619 printf( win->GetClassInfo()->GetClassName() );
620 printf( ".\n" );
621 */
622
623 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
624 event.SetEventObject( win );
625
626 if (win->GetEventHandler()->ProcessEvent( event ))
627 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
628
629 return TRUE;
630 }
631
632 //-----------------------------------------------------------------------------
633 // "enter_notify_event"
634 //-----------------------------------------------------------------------------
635
636 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
637 {
638 if (widget->window != gdk_event->window) return TRUE;
639
640 if (g_blockEventsOnDrag) return TRUE;
641
642 if (!win->HasVMT()) return TRUE;
643
644 /*
645 printf( "OnEnter from " );
646 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
647 printf( win->GetClassInfo()->GetClassName() );
648 printf( ".\n" );
649 */
650
651 if ((widget->window) && (win->m_cursor))
652 gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
653
654 wxMouseEvent event( wxEVT_ENTER_WINDOW );
655 event.SetEventObject( win );
656
657 if (win->GetEventHandler()->ProcessEvent( event ))
658 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
659
660 return TRUE;
661 }
662
663 //-----------------------------------------------------------------------------
664 // "leave_notify_event"
665 //-----------------------------------------------------------------------------
666
667 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
668 {
669 if (widget->window != gdk_event->window) return TRUE;
670
671 if (g_blockEventsOnDrag) return TRUE;
672
673 if (!win->HasVMT()) return TRUE;
674
675 /*
676 printf( "OnLeave from " );
677 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
678 printf( win->GetClassInfo()->GetClassName() );
679 printf( ".\n" );
680 */
681
682 if ((widget->window) && (win->m_cursor))
683 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
684
685 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
686 event.SetEventObject( win );
687
688 if (win->GetEventHandler()->ProcessEvent( event ))
689 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
690
691 return TRUE;
692 }
693
694 //-----------------------------------------------------------------------------
695 // "value_changed" from m_vAdjust
696 //-----------------------------------------------------------------------------
697
698 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
699 {
700 if (g_blockEventsOnDrag) return;
701
702 /*
703 printf( "OnVScroll from " );
704 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
705 printf( win->GetClassInfo()->GetClassName() );
706 printf( ".\n" );
707 */
708
709 if (!win->HasVMT()) return;
710
711 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
712 if (fabs(diff) < 0.2) return;
713
714 wxEventType command = wxEVT_NULL;
715
716 float line_step = win->m_vAdjust->step_increment;
717 float page_step = win->m_vAdjust->page_increment;
718
719 if (win->m_isScrolling)
720 {
721 command = wxEVT_SCROLL_THUMBTRACK;
722 }
723 else
724 {
725 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
726 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
727 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
728 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
729 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
730 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
731 else command = wxEVT_SCROLL_THUMBTRACK;
732 }
733
734 int value = (int)(win->m_vAdjust->value+0.5);
735
736 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
737 event.SetEventObject( win );
738 win->GetEventHandler()->ProcessEvent( event );
739 }
740
741 //-----------------------------------------------------------------------------
742 // "value_changed" from m_hAdjust
743 //-----------------------------------------------------------------------------
744
745 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
746 {
747 if (g_blockEventsOnDrag) return;
748
749 /*
750 printf( "OnHScroll from " );
751 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
752 printf( win->GetClassInfo()->GetClassName() );
753 printf( ".\n" );
754 */
755
756 if (!win->HasVMT()) return;
757
758 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
759 if (fabs(diff) < 0.2) return;
760
761 wxEventType command = wxEVT_NULL;
762
763 float line_step = win->m_hAdjust->step_increment;
764 float page_step = win->m_hAdjust->page_increment;
765
766 if (win->m_isScrolling)
767 {
768 command = wxEVT_SCROLL_THUMBTRACK;
769 }
770 else
771 {
772 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
773 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
774 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
775 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
776 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
777 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
778 else command = wxEVT_SCROLL_THUMBTRACK;
779 }
780
781 int value = (int)(win->m_hAdjust->value+0.5);
782
783 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
784 event.SetEventObject( win );
785 win->GetEventHandler()->ProcessEvent( event );
786 }
787
788 //-----------------------------------------------------------------------------
789 // "changed" from m_vAdjust
790 //-----------------------------------------------------------------------------
791
792 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
793 {
794 if (g_blockEventsOnDrag) return;
795
796 /*
797 printf( "OnVScroll change from " );
798 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
799 printf( win->GetClassInfo()->GetClassName() );
800 printf( ".\n" );
801 */
802
803 if (!win->HasVMT()) return;
804
805 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
806 int value = (int)(win->m_vAdjust->value+0.5);
807
808 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
809 event.SetEventObject( win );
810 win->GetEventHandler()->ProcessEvent( event );
811 }
812
813 //-----------------------------------------------------------------------------
814 // "changed" from m_hAdjust
815 //-----------------------------------------------------------------------------
816
817 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
818 {
819 if (g_blockEventsOnDrag) return;
820
821 /*
822 printf( "OnHScroll change from " );
823 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
824 printf( win->GetClassInfo()->GetClassName() );
825 printf( ".\n" );
826 */
827
828 if (!win->HasVMT()) return;
829
830 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
831 int value = (int)(win->m_hAdjust->value+0.5);
832
833 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
834 event.SetEventObject( win );
835 win->GetEventHandler()->ProcessEvent( event );
836 }
837
838 //-----------------------------------------------------------------------------
839 // "button_press_event" from scrollbar
840 //-----------------------------------------------------------------------------
841
842 static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
843 GdkEventButton *WXUNUSED(gdk_event),
844 wxWindow *win )
845 {
846 // if (gdk_event->window != widget->slider) return FALSE;
847
848 win->m_isScrolling = TRUE;
849 g_blockEventsOnScroll = TRUE;
850
851 return FALSE;
852 }
853
854 //-----------------------------------------------------------------------------
855 // "button_release_event" from scrollbar
856 //-----------------------------------------------------------------------------
857
858 static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
859 GdkEventButton *WXUNUSED(gdk_event),
860 wxWindow *win )
861 {
862
863 // don't test here as we can reelase the mouse while being over
864 // a different window then the slider
865 //
866 // if (gdk_event->window != widget->slider) return FALSE;
867
868 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(win->m_widget);
869
870 if (widget == GTK_RANGE(s_window->vscrollbar))
871 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
872 else
873 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
874
875 win->m_isScrolling = FALSE;
876 g_blockEventsOnScroll = FALSE;
877
878 return FALSE;
879 }
880
881 //-----------------------------------------------------------------------------
882 // InsertChild for wxWindow.
883 //-----------------------------------------------------------------------------
884
885 // Callback for wxWindow. This very strange beast has to be used because
886 // C++ has no virtual methods in a constructor. We have to emulate a
887 // virtual function here as wxNotebook requires a different way to insert
888 // a child in it. I had opted for creating a wxNotebookPage window class
889 // which would have made this superflouus (such in the MDI window system),
890 // but no-one is listening to me...
891
892 static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
893 {
894 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
895 GTK_WIDGET(child->m_widget),
896 child->m_x,
897 child->m_y );
898
899 gtk_widget_set_usize( GTK_WIDGET(child->m_widget),
900 child->m_width,
901 child->m_height );
902 }
903
904 //-----------------------------------------------------------------------------
905 // wxWindow
906 //-----------------------------------------------------------------------------
907
908 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
909
910 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
911 EVT_SIZE(wxWindow::OnSize)
912 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
913 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
914 EVT_IDLE(wxWindow::OnIdle)
915 END_EVENT_TABLE()
916
917 wxWindow::wxWindow()
918 {
919 m_widget = (GtkWidget *) NULL;
920 m_wxwindow = (GtkWidget *) NULL;
921 m_parent = (wxWindow *) NULL;
922 m_children.DeleteContents( FALSE );
923
924 m_x = 0;
925 m_y = 0;
926 m_width = 0;
927 m_height = 0;
928 m_minWidth = -1;
929 m_minHeight = -1;
930 m_maxWidth = -1;
931 m_maxHeight = -1;
932
933 m_retCode = 0;
934
935 m_eventHandler = this;
936 m_windowValidator = (wxValidator *) NULL;
937
938 m_windowId = -1;
939
940 m_cursor = (wxCursor *) NULL;
941 m_font = *wxSWISS_FONT;
942 m_windowStyle = 0;
943 m_windowName = "noname";
944
945 m_constraints = (wxLayoutConstraints *) NULL;
946 m_constraintsInvolvedIn = (wxList *) NULL;
947 m_windowSizer = (wxSizer *) NULL;
948 m_sizerParent = (wxWindow *) NULL;
949 m_autoLayout = FALSE;
950
951 m_sizeSet = FALSE;
952 m_hasVMT = FALSE;
953 m_needParent = TRUE;
954
955 m_hasScrolling = FALSE;
956 m_isScrolling = FALSE;
957 m_hAdjust = (GtkAdjustment*) NULL;
958 m_vAdjust = (GtkAdjustment*) NULL;
959 m_oldHorizontalPos = 0.0;
960 m_oldVerticalPos = 0.0;
961
962 m_isShown = FALSE;
963 m_isEnabled = TRUE;
964
965 m_dropTarget = (wxDropTarget*) NULL;
966 m_resizing = FALSE;
967 m_scrollGC = (GdkGC*) NULL;
968 m_widgetStyle = (GtkStyle*) NULL;
969
970 m_insertCallback = wxInsertChildInWindow;
971
972 m_clientObject = (wxClientData*) NULL;
973 m_clientData = NULL;
974 }
975
976 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
977 const wxPoint &pos, const wxSize &size,
978 long style, const wxString &name )
979 {
980 m_insertCallback = wxInsertChildInWindow;
981 Create( parent, id, pos, size, style, name );
982 }
983
984 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
985 const wxPoint &pos, const wxSize &size,
986 long style, const wxString &name )
987 {
988 m_isShown = FALSE;
989 m_isEnabled = TRUE;
990 m_needParent = TRUE;
991
992 PreCreation( parent, id, pos, size, style, name );
993
994 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
995 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
996
997 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
998
999 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1000 scroll_class->scrollbar_spacing = 0;
1001
1002 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1003
1004 m_oldHorizontalPos = 0.0;
1005 m_oldVerticalPos = 0.0;
1006
1007 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
1008 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
1009
1010 m_wxwindow = gtk_myfixed_new();
1011
1012 #ifdef NEW_GTK_SCROLL_CODE
1013 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
1014 GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
1015 #else
1016 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
1017 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
1018 #endif
1019
1020 if (m_windowStyle & wxRAISED_BORDER)
1021 {
1022 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1023 }
1024 else if (m_windowStyle & wxSUNKEN_BORDER)
1025 {
1026 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1027 }
1028 else
1029 {
1030 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1031 }
1032
1033 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
1034 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1035 else
1036 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1037
1038 // shut the viewport up
1039 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1040 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1041
1042 // I _really_ don't want scrollbars in the beginning
1043 m_vAdjust->lower = 0.0;
1044 m_vAdjust->upper = 1.0;
1045 m_vAdjust->value = 0.0;
1046 m_vAdjust->step_increment = 1.0;
1047 m_vAdjust->page_increment = 1.0;
1048 m_vAdjust->page_size = 5.0;
1049 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1050 m_hAdjust->lower = 0.0;
1051 m_hAdjust->upper = 1.0;
1052 m_hAdjust->value = 0.0;
1053 m_hAdjust->step_increment = 1.0;
1054 m_hAdjust->page_increment = 1.0;
1055 m_hAdjust->page_size = 5.0;
1056 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1057
1058 // these handlers block mouse events to any window during scrolling
1059 // such as motion events and prevent GTK and wxWindows from fighting
1060 // over where the slider should be
1061
1062 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
1063 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1064
1065 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
1066 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1067
1068 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
1069 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1070
1071 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
1072 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1073
1074 // these handers het notified when screen updates are required either when
1075 // scrolling or when the window size (and therefore scrollbar configuration)
1076 // has changed
1077
1078 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1079 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1080 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1081 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1082
1083 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1084 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1085 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1086 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1087
1088 gtk_widget_show( m_wxwindow );
1089
1090 if (m_parent) m_parent->AddChild( this );
1091
1092 (m_parent->m_insertCallback)( m_parent, this );
1093
1094 PostCreation();
1095
1096 Show( TRUE );
1097
1098 return TRUE;
1099 }
1100
1101 wxWindow::~wxWindow()
1102 {
1103 m_hasVMT = FALSE;
1104
1105 if (m_dropTarget) delete m_dropTarget;
1106
1107 if (m_parent) m_parent->RemoveChild( this );
1108 if (m_widget) Show( FALSE );
1109
1110 DestroyChildren();
1111
1112 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1113
1114 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1115
1116 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1117
1118 if (m_widget) gtk_widget_destroy( m_widget );
1119
1120 if (m_cursor) delete m_cursor;
1121
1122 DeleteRelatedConstraints();
1123 if (m_constraints)
1124 {
1125 // This removes any dangling pointers to this window
1126 // in other windows' constraintsInvolvedIn lists.
1127 UnsetConstraints(m_constraints);
1128 delete m_constraints;
1129 m_constraints = (wxLayoutConstraints *) NULL;
1130 }
1131 if (m_windowSizer)
1132 {
1133 delete m_windowSizer;
1134 m_windowSizer = (wxSizer *) NULL;
1135 }
1136 // If this is a child of a sizer, remove self from parent
1137 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1138
1139 // Just in case the window has been Closed, but
1140 // we're then deleting immediately: don't leave
1141 // dangling pointers.
1142 wxPendingDelete.DeleteObject(this);
1143
1144 // Just in case we've loaded a top-level window via
1145 // wxWindow::LoadNativeDialog but we weren't a dialog
1146 // class
1147 wxTopLevelWindows.DeleteObject(this);
1148
1149 if (m_windowValidator) delete m_windowValidator;
1150
1151 if (m_clientObject) delete m_clientObject;
1152 }
1153
1154 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1155 const wxPoint &pos, const wxSize &size,
1156 long style, const wxString &name )
1157 {
1158 if (m_needParent && (parent == NULL))
1159 wxFatalError( "Need complete parent.", name );
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_childrenFirst();
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 wxList& wxWindow::GetChildren() const
1807 {
1808 return m_children;
1809 }
1810
1811 wxWindow *wxWindow::ReParent( wxWindow *newParent )
1812 {
1813 wxWindow *oldParent = GetParent();
1814
1815 if (oldParent) oldParent->RemoveChild( this );
1816
1817 gtk_widget_unparent( m_widget );
1818
1819 if (newParent)
1820 {
1821 newParent->AddChild( this );
1822 (newParent->m_insertCallback)( newParent, this );
1823 }
1824
1825 return oldParent;
1826 }
1827
1828 void wxWindow::RemoveChild( wxWindow *child )
1829 {
1830 m_children.DeleteObject( child );
1831 child->m_parent = (wxWindow *) NULL;
1832 }
1833
1834 void wxWindow::SetReturnCode( int retCode )
1835 {
1836 m_retCode = retCode;
1837 }
1838
1839 int wxWindow::GetReturnCode()
1840 {
1841 return m_retCode;
1842 }
1843
1844 void wxWindow::Raise()
1845 {
1846 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1847
1848 if (m_widget) gdk_window_raise( m_widget->window );
1849 }
1850
1851 void wxWindow::Lower()
1852 {
1853 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1854
1855 if (m_widget) gdk_window_lower( m_widget->window );
1856 }
1857
1858 wxEvtHandler *wxWindow::GetEventHandler()
1859 {
1860 return m_eventHandler;
1861 }
1862
1863 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1864 {
1865 m_eventHandler = handler;
1866 }
1867
1868 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1869 {
1870 handler->SetNextHandler(GetEventHandler());
1871 SetEventHandler(handler);
1872 }
1873
1874 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1875 {
1876 if (GetEventHandler())
1877 {
1878 wxEvtHandler *handlerA = GetEventHandler();
1879 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1880 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1881 SetEventHandler(handlerB);
1882 if (deleteHandler)
1883 {
1884 delete handlerA;
1885 return (wxEvtHandler*) NULL;
1886 }
1887 else
1888 return handlerA;
1889 }
1890 else
1891 return (wxEvtHandler *) NULL;
1892 }
1893
1894 wxValidator *wxWindow::GetValidator()
1895 {
1896 return m_windowValidator;
1897 }
1898
1899 void wxWindow::SetValidator( const wxValidator& validator )
1900 {
1901 if (m_windowValidator) delete m_windowValidator;
1902 m_windowValidator = validator.Clone();
1903 if (m_windowValidator) m_windowValidator->SetWindow(this);
1904 }
1905
1906 void wxWindow::SetClientObject( wxClientData *data )
1907 {
1908 if (m_clientObject) delete m_clientObject;
1909 m_clientObject = data;
1910 }
1911
1912 wxClientData *wxWindow::GetClientObject()
1913 {
1914 return m_clientObject;
1915 }
1916
1917 void wxWindow::SetClientData( void *data )
1918 {
1919 m_clientData = data;
1920 }
1921
1922 void *wxWindow::GetClientData()
1923 {
1924 return m_clientData;
1925 }
1926
1927 bool wxWindow::IsBeingDeleted()
1928 {
1929 return FALSE;
1930 }
1931
1932 void wxWindow::SetId( wxWindowID id )
1933 {
1934 m_windowId = id;
1935 }
1936
1937 wxWindowID wxWindow::GetId()
1938 {
1939 return m_windowId;
1940 }
1941
1942 void wxWindow::SetCursor( const wxCursor &cursor )
1943 {
1944 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1945
1946 if (m_cursor == NULL)
1947 {
1948 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1949 m_cursor = new wxCursor( wxCURSOR_ARROW );
1950 }
1951
1952 if (cursor.Ok())
1953 {
1954 if (*((wxCursor*)&cursor) == m_cursor) return;
1955 *m_cursor = cursor;
1956 }
1957 else
1958 {
1959 *m_cursor = *wxSTANDARD_CURSOR;
1960 }
1961
1962 if ((m_widget) && (m_widget->window))
1963 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1964
1965 if ((m_wxwindow) && (m_wxwindow->window))
1966 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1967 }
1968
1969 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1970 {
1971 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1972
1973 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1974 {
1975 if (rect)
1976 gdk_window_clear_area( m_wxwindow->window,
1977 rect->x,
1978 rect->y,
1979 rect->width,
1980 rect->height );
1981 else
1982 Clear();
1983 }
1984 if (!rect)
1985 {
1986 if (m_wxwindow)
1987 {
1988 int w = 0;
1989 int h = 0;
1990 GetClientSize( &w, &h );
1991
1992 GdkRectangle gdk_rect;
1993 gdk_rect.x = 0;
1994 gdk_rect.y = 0;
1995 gdk_rect.width = w;
1996 gdk_rect.height = h;
1997 gtk_widget_draw( m_wxwindow, &gdk_rect );
1998 }
1999 }
2000 else
2001 {
2002 GdkRectangle gdk_rect;
2003 gdk_rect.x = rect->x;
2004 gdk_rect.y = rect->y;
2005 gdk_rect.width = rect->width;
2006 gdk_rect.height = rect->height;
2007
2008 if (m_wxwindow)
2009 gtk_widget_draw( m_wxwindow, &gdk_rect );
2010 else
2011 gtk_widget_draw( m_widget, &gdk_rect );
2012 }
2013 }
2014
2015 wxRegion wxWindow::GetUpdateRegion() const
2016 {
2017 return m_updateRegion;
2018 }
2019
2020 bool wxWindow::IsExposed( int x, int y) const
2021 {
2022 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
2023 }
2024
2025 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
2026 {
2027 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
2028 }
2029
2030 bool wxWindow::IsExposed( const wxPoint& pt ) const
2031 {
2032 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
2033 }
2034
2035 bool wxWindow::IsExposed( const wxRect& rect ) const
2036 {
2037 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
2038 }
2039
2040 void wxWindow::Clear()
2041 {
2042 wxCHECK_RET( m_widget != NULL, "invalid window" );
2043
2044 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
2045 }
2046
2047 wxColour wxWindow::GetBackgroundColour() const
2048 {
2049 return m_backgroundColour;
2050 }
2051
2052 void wxWindow::SetBackgroundColour( const wxColour &colour )
2053 {
2054 wxCHECK_RET( m_widget != NULL, "invalid window" );
2055
2056 if (m_backgroundColour == colour) return;
2057
2058 if (!m_backgroundColour.Ok())
2059 if (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) == colour) return;
2060
2061 m_backgroundColour = colour;
2062 if (!m_backgroundColour.Ok()) return;
2063
2064 if (m_wxwindow)
2065 {
2066 GdkWindow *window = m_wxwindow->window;
2067 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2068 gdk_window_set_background( window, m_backgroundColour.GetColor() );
2069 gdk_window_clear( window );
2070 }
2071
2072 ApplyWidgetStyle();
2073 }
2074
2075 wxColour wxWindow::GetForegroundColour() const
2076 {
2077 return m_foregroundColour;
2078 }
2079
2080 void wxWindow::SetForegroundColour( const wxColour &colour )
2081 {
2082 wxCHECK_RET( m_widget != NULL, "invalid window" );
2083
2084 if (m_foregroundColour == colour) return;
2085
2086 m_foregroundColour = colour;
2087 if (!m_foregroundColour.Ok()) return;
2088
2089 ApplyWidgetStyle();
2090 }
2091
2092 GtkStyle *wxWindow::GetWidgetStyle()
2093 {
2094 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
2095
2096 m_widgetStyle =
2097 gtk_style_copy(
2098 gtk_widget_get_style( m_widget ) );
2099
2100 return m_widgetStyle;
2101 }
2102
2103 void wxWindow::SetWidgetStyle()
2104 {
2105 GtkStyle *style = GetWidgetStyle();
2106
2107 gdk_font_unref( style->font );
2108 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2109
2110 if (m_foregroundColour.Ok())
2111 {
2112 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2113 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2114 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2115 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2116 }
2117
2118 if (m_backgroundColour.Ok())
2119 {
2120 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2121 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2122 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2123 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2124 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2125 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2126 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2127 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2128 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2129 }
2130 }
2131
2132 void wxWindow::ApplyWidgetStyle()
2133 {
2134 }
2135
2136 bool wxWindow::Validate()
2137 {
2138 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2139
2140 wxNode *node = m_children.First();
2141 while (node)
2142 {
2143 wxWindow *child = (wxWindow *)node->Data();
2144 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2145 { return FALSE; }
2146 node = node->Next();
2147 }
2148 return TRUE;
2149 }
2150
2151 bool wxWindow::TransferDataToWindow()
2152 {
2153 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2154
2155 wxNode *node = m_children.First();
2156 while (node)
2157 {
2158 wxWindow *child = (wxWindow *)node->Data();
2159 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2160 !child->GetValidator()->TransferToWindow() )
2161 {
2162 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2163 return FALSE;
2164 }
2165 node = node->Next();
2166 }
2167 return TRUE;
2168 }
2169
2170 bool wxWindow::TransferDataFromWindow()
2171 {
2172 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2173
2174 wxNode *node = m_children.First();
2175 while (node)
2176 {
2177 wxWindow *child = (wxWindow *)node->Data();
2178 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2179 { return FALSE; }
2180 node = node->Next();
2181 }
2182 return TRUE;
2183 }
2184
2185 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2186 {
2187 m_acceleratorTable = accel;
2188 }
2189
2190 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2191 {
2192 TransferDataToWindow();
2193 }
2194
2195 void wxWindow::InitDialog()
2196 {
2197 wxCHECK_RET( m_widget != NULL, "invalid window" );
2198
2199 wxInitDialogEvent event(GetId());
2200 event.SetEventObject( this );
2201 GetEventHandler()->ProcessEvent(event);
2202 }
2203
2204 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2205 {
2206 menu->SetInvokingWindow( win );
2207 wxNode *node = menu->m_items.First();
2208 while (node)
2209 {
2210 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2211 if (menuitem->IsSubMenu())
2212 SetInvokingWindow( menuitem->GetSubMenu(), win );
2213 node = node->Next();
2214 }
2215 }
2216
2217 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2218 {
2219 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2220
2221 wxCHECK_MSG( menu != NULL, FALSE, "invalid popup-menu" );
2222
2223 SetInvokingWindow( menu, this );
2224 gtk_menu_popup(
2225 GTK_MENU(menu->m_menu),
2226 (GtkWidget *)NULL, // parent menu shell
2227 (GtkWidget *)NULL, // parent menu item
2228 (GtkMenuPositionFunc)NULL,
2229 NULL, // client data
2230 0, // button used to activate it
2231 0//gs_timeLastClick // the time of activation
2232 );
2233 return TRUE;
2234 }
2235
2236 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2237 {
2238 wxCHECK_RET( m_widget != NULL, "invalid window" );
2239
2240 GtkWidget *dnd_widget = GetConnectWidget();
2241
2242 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
2243
2244 if (m_dropTarget) delete m_dropTarget;
2245 m_dropTarget = dropTarget;
2246
2247 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
2248 }
2249
2250 wxDropTarget *wxWindow::GetDropTarget() const
2251 {
2252 return m_dropTarget;
2253 }
2254
2255 GtkWidget* wxWindow::GetConnectWidget()
2256 {
2257 GtkWidget *connect_widget = m_widget;
2258 if (m_wxwindow) connect_widget = m_wxwindow;
2259
2260 return connect_widget;
2261 }
2262
2263 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2264 {
2265 if (m_wxwindow) return (window == m_wxwindow->window);
2266 return (window == m_widget->window);
2267 }
2268
2269 void wxWindow::SetFont( const wxFont &font )
2270 {
2271 wxCHECK_RET( m_widget != NULL, "invalid window" );
2272
2273 if (((wxFont*)&font)->Ok())
2274 m_font = font;
2275 else
2276 m_font = *wxSWISS_FONT;
2277
2278 ApplyWidgetStyle();
2279 }
2280
2281 wxFont *wxWindow::GetFont()
2282 {
2283 return &m_font;
2284 }
2285
2286 void wxWindow::SetWindowStyleFlag( long flag )
2287 {
2288 m_windowStyle = flag;
2289 }
2290
2291 long wxWindow::GetWindowStyleFlag() const
2292 {
2293 return m_windowStyle;
2294 }
2295
2296 void wxWindow::CaptureMouse()
2297 {
2298 wxCHECK_RET( m_widget != NULL, "invalid window" );
2299
2300 wxCHECK_RET( g_capturing == FALSE, "CaptureMouse called twice" );
2301
2302 GtkWidget *connect_widget = GetConnectWidget();
2303 gtk_grab_add( connect_widget );
2304 gdk_pointer_grab ( connect_widget->window, FALSE,
2305 (GdkEventMask)
2306 (GDK_BUTTON_PRESS_MASK |
2307 GDK_BUTTON_RELEASE_MASK |
2308 GDK_POINTER_MOTION_MASK),
2309 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2310 g_capturing = TRUE;
2311 }
2312
2313 void wxWindow::ReleaseMouse()
2314 {
2315 wxCHECK_RET( m_widget != NULL, "invalid window" );
2316
2317 wxCHECK_RET( g_capturing == TRUE, "ReleaseMouse called twice" );
2318
2319 GtkWidget *connect_widget = GetConnectWidget();
2320 gtk_grab_remove( connect_widget );
2321 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2322 g_capturing = FALSE;
2323 }
2324
2325 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2326 {
2327 }
2328
2329 wxString wxWindow::GetTitle() const
2330 {
2331 return (wxString&)m_windowName;
2332 }
2333
2334 wxString wxWindow::GetLabel() const
2335 {
2336 return GetTitle();
2337 }
2338
2339 void wxWindow::SetName( const wxString &name )
2340 {
2341 m_windowName = name;
2342 }
2343
2344 wxString wxWindow::GetName() const
2345 {
2346 return (wxString&)m_windowName;
2347 }
2348
2349 bool wxWindow::IsShown() const
2350 {
2351 return m_isShown;
2352 }
2353
2354 bool wxWindow::IsRetained()
2355 {
2356 return FALSE;
2357 }
2358
2359 wxWindow *wxWindow::FindWindow( long id )
2360 {
2361 if (id == m_windowId) return this;
2362 wxNode *node = m_children.First();
2363 while (node)
2364 {
2365 wxWindow *child = (wxWindow*)node->Data();
2366 wxWindow *res = child->FindWindow( id );
2367 if (res) return res;
2368 node = node->Next();
2369 }
2370 return (wxWindow *) NULL;
2371 }
2372
2373 wxWindow *wxWindow::FindWindow( const wxString& name )
2374 {
2375 if (name == m_windowName) return this;
2376 wxNode *node = m_children.First();
2377 while (node)
2378 {
2379 wxWindow *child = (wxWindow*)node->Data();
2380 wxWindow *res = child->FindWindow( name );
2381 if (res) return res;
2382 node = node->Next();
2383 }
2384 return (wxWindow *) NULL;
2385 }
2386
2387 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2388 int range, bool refresh )
2389 {
2390 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2391
2392 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2393
2394 if (!m_wxwindow) return;
2395
2396 m_hasScrolling = TRUE;
2397
2398 if (orient == wxHORIZONTAL)
2399 {
2400 float fpos = (float)pos;
2401 float frange = (float)range;
2402 float fthumb = (float)thumbVisible;
2403
2404 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2405 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2406 {
2407 SetScrollPos( orient, pos, refresh );
2408 return;
2409 }
2410
2411 m_oldHorizontalPos = fpos;
2412
2413 m_hAdjust->lower = 0.0;
2414 m_hAdjust->upper = frange;
2415 m_hAdjust->value = fpos;
2416 m_hAdjust->step_increment = 1.0;
2417 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2418 m_hAdjust->page_size = fthumb;
2419 }
2420 else
2421 {
2422 float fpos = (float)pos;
2423 float frange = (float)range;
2424 float fthumb = (float)thumbVisible;
2425
2426 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2427 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2428 {
2429 SetScrollPos( orient, pos, refresh );
2430 return;
2431 }
2432
2433 m_oldVerticalPos = fpos;
2434
2435 m_vAdjust->lower = 0.0;
2436 m_vAdjust->upper = frange;
2437 m_vAdjust->value = fpos;
2438 m_vAdjust->step_increment = 1.0;
2439 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2440 m_vAdjust->page_size = fthumb;
2441 }
2442
2443 if (m_wxwindow->window)
2444 {
2445 if (orient == wxHORIZONTAL)
2446 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2447 else
2448 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2449
2450 gtk_widget_set_usize( m_widget, m_width, m_height );
2451 }
2452 }
2453
2454 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2455 {
2456 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2457
2458 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2459
2460 if (!m_wxwindow) return;
2461
2462 if (orient == wxHORIZONTAL)
2463 {
2464 float fpos = (float)pos;
2465 m_oldHorizontalPos = fpos;
2466
2467 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2468 m_hAdjust->value = fpos;
2469 }
2470 else
2471 {
2472 float fpos = (float)pos;
2473 m_oldVerticalPos = fpos;
2474 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2475 m_vAdjust->value = fpos;
2476 }
2477
2478 if (!m_isScrolling)
2479 {
2480 if (m_wxwindow->window)
2481 {
2482 if (orient == wxHORIZONTAL)
2483 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2484 else
2485 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2486 }
2487 }
2488 }
2489
2490 int wxWindow::GetScrollThumb( int orient ) const
2491 {
2492 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2493
2494 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2495
2496 if (!m_wxwindow) return 0;
2497
2498 if (orient == wxHORIZONTAL)
2499 return (int)(m_hAdjust->page_size+0.5);
2500 else
2501 return (int)(m_vAdjust->page_size+0.5);
2502 }
2503
2504 int wxWindow::GetScrollPos( int orient ) const
2505 {
2506 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2507
2508 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2509
2510 if (!m_wxwindow) return 0;
2511
2512 if (orient == wxHORIZONTAL)
2513 return (int)(m_hAdjust->value+0.5);
2514 else
2515 return (int)(m_vAdjust->value+0.5);
2516 }
2517
2518 int wxWindow::GetScrollRange( int orient ) const
2519 {
2520 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2521
2522 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2523
2524 if (!m_wxwindow) return 0;
2525
2526 if (orient == wxHORIZONTAL)
2527 return (int)(m_hAdjust->upper+0.5);
2528 else
2529 return (int)(m_vAdjust->upper+0.5);
2530 }
2531
2532 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2533 {
2534 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2535
2536 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2537
2538 if (!m_wxwindow) return;
2539
2540 int cw = 0;
2541 int ch = 0;
2542 GetClientSize( &cw, &ch );
2543
2544 int w = cw - abs(dx);
2545 int h = ch - abs(dy);
2546 if ((h < 0) || (w < 0))
2547 {
2548 Refresh();
2549 return;
2550 }
2551 int s_x = 0;
2552 int s_y = 0;
2553 if (dx < 0) s_x = -dx;
2554 if (dy < 0) s_y = -dy;
2555 int d_x = 0;
2556 int d_y = 0;
2557 if (dx > 0) d_x = dx;
2558 if (dy > 0) d_y = dy;
2559
2560 if (!m_scrollGC)
2561 {
2562 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2563 gdk_gc_set_exposures( m_scrollGC, TRUE );
2564 }
2565
2566 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2567 m_wxwindow->window, s_x, s_y, w, h );
2568
2569 wxRect rect;
2570 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2571 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2572 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2573 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2574
2575 Refresh( TRUE, &rect );
2576 }
2577
2578 //-------------------------------------------------------------------------------------
2579 // Layout
2580 //-------------------------------------------------------------------------------------
2581
2582 wxLayoutConstraints *wxWindow::GetConstraints() const
2583 {
2584 return m_constraints;
2585 }
2586
2587 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2588 {
2589 if (m_constraints)
2590 {
2591 UnsetConstraints(m_constraints);
2592 delete m_constraints;
2593 }
2594 m_constraints = constraints;
2595 if (m_constraints)
2596 {
2597 // Make sure other windows know they're part of a 'meaningful relationship'
2598 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2599 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2600 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2601 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2602 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2603 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2604 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2605 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2606 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2607 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2608 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2609 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2610 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2611 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2612 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2613 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2614 }
2615 ;
2616 }
2617 ;
2618
2619 void wxWindow::SetAutoLayout( bool autoLayout )
2620 {
2621 m_autoLayout = autoLayout;
2622 }
2623
2624 bool wxWindow::GetAutoLayout() const
2625 {
2626 return m_autoLayout;
2627 }
2628
2629 wxSizer *wxWindow::GetSizer() const
2630 {
2631 return m_windowSizer;
2632 }
2633
2634 void wxWindow::SetSizerParent( wxWindow *win )
2635 {
2636 m_sizerParent = win;
2637 }
2638
2639 wxWindow *wxWindow::GetSizerParent() const
2640 {
2641 return m_sizerParent;
2642 }
2643
2644 // This removes any dangling pointers to this window
2645 // in other windows' constraintsInvolvedIn lists.
2646 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2647 {
2648 if (c)
2649 {
2650 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2651 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2652 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2653 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2654 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2655 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2656 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2657 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2658 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2659 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2660 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2661 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2662 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2663 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2664 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2665 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2666 }
2667 }
2668
2669 // Back-pointer to other windows we're involved with, so if we delete
2670 // this window, we must delete any constraints we're involved with.
2671 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2672 {
2673 if (!m_constraintsInvolvedIn)
2674 m_constraintsInvolvedIn = new wxList;
2675 if (!m_constraintsInvolvedIn->Member(otherWin))
2676 m_constraintsInvolvedIn->Append(otherWin);
2677 }
2678
2679 // REMOVE back-pointer to other windows we're involved with.
2680 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2681 {
2682 if (m_constraintsInvolvedIn)
2683 m_constraintsInvolvedIn->DeleteObject(otherWin);
2684 }
2685
2686 // Reset any constraints that mention this window
2687 void wxWindow::DeleteRelatedConstraints()
2688 {
2689 if (m_constraintsInvolvedIn)
2690 {
2691 wxNode *node = m_constraintsInvolvedIn->First();
2692 while (node)
2693 {
2694 wxWindow *win = (wxWindow *)node->Data();
2695 wxNode *next = node->Next();
2696 wxLayoutConstraints *constr = win->GetConstraints();
2697
2698 // Reset any constraints involving this window
2699 if (constr)
2700 {
2701 constr->left.ResetIfWin((wxWindow *)this);
2702 constr->top.ResetIfWin((wxWindow *)this);
2703 constr->right.ResetIfWin((wxWindow *)this);
2704 constr->bottom.ResetIfWin((wxWindow *)this);
2705 constr->width.ResetIfWin((wxWindow *)this);
2706 constr->height.ResetIfWin((wxWindow *)this);
2707 constr->centreX.ResetIfWin((wxWindow *)this);
2708 constr->centreY.ResetIfWin((wxWindow *)this);
2709 }
2710 delete node;
2711 node = next;
2712 }
2713 delete m_constraintsInvolvedIn;
2714 m_constraintsInvolvedIn = (wxList *) NULL;
2715 }
2716 }
2717
2718 void wxWindow::SetSizer(wxSizer *sizer)
2719 {
2720 m_windowSizer = sizer;
2721 if (sizer)
2722 sizer->SetSizerParent((wxWindow *)this);
2723 }
2724
2725 /*
2726 * New version
2727 */
2728
2729 bool wxWindow::Layout()
2730 {
2731 if (GetConstraints())
2732 {
2733 int w, h;
2734 GetClientSize(&w, &h);
2735 GetConstraints()->width.SetValue(w);
2736 GetConstraints()->height.SetValue(h);
2737 }
2738
2739 // If top level (one sizer), evaluate the sizer's constraints.
2740 if (GetSizer())
2741 {
2742 int noChanges;
2743 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2744 GetSizer()->LayoutPhase1(&noChanges);
2745 GetSizer()->LayoutPhase2(&noChanges);
2746 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2747 return TRUE;
2748 }
2749 else
2750 {
2751 // Otherwise, evaluate child constraints
2752 ResetConstraints(); // Mark all constraints as unevaluated
2753 DoPhase(1); // Just one phase need if no sizers involved
2754 DoPhase(2);
2755 SetConstraintSizes(); // Recursively set the real window sizes
2756 }
2757 return TRUE;
2758 }
2759
2760
2761 // Do a phase of evaluating constraints:
2762 // the default behaviour. wxSizers may do a similar
2763 // thing, but also impose their own 'constraints'
2764 // and order the evaluation differently.
2765 bool wxWindow::LayoutPhase1(int *noChanges)
2766 {
2767 wxLayoutConstraints *constr = GetConstraints();
2768 if (constr)
2769 {
2770 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2771 }
2772 else
2773 return TRUE;
2774 }
2775
2776 bool wxWindow::LayoutPhase2(int *noChanges)
2777 {
2778 *noChanges = 0;
2779
2780 // Layout children
2781 DoPhase(1);
2782 DoPhase(2);
2783 return TRUE;
2784 }
2785
2786 // Do a phase of evaluating child constraints
2787 bool wxWindow::DoPhase(int phase)
2788 {
2789 int noIterations = 0;
2790 int maxIterations = 500;
2791 int noChanges = 1;
2792 int noFailures = 0;
2793 wxList succeeded;
2794 while ((noChanges > 0) && (noIterations < maxIterations))
2795 {
2796 noChanges = 0;
2797 noFailures = 0;
2798 wxNode *node = m_children.first();
2799 while (node)
2800 {
2801 wxWindow *child = (wxWindow *)node->Data();
2802 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2803 {
2804 wxLayoutConstraints *constr = child->GetConstraints();
2805 if (constr)
2806 {
2807 if (succeeded.Member(child))
2808 {
2809 }
2810 else
2811 {
2812 int tempNoChanges = 0;
2813 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2814 noChanges += tempNoChanges;
2815 if (success)
2816 {
2817 succeeded.Append(child);
2818 }
2819 }
2820 }
2821 }
2822 node = node->Next();
2823 }
2824 noIterations ++;
2825 }
2826 return TRUE;
2827 }
2828
2829 void wxWindow::ResetConstraints()
2830 {
2831 wxLayoutConstraints *constr = GetConstraints();
2832 if (constr)
2833 {
2834 constr->left.SetDone(FALSE);
2835 constr->top.SetDone(FALSE);
2836 constr->right.SetDone(FALSE);
2837 constr->bottom.SetDone(FALSE);
2838 constr->width.SetDone(FALSE);
2839 constr->height.SetDone(FALSE);
2840 constr->centreX.SetDone(FALSE);
2841 constr->centreY.SetDone(FALSE);
2842 }
2843 wxNode *node = m_children.First();
2844 while (node)
2845 {
2846 wxWindow *win = (wxWindow *)node->Data();
2847 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2848 win->ResetConstraints();
2849 node = node->Next();
2850 }
2851 }
2852
2853 // Need to distinguish between setting the 'fake' size for
2854 // windows and sizers, and setting the real values.
2855 void wxWindow::SetConstraintSizes(bool recurse)
2856 {
2857 wxLayoutConstraints *constr = GetConstraints();
2858 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2859 constr->width.GetDone() && constr->height.GetDone())
2860 {
2861 int x = constr->left.GetValue();
2862 int y = constr->top.GetValue();
2863 int w = constr->width.GetValue();
2864 int h = constr->height.GetValue();
2865
2866 // If we don't want to resize this window, just move it...
2867 if ((constr->width.GetRelationship() != wxAsIs) ||
2868 (constr->height.GetRelationship() != wxAsIs))
2869 {
2870 // Calls Layout() recursively. AAAGH. How can we stop that.
2871 // Simply take Layout() out of non-top level OnSizes.
2872 SizerSetSize(x, y, w, h);
2873 }
2874 else
2875 {
2876 SizerMove(x, y);
2877 }
2878 }
2879 else if (constr)
2880 {
2881 char *windowClass = this->GetClassInfo()->GetClassName();
2882
2883 wxString winName;
2884 if (GetName() == "")
2885 winName = _("unnamed");
2886 else
2887 winName = GetName();
2888 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2889 if (!constr->left.GetDone())
2890 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2891 if (!constr->right.GetDone())
2892 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2893 if (!constr->width.GetDone())
2894 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2895 if (!constr->height.GetDone())
2896 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2897 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2898 }
2899
2900 if (recurse)
2901 {
2902 wxNode *node = m_children.First();
2903 while (node)
2904 {
2905 wxWindow *win = (wxWindow *)node->Data();
2906 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2907 win->SetConstraintSizes();
2908 node = node->Next();
2909 }
2910 }
2911 }
2912
2913 // This assumes that all sizers are 'on' the same
2914 // window, i.e. the parent of this window.
2915 void wxWindow::TransformSizerToActual(int *x, int *y) const
2916 {
2917 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2918 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2919 return;
2920
2921 int xp, yp;
2922 m_sizerParent->GetPosition(&xp, &yp);
2923 m_sizerParent->TransformSizerToActual(&xp, &yp);
2924 *x += xp;
2925 *y += yp;
2926 }
2927
2928 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2929 {
2930 int xx = x;
2931 int yy = y;
2932 TransformSizerToActual(&xx, &yy);
2933 SetSize(xx, yy, w, h);
2934 }
2935
2936 void wxWindow::SizerMove(int x, int y)
2937 {
2938 int xx = x;
2939 int yy = y;
2940 TransformSizerToActual(&xx, &yy);
2941 Move(xx, yy);
2942 }
2943
2944 // Only set the size/position of the constraint (if any)
2945 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2946 {
2947 wxLayoutConstraints *constr = GetConstraints();
2948 if (constr)
2949 {
2950 if (x != -1)
2951 {
2952 constr->left.SetValue(x);
2953 constr->left.SetDone(TRUE);
2954 }
2955 if (y != -1)
2956 {
2957 constr->top.SetValue(y);
2958 constr->top.SetDone(TRUE);
2959 }
2960 if (w != -1)
2961 {
2962 constr->width.SetValue(w);
2963 constr->width.SetDone(TRUE);
2964 }
2965 if (h != -1)
2966 {
2967 constr->height.SetValue(h);
2968 constr->height.SetDone(TRUE);
2969 }
2970 }
2971 }
2972
2973 void wxWindow::MoveConstraint(int x, int y)
2974 {
2975 wxLayoutConstraints *constr = GetConstraints();
2976 if (constr)
2977 {
2978 if (x != -1)
2979 {
2980 constr->left.SetValue(x);
2981 constr->left.SetDone(TRUE);
2982 }
2983 if (y != -1)
2984 {
2985 constr->top.SetValue(y);
2986 constr->top.SetDone(TRUE);
2987 }
2988 }
2989 }
2990
2991 void wxWindow::GetSizeConstraint(int *w, int *h) const
2992 {
2993 wxLayoutConstraints *constr = GetConstraints();
2994 if (constr)
2995 {
2996 *w = constr->width.GetValue();
2997 *h = constr->height.GetValue();
2998 }
2999 else
3000 GetSize(w, h);
3001 }
3002
3003 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
3004 {
3005 wxLayoutConstraints *constr = GetConstraints();
3006 if (constr)
3007 {
3008 *w = constr->width.GetValue();
3009 *h = constr->height.GetValue();
3010 }
3011 else
3012 GetClientSize(w, h);
3013 }
3014
3015 void wxWindow::GetPositionConstraint(int *x, int *y) const
3016 {
3017 wxLayoutConstraints *constr = GetConstraints();
3018 if (constr)
3019 {
3020 *x = constr->left.GetValue();
3021 *y = constr->top.GetValue();
3022 }
3023 else
3024 GetPosition(x, y);
3025 }
3026
3027 bool wxWindow::AcceptsFocus() const
3028 {
3029 return IsEnabled() && IsShown();
3030 }
3031
3032 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
3033 {
3034 UpdateWindowUI();
3035 }