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