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