]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/window.cpp
59d8a97bbd69cc1b5c21212895a55c5b90c66dfe
[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/mdi.h"
27 #include "wx/menu.h"
28 #include "wx/notebook.h"
29 #include "wx/statusbr.h"
30 #include "wx/intl.h"
31 #include "wx/gtk/win_gtk.h"
32 #include "gdk/gdkprivate.h"
33 #include "gdk/gdkkeysyms.h"
34
35 #include <math.h>
36
37 //-----------------------------------------------------------------------------
38 // documentation on internals
39 //-----------------------------------------------------------------------------
40
41 /*
42 I have been asked several times about writing some documentation about
43 the GTK port of wxWindows, especially its internal structures. Obviously,
44 you cannot understand wxGTK without knowing a little about the GTK, but
45 some more information about what the wxWindow, which is the base class
46 for all other window classes, does seems required as well.
47
48 What does wxWindow do? It contains the common interface for the following
49 jobs of its descentants:
50
51 1) Define the rudimentary behaviour common to all window classes, such as
52 resizing, intercepting user input so as to make it possible to use these
53 events for special purposes in a derived class, window names etc.
54
55 2) Provide the possibility to contain and manage children, if the derived
56 class is allowed to contain children, which holds true for those window
57 classes, which do not display a native GTK widget. To name them, these
58 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
59 work classes are a special case and are handled a bit differently from
60 the rest.
61
62 3) Provide the possibility to draw into a client area of a window. This,
63 too, only holds true for classes that do not display a native GTK widget
64 as above.
65
66 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
67 face for this is usually in wxScrolledWidget, but the GTK implementation
68 is in this class.
69
70 5) A multitude of helper or extra methods for special purposes, such as
71 Drag'n'Drop, managing validators etc.
72
73 Normally one might expect, that one wxWindows class would always contain
74 one GTK widget. Under GTK, there is no such allround widget that has all
75 the functionality. Moreover, the GTK defines a client area as a different
76 widget from the actual widget you are handling. Last but not least some
77 special classes (e.g. wxFrame) handle different categories of widgets and
78 still have the possibility to draw something in the client area.
79 It was therefore required to write a special purpose GTK widget, that would
80 represent a client area in the sense of wxWindows capable to do the jobs
81 2), 3) and 4). I have written this class and it resides in win_gtk.c of
82 this directory.
83
84 All windows must have a widget, with which they interact with other under-
85 lying GTK widget. It is this widget, e.g. that has to be resized etc and
86 thw wxWindow class has a member variable called m_widget which holds a
87 pointer to this widget. When the window class displays a GTK native widget,
88 this is the only GTK widget the class manages. When the class has a client
89 area for drawing into and for containing children it must have at least
90 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
91 but there can be any number of widgets, handled by a class (e.g. the frame
92 class handles three). The common rule for all windows is only, that the
93 widget that interacts with the rest of GTK must be referenced in m_widget
94 and all other widgets must be children of this widget on the GTK level.
95 The top-most widget, which also represents the client area, must be in
96 the m_wxwindow field and must be of 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, GdkEvent *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 win->GetDropTarget()->Drop( event, x, y );
854 }
855
856 /*
857 g_free (event->dropdataavailable.data);
858 g_free (event->dropdataavailable.data_type);
859 */
860 }
861
862 //-----------------------------------------------------------------------------
863 // wxWindow
864 //-----------------------------------------------------------------------------
865
866 IMPLEMENT_DYNAMIC_CLASS(wxWindow,wxEvtHandler)
867
868 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
869 EVT_SIZE(wxWindow::OnSize)
870 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
871 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
872 EVT_IDLE(wxWindow::OnIdle)
873 END_EVENT_TABLE()
874
875 wxWindow::wxWindow()
876 {
877 m_widget = (GtkWidget *) NULL;
878 m_wxwindow = (GtkWidget *) NULL;
879 m_parent = (wxWindow *) NULL;
880 m_children.DeleteContents( FALSE );
881 m_x = 0;
882 m_y = 0;
883 m_width = 0;
884 m_height = 0;
885 m_minWidth = -1;
886 m_minHeight = -1;
887 m_maxWidth = -1;
888 m_maxHeight = -1;
889 m_retCode = 0;
890 m_eventHandler = this;
891 m_windowValidator = (wxValidator *) NULL;
892 m_windowId = -1;
893 m_cursor = (wxCursor *) NULL;
894 m_font = *wxSWISS_FONT;
895 m_windowStyle = 0;
896 m_windowName = "noname";
897 m_constraints = (wxLayoutConstraints *) NULL;
898 m_constraintsInvolvedIn = (wxList *) NULL;
899 m_windowSizer = (wxSizer *) NULL;
900 m_sizerParent = (wxWindow *) NULL;
901 m_autoLayout = FALSE;
902 m_sizeSet = FALSE;
903 m_hasVMT = FALSE;
904 m_needParent = TRUE;
905 m_hasScrolling = FALSE;
906 m_isScrolling = FALSE;
907 m_hAdjust = (GtkAdjustment *) NULL;
908 m_vAdjust = (GtkAdjustment *) NULL;
909 m_oldHorizontalPos = 0.0;
910 m_oldVerticalPos = 0.0;
911 m_isShown = FALSE;
912 m_isEnabled = TRUE;
913 m_pDropTarget = (wxDropTarget *) NULL;
914 m_resizing = FALSE;
915 m_scrollGC = (GdkGC*) NULL;
916 m_widgetStyle = (GtkStyle*) NULL;
917 }
918
919 bool wxWindow::Create( wxWindow *parent, wxWindowID id,
920 const wxPoint &pos, const wxSize &size,
921 long style, const wxString &name )
922 {
923 m_isShown = FALSE;
924 m_isEnabled = TRUE;
925 m_needParent = TRUE;
926
927 m_cursor = (wxCursor *) NULL;
928
929 PreCreation( parent, id, pos, size, style, name );
930
931 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
932 m_hasScrolling = TRUE;
933
934 GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
935
936 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_press_event",
937 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
938
939 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_press_event",
940 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
941
942 gtk_signal_connect( GTK_OBJECT(s_window->vscrollbar), "button_release_event",
943 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
944
945 gtk_signal_connect( GTK_OBJECT(s_window->hscrollbar), "button_release_event",
946 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
947
948 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
949 scroll_class->scrollbar_spacing = 0;
950
951 gtk_scrolled_window_set_policy( s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
952
953 m_oldHorizontalPos = 0.0;
954 m_oldVerticalPos = 0.0;
955
956 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->hscrollbar) );
957 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(s_window->vscrollbar) );
958
959 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
960 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
961 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
962 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
963
964 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
965 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
966 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
967 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
968
969 GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
970
971 if (m_windowStyle & wxRAISED_BORDER)
972 {
973 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
974 }
975 else if (m_windowStyle & wxSUNKEN_BORDER)
976 {
977 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
978 }
979 else
980 {
981 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
982 }
983
984 m_wxwindow = gtk_myfixed_new();
985
986 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
987
988 if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
989 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
990 else
991 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
992
993 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
994
995 // shut the viewport up
996 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
997 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
998
999 // I _really_ don't want scrollbars in the beginning
1000 m_vAdjust->lower = 0.0;
1001 m_vAdjust->upper = 1.0;
1002 m_vAdjust->value = 0.0;
1003 m_vAdjust->step_increment = 1.0;
1004 m_vAdjust->page_increment = 1.0;
1005 m_vAdjust->page_size = 5.0;
1006 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1007 m_hAdjust->lower = 0.0;
1008 m_hAdjust->upper = 1.0;
1009 m_hAdjust->value = 0.0;
1010 m_hAdjust->step_increment = 1.0;
1011 m_hAdjust->page_increment = 1.0;
1012 m_hAdjust->page_size = 5.0;
1013 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
1014
1015 gtk_widget_show( m_wxwindow );
1016
1017 PostCreation();
1018
1019 Show( TRUE );
1020
1021 return TRUE;
1022 }
1023
1024 wxWindow::~wxWindow()
1025 {
1026 m_hasVMT = FALSE;
1027
1028 if (m_pDropTarget) delete m_pDropTarget;
1029
1030 if (m_parent) m_parent->RemoveChild( this );
1031 if (m_widget) Show( FALSE );
1032
1033 DestroyChildren();
1034
1035 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
1036
1037 if (m_scrollGC) gdk_gc_unref( m_scrollGC );
1038
1039 if (m_wxwindow) gtk_widget_destroy( m_wxwindow );
1040
1041 if (m_widget) gtk_widget_destroy( m_widget );
1042
1043 wxDELETE(m_cursor);
1044
1045 DeleteRelatedConstraints();
1046 if (m_constraints)
1047 {
1048 // This removes any dangling pointers to this window
1049 // in other windows' constraintsInvolvedIn lists.
1050 UnsetConstraints(m_constraints);
1051 delete m_constraints;
1052 m_constraints = (wxLayoutConstraints *) NULL;
1053 }
1054 if (m_windowSizer)
1055 {
1056 delete m_windowSizer;
1057 m_windowSizer = (wxSizer *) NULL;
1058 }
1059 // If this is a child of a sizer, remove self from parent
1060 if (m_sizerParent) m_sizerParent->RemoveChild((wxWindow *)this);
1061
1062 // Just in case the window has been Closed, but
1063 // we're then deleting immediately: don't leave
1064 // dangling pointers.
1065 wxPendingDelete.DeleteObject(this);
1066
1067 // Just in case we've loaded a top-level window via
1068 // wxWindow::LoadNativeDialog but we weren't a dialog
1069 // class
1070 wxTopLevelWindows.DeleteObject(this);
1071
1072 if (m_windowValidator) delete m_windowValidator;
1073 }
1074
1075 void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
1076 const wxPoint &pos, const wxSize &size,
1077 long style, const wxString &name )
1078 {
1079 if (m_needParent && (parent == NULL))
1080 wxFatalError( "Need complete parent.", name );
1081
1082 m_widget = (GtkWidget *) NULL;
1083 m_hasVMT = FALSE;
1084 m_parent = parent;
1085 m_children.DeleteContents( FALSE );
1086 m_x = (int)pos.x;
1087 m_y = (int)pos.y;
1088 m_width = size.x;
1089 if (m_width == -1) m_width = 20;
1090 m_height = size.y;
1091 if (m_height == -1) m_height = 20;
1092 m_minWidth = -1;
1093 m_minHeight = -1;
1094 m_maxWidth = -1;
1095 m_maxHeight = -1;
1096 m_retCode = 0;
1097 m_eventHandler = this;
1098 m_windowId = id;
1099 m_sizeSet = FALSE;
1100 if (m_cursor == NULL)
1101 m_cursor = new wxCursor( wxCURSOR_ARROW );
1102 m_font = *wxSWISS_FONT;
1103 // m_backgroundColour = wxWHITE;
1104 m_foregroundColour = wxBLACK;
1105 m_windowStyle = style;
1106 m_windowName = name;
1107 m_constraints = (wxLayoutConstraints *) NULL;
1108 m_constraintsInvolvedIn = (wxList *) NULL;
1109 m_windowSizer = (wxSizer *) NULL;
1110 m_sizerParent = (wxWindow *) NULL;
1111 m_autoLayout = FALSE;
1112 m_hasScrolling = FALSE;
1113 m_isScrolling = FALSE;
1114 m_pDropTarget = (wxDropTarget *) NULL;
1115 m_resizing = FALSE;
1116 m_windowValidator = (wxValidator *) NULL;
1117 m_scrollGC = (GdkGC*) NULL;
1118 m_widgetStyle = (GtkStyle*) NULL;
1119 }
1120
1121 void wxWindow::PostCreation()
1122 {
1123 if (m_parent) m_parent->AddChild( this );
1124
1125 if (m_wxwindow)
1126 {
1127 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1128 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
1129
1130 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1131 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
1132 }
1133
1134 ConnectWidget( GetConnectWidget() );
1135
1136 if (m_widget && m_parent) gtk_widget_realize( m_widget );
1137
1138 if (m_wxwindow) gtk_widget_realize( m_wxwindow );
1139
1140 SetCursor( *wxSTANDARD_CURSOR );
1141
1142 m_hasVMT = TRUE;
1143 }
1144
1145 void wxWindow::ConnectWidget( GtkWidget *widget )
1146 {
1147 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1148 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
1149
1150 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1151 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
1152
1153 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1154 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
1155
1156 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1157 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
1158
1159 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1160 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
1161
1162 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1163 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
1164
1165 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1166 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
1167
1168 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1169 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
1170 }
1171
1172 bool wxWindow::HasVMT()
1173 {
1174 return m_hasVMT;
1175 }
1176
1177 bool wxWindow::Close( bool force )
1178 {
1179 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1180
1181 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1182 event.SetEventObject(this);
1183 event.SetForce(force);
1184
1185 return GetEventHandler()->ProcessEvent(event);
1186 }
1187
1188 bool wxWindow::Destroy()
1189 {
1190 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1191
1192 m_hasVMT = FALSE;
1193 delete this;
1194 return TRUE;
1195 }
1196
1197 bool wxWindow::DestroyChildren()
1198 {
1199 if (GetChildren())
1200 {
1201 wxNode *node;
1202 while ((node = GetChildren()->First()) != (wxNode *)NULL)
1203 {
1204 wxWindow *child;
1205 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL)
1206 {
1207 delete child;
1208 if (GetChildren()->Member(child)) delete node;
1209 }
1210 }
1211 }
1212 return TRUE;
1213 }
1214
1215 void wxWindow::PrepareDC( wxDC &WXUNUSED(dc) )
1216 {
1217 // are we to set fonts here ?
1218 }
1219
1220 void wxWindow::ImplementSetSize()
1221 {
1222 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1223 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
1224 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
1225 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
1226 gtk_widget_set_usize( m_widget, m_width, m_height );
1227 }
1228
1229 void wxWindow::ImplementSetPosition()
1230 {
1231 if (IS_KIND_OF(this,wxFrame) || IS_KIND_OF(this,wxDialog))
1232 {
1233 if ((m_x != -1) || (m_y != -1))
1234 gtk_widget_set_uposition( m_widget, m_x, m_y );
1235 return;
1236 }
1237
1238 if (!m_parent)
1239 {
1240 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1241 return;
1242 }
1243
1244 if ((m_parent) && (m_parent->m_wxwindow))
1245 gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x, m_y );
1246
1247 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1248 }
1249
1250 void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
1251 {
1252 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1253
1254 if (m_resizing) return; // I don't like recursions
1255 m_resizing = TRUE;
1256
1257 int newX = x;
1258 int newY = y;
1259 int newW = width;
1260 int newH = height;
1261
1262 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1263 {
1264 if (newX == -1) newX = m_x;
1265 if (newY == -1) newY = m_y;
1266 if (newW == -1) newW = m_width;
1267 if (newH == -1) newH = m_height;
1268 }
1269
1270 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1271 {
1272 if (newW == -1) newW = 80;
1273 }
1274
1275 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1276 {
1277 if (newH == -1) newH = 26;
1278 }
1279
1280 if ((m_x != newX) || (m_y != newY) || (!m_sizeSet))
1281 {
1282 m_x = newX;
1283 m_y = newY;
1284 ImplementSetPosition();
1285 }
1286 if ((m_width != newW) || (m_height != newH) || (!m_sizeSet))
1287 {
1288 m_width = newW;
1289 m_height = newH;
1290 ImplementSetSize();
1291 }
1292 m_sizeSet = TRUE;
1293
1294 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1295 event.SetEventObject( this );
1296 ProcessEvent( event );
1297
1298 m_resizing = FALSE;
1299 }
1300
1301 void wxWindow::SetSize( int width, int height )
1302 {
1303 SetSize( -1, -1, width, height, wxSIZE_USE_EXISTING );
1304 }
1305
1306 void wxWindow::Move( int x, int y )
1307 {
1308 SetSize( x, y, -1, -1, wxSIZE_USE_EXISTING );
1309 }
1310
1311 void wxWindow::GetSize( int *width, int *height ) const
1312 {
1313 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1314
1315 if (width) (*width) = m_width;
1316 if (height) (*height) = m_height;
1317 }
1318
1319 void wxWindow::SetClientSize( int width, int height )
1320 {
1321 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1322
1323 if (!m_wxwindow)
1324 {
1325 SetSize( width, height );
1326 }
1327 else
1328 {
1329 int dw = 0;
1330 int dh = 0;
1331
1332 if (!m_hasScrolling)
1333 {
1334 /*
1335 do we have sunken dialogs ?
1336
1337 GtkStyleClass *window_class = m_wxwindow->style->klass;
1338
1339 dw += 2 * window_class->xthickness;
1340 dh += 2 * window_class->ythickness;
1341 */
1342 }
1343 else
1344 {
1345 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1346 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1347
1348 GtkWidget *viewport = scroll_window->viewport;
1349 GtkStyleClass *viewport_class = viewport->style->klass;
1350
1351 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1352 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1353
1354 if ((m_windowStyle & wxRAISED_BORDER) ||
1355 (m_windowStyle & wxSUNKEN_BORDER))
1356 {
1357 dw += 2 * viewport_class->xthickness;
1358 dh += 2 * viewport_class->ythickness;
1359 }
1360
1361 if (GTK_WIDGET_VISIBLE(vscrollbar))
1362 {
1363 dw += vscrollbar->allocation.width;
1364 dw += scroll_class->scrollbar_spacing;
1365 }
1366
1367 if (GTK_WIDGET_VISIBLE(hscrollbar))
1368 {
1369 dh += hscrollbar->allocation.height;
1370 dw += scroll_class->scrollbar_spacing;
1371 }
1372 }
1373
1374 SetSize( width+dw, height+dh );
1375 }
1376 }
1377
1378 void wxWindow::GetClientSize( int *width, int *height ) const
1379 {
1380 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1381
1382 if (!m_wxwindow)
1383 {
1384 if (width) (*width) = m_width;
1385 if (height) (*height) = m_height;
1386 }
1387 else
1388 {
1389 int dw = 0;
1390 int dh = 0;
1391
1392 if (!m_hasScrolling)
1393 {
1394 /*
1395 do we have sunken dialogs ?
1396
1397 GtkStyleClass *window_class = m_wxwindow->style->klass;
1398
1399 dw += 2 * window_class->xthickness;
1400 dh += 2 * window_class->ythickness;
1401 */
1402 }
1403 else
1404 {
1405 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1406 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1407
1408 GtkWidget *viewport = scroll_window->viewport;
1409 GtkStyleClass *viewport_class = viewport->style->klass;
1410
1411 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1412 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1413
1414 if ((m_windowStyle & wxRAISED_BORDER) ||
1415 (m_windowStyle & wxSUNKEN_BORDER))
1416 {
1417 dw += 2 * viewport_class->xthickness;
1418 dh += 2 * viewport_class->ythickness;
1419 }
1420
1421 if (GTK_WIDGET_VISIBLE(vscrollbar))
1422 {
1423 // dw += vscrollbar->allocation.width;
1424 dw += 15; // range.slider_width = 11 + 2*2pts edge
1425 dw += scroll_class->scrollbar_spacing;
1426 }
1427
1428 if (GTK_WIDGET_VISIBLE(hscrollbar))
1429 {
1430 // dh += hscrollbar->allocation.height;
1431 dh += 15;
1432 dh += scroll_class->scrollbar_spacing;
1433 }
1434 }
1435
1436 if (width) (*width) = m_width - dw;
1437 if (height) (*height) = m_height - dh;
1438 }
1439 }
1440
1441 void wxWindow::GetPosition( int *x, int *y ) const
1442 {
1443 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1444
1445 if (x) (*x) = m_x;
1446 if (y) (*y) = m_y;
1447 }
1448
1449 void wxWindow::ClientToScreen( int *x, int *y )
1450 {
1451 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1452
1453 GdkWindow *source = (GdkWindow *) NULL;
1454 if (m_wxwindow)
1455 source = m_wxwindow->window;
1456 else
1457 source = m_widget->window;
1458
1459 int org_x = 0;
1460 int org_y = 0;
1461 gdk_window_get_origin( source, &org_x, &org_y );
1462
1463 if (!m_wxwindow)
1464 {
1465 if (GTK_WIDGET_NO_WINDOW (m_widget))
1466 {
1467 org_x += m_widget->allocation.x;
1468 org_y += m_widget->allocation.y;
1469 }
1470 }
1471
1472 if (x) *x += org_x;
1473 if (y) *y += org_y;
1474 }
1475
1476 void wxWindow::ScreenToClient( int *x, int *y )
1477 {
1478 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1479
1480 GdkWindow *source = (GdkWindow *) NULL;
1481 if (m_wxwindow)
1482 source = m_wxwindow->window;
1483 else
1484 source = m_widget->window;
1485
1486 int org_x = 0;
1487 int org_y = 0;
1488 gdk_window_get_origin( source, &org_x, &org_y );
1489
1490 if (!m_wxwindow)
1491 {
1492 if (GTK_WIDGET_NO_WINDOW (m_widget))
1493 {
1494 org_x += m_widget->allocation.x;
1495 org_y += m_widget->allocation.y;
1496 }
1497 }
1498
1499 if (x) *x -= org_x;
1500 if (y) *y -= org_y;
1501 }
1502
1503 void wxWindow::Centre( int direction )
1504 {
1505 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1506
1507 if (IS_KIND_OF(this,wxDialog) || IS_KIND_OF(this,wxFrame))
1508 {
1509 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
1510 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
1511 ImplementSetPosition();
1512 }
1513 else
1514 {
1515 if (m_parent)
1516 {
1517 int p_w = 0;
1518 int p_h = 0;
1519 m_parent->GetSize( &p_w, &p_h );
1520 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (p_w - m_width) / 2;
1521 if (direction & wxVERTICAL == wxVERTICAL) m_y = (p_h - m_height) / 2;
1522 ImplementSetPosition();
1523 }
1524 }
1525 }
1526
1527 void wxWindow::Fit()
1528 {
1529 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1530
1531 int maxX = 0;
1532 int maxY = 0;
1533 wxNode *node = GetChildren()->First();
1534 while ( node )
1535 {
1536 wxWindow *win = (wxWindow *)node->Data();
1537 int wx, wy, ww, wh;
1538 win->GetPosition(&wx, &wy);
1539 win->GetSize(&ww, &wh);
1540 if ( wx + ww > maxX )
1541 maxX = wx + ww;
1542 if ( wy + wh > maxY )
1543 maxY = wy + wh;
1544
1545 node = node->Next();
1546 }
1547 SetClientSize(maxX + 5, maxY + 10);
1548 }
1549
1550 void wxWindow::SetSizeHints( int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH) )
1551 {
1552 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1553
1554 m_minWidth = minW;
1555 m_minHeight = minH;
1556 m_maxWidth = maxW;
1557 m_maxHeight = maxH;
1558 }
1559
1560 void wxWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
1561 {
1562 //if (GetAutoLayout()) Layout();
1563 }
1564
1565 bool wxWindow::Show( bool show )
1566 {
1567 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1568
1569 if (show)
1570 gtk_widget_show( m_widget );
1571 else
1572 gtk_widget_hide( m_widget );
1573 m_isShown = show;
1574 return TRUE;
1575 }
1576
1577 void wxWindow::Enable( bool enable )
1578 {
1579 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1580
1581 m_isEnabled = enable;
1582 gtk_widget_set_sensitive( m_widget, enable );
1583 if (m_wxwindow) gtk_widget_set_sensitive( m_wxwindow, enable );
1584 }
1585
1586 int wxWindow::GetCharHeight() const
1587 {
1588 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1589
1590 if (!m_font.Ok())
1591 {
1592 wxFAIL_MSG( "invalid font" );
1593 return -1;
1594 }
1595
1596 GdkFont *font = m_font.GetInternalFont( 1.0 );
1597 return font->ascent + font->descent;
1598 }
1599
1600 int wxWindow::GetCharWidth() const
1601 {
1602 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1603
1604 if (!m_font.Ok())
1605 {
1606 wxFAIL_MSG( "invalid font" );
1607 return -1;
1608 }
1609
1610 GdkFont *font = m_font.GetInternalFont( 1.0 );
1611 return gdk_string_width( font, "H" );
1612 }
1613
1614 void wxWindow::GetTextExtent( const wxString& string, int *x, int *y,
1615 int *descent, int *externalLeading, const wxFont *theFont, bool WXUNUSED(use16) ) const
1616 {
1617 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1618
1619 wxFont fontToUse = m_font;
1620 if (theFont) fontToUse = *theFont;
1621
1622 if (!fontToUse.Ok())
1623 {
1624 wxFAIL_MSG( "invalid font" );
1625 return;
1626 }
1627 wxASSERT_MSG( (m_font.Ok()), "invalid font" );
1628
1629 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
1630 if (x) (*x) = gdk_string_width( font, string );
1631 if (y) (*y) = font->ascent + font->descent;
1632 if (descent) (*descent) = font->descent;
1633 if (externalLeading) (*externalLeading) = 0; // ??
1634 }
1635
1636 void wxWindow::MakeModal( bool modal )
1637 {
1638 return;
1639 // Disable all other windows
1640 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
1641 {
1642 wxNode *node = wxTopLevelWindows.First();
1643 while (node)
1644 {
1645 wxWindow *win = (wxWindow *)node->Data();
1646 if (win != this)
1647 win->Enable(!modal);
1648
1649 node = node->Next();
1650 }
1651 }
1652 }
1653
1654 void wxWindow::SetFocus()
1655 {
1656 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1657
1658 GtkWidget *connect_widget = GetConnectWidget();
1659 if (connect_widget)
1660 {
1661 if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
1662 {
1663 gtk_widget_grab_focus (connect_widget);
1664 }
1665 }
1666 }
1667
1668 bool wxWindow::OnClose()
1669 {
1670 return TRUE;
1671 }
1672
1673 void wxWindow::AddChild( wxWindow *child )
1674 {
1675 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1676 wxASSERT_MSG( (m_wxwindow != NULL), "window need client area" );
1677 wxASSERT_MSG( (child != NULL), "invalid child" );
1678 wxASSERT_MSG( (child->m_widget != NULL), "invalid child" );
1679
1680 // Addchild is (often) called before the program
1681 // has left the parents constructor so that no
1682 // virtual tables work yet. The approach below
1683 // practically imitates virtual tables, i.e. it
1684 // implements a different AddChild() behaviour
1685 // for wxFrame, wxDialog, wxWindow and
1686 // wxMDIParentFrame.
1687
1688 // wxFrame and wxDialog as children aren't placed into the parents
1689
1690 if (( IS_KIND_OF(child,wxFrame) || IS_KIND_OF(child,wxDialog) ) &&
1691 (!IS_KIND_OF(child,wxMDIChildFrame)))
1692 {
1693 m_children.Append( child );
1694
1695 if ((child->m_x != -1) && (child->m_y != -1))
1696 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
1697
1698 return;
1699 }
1700
1701 // In the case of an wxMDIChildFrame descendant, we use the
1702 // client windows's AddChild()
1703
1704 if (IS_KIND_OF(this,wxMDIParentFrame))
1705 {
1706 if (IS_KIND_OF(child,wxMDIChildFrame))
1707 {
1708 wxMDIClientWindow *client = ((wxMDIParentFrame*)this)->GetClientWindow();
1709 if (client)
1710 {
1711 client->AddChild( child );
1712 return;
1713 }
1714 }
1715 }
1716
1717 // wxNotebook is very special, so it has a private AddChild()
1718
1719 if (IS_KIND_OF(this,wxNotebook))
1720 {
1721 wxNotebook *tab = (wxNotebook*)this;
1722 tab->AddChild( child );
1723 return;
1724 }
1725
1726 // wxFrame has a private AddChild
1727
1728 if (IS_KIND_OF(this,wxFrame) && !IS_KIND_OF(this,wxMDIChildFrame))
1729 {
1730 wxFrame *frame = (wxFrame*)this;
1731 frame->AddChild( child );
1732 return;
1733 }
1734
1735 // All the rest
1736
1737 m_children.Append( child );
1738 if (m_wxwindow) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget,
1739 child->m_x, child->m_y );
1740
1741 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
1742 }
1743
1744 wxList *wxWindow::GetChildren()
1745 {
1746 return (&m_children);
1747 }
1748
1749 void wxWindow::RemoveChild( wxWindow *child )
1750 {
1751 if (GetChildren())
1752 GetChildren()->DeleteObject( child );
1753 child->m_parent = (wxWindow *) NULL;
1754 }
1755
1756 void wxWindow::SetReturnCode( int retCode )
1757 {
1758 m_retCode = retCode;
1759 }
1760
1761 int wxWindow::GetReturnCode()
1762 {
1763 return m_retCode;
1764 }
1765
1766 void wxWindow::Raise()
1767 {
1768 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1769
1770 if (m_widget) gdk_window_raise( m_widget->window );
1771 }
1772
1773 void wxWindow::Lower()
1774 {
1775 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1776
1777 if (m_widget) gdk_window_lower( m_widget->window );
1778 }
1779
1780 wxEvtHandler *wxWindow::GetEventHandler()
1781 {
1782 return m_eventHandler;
1783 }
1784
1785 void wxWindow::SetEventHandler( wxEvtHandler *handler )
1786 {
1787 m_eventHandler = handler;
1788 }
1789
1790 void wxWindow::PushEventHandler(wxEvtHandler *handler)
1791 {
1792 handler->SetNextHandler(GetEventHandler());
1793 SetEventHandler(handler);
1794 }
1795
1796 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
1797 {
1798 if (GetEventHandler())
1799 {
1800 wxEvtHandler *handlerA = GetEventHandler();
1801 wxEvtHandler *handlerB = handlerA->GetNextHandler();
1802 handlerA->SetNextHandler((wxEvtHandler *) NULL);
1803 SetEventHandler(handlerB);
1804 if (deleteHandler)
1805 {
1806 delete handlerA;
1807 return (wxEvtHandler*) NULL;
1808 }
1809 else
1810 return handlerA;
1811 }
1812 else
1813 return (wxEvtHandler *) NULL;
1814 }
1815
1816 wxValidator *wxWindow::GetValidator()
1817 {
1818 return m_windowValidator;
1819 }
1820
1821 void wxWindow::SetValidator( const wxValidator& validator )
1822 {
1823 if (m_windowValidator) delete m_windowValidator;
1824 m_windowValidator = validator.Clone();
1825 if (m_windowValidator) m_windowValidator->SetWindow(this);
1826 }
1827
1828 bool wxWindow::IsBeingDeleted()
1829 {
1830 return FALSE;
1831 }
1832
1833 void wxWindow::SetId( wxWindowID id )
1834 {
1835 m_windowId = id;
1836 }
1837
1838 wxWindowID wxWindow::GetId()
1839 {
1840 return m_windowId;
1841 }
1842
1843 void wxWindow::SetCursor( const wxCursor &cursor )
1844 {
1845 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1846
1847 if (m_cursor == NULL)
1848 {
1849 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1850 m_cursor = new wxCursor( wxCURSOR_ARROW );
1851 }
1852
1853 if (cursor.Ok())
1854 {
1855 if (*((wxCursor*)&cursor) == m_cursor) return;
1856 *m_cursor = cursor;
1857 }
1858 else
1859 {
1860 *m_cursor = *wxSTANDARD_CURSOR;
1861 }
1862
1863 if ((m_widget) && (m_widget->window))
1864 gdk_window_set_cursor( m_widget->window, m_cursor->GetCursor() );
1865
1866 if ((m_wxwindow) && (m_wxwindow->window))
1867 gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
1868 }
1869
1870 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
1871 {
1872 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
1873
1874 if (eraseBackground && m_wxwindow && m_wxwindow->window)
1875 {
1876 if (rect)
1877 gdk_window_clear_area( m_wxwindow->window,
1878 rect->x,
1879 rect->y,
1880 rect->width,
1881 rect->height );
1882 else
1883 Clear();
1884 }
1885 if (!rect)
1886 {
1887 if (m_wxwindow)
1888 {
1889 int w = 0;
1890 int h = 0;
1891 GetClientSize( &w, &h );
1892
1893 GdkRectangle gdk_rect;
1894 gdk_rect.x = 0;
1895 gdk_rect.y = 0;
1896 gdk_rect.width = w;
1897 gdk_rect.height = h;
1898 gtk_widget_draw( m_wxwindow, &gdk_rect );
1899 }
1900 }
1901 else
1902 {
1903 GdkRectangle gdk_rect;
1904 gdk_rect.x = rect->x;
1905 gdk_rect.y = rect->y;
1906 gdk_rect.width = rect->width;
1907 gdk_rect.height = rect->height;
1908
1909 if (m_wxwindow)
1910 gtk_widget_draw( m_wxwindow, &gdk_rect );
1911 else
1912 gtk_widget_draw( m_widget, &gdk_rect );
1913 }
1914 }
1915
1916 wxRegion wxWindow::GetUpdateRegion() const
1917 {
1918 return m_updateRegion;
1919 }
1920
1921 bool wxWindow::IsExposed( int x, int y) const
1922 {
1923 return (m_updateRegion.Contains( x, y ) != wxOutRegion );
1924 }
1925
1926 bool wxWindow::IsExposed( int x, int y, int w, int h ) const
1927 {
1928 return (m_updateRegion.Contains( x, y, w, h ) != wxOutRegion );
1929 }
1930
1931 bool wxWindow::IsExposed( const wxPoint& pt ) const
1932 {
1933 return (m_updateRegion.Contains( pt.x, pt.y ) != wxOutRegion );
1934 }
1935
1936 bool wxWindow::IsExposed( const wxRect& rect ) const
1937 {
1938 return (m_updateRegion.Contains( rect.x, rect.y, rect.width, rect.height ) != wxOutRegion );
1939 }
1940
1941 void wxWindow::Clear()
1942 {
1943 wxCHECK_RET( m_widget != NULL, "invalid window" );
1944
1945 if (m_wxwindow && m_wxwindow->window) gdk_window_clear( m_wxwindow->window );
1946 }
1947
1948 wxColour wxWindow::GetBackgroundColour() const
1949 {
1950 return m_backgroundColour;
1951 }
1952
1953 void wxWindow::SetBackgroundColour( const wxColour &colour )
1954 {
1955 wxCHECK_RET( m_widget != NULL, "invalid window" );
1956
1957 m_backgroundColour = colour;
1958 if (!m_backgroundColour.Ok()) return;
1959
1960 if (m_wxwindow)
1961 {
1962 GdkWindow *window = m_wxwindow->window;
1963 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
1964 gdk_window_set_background( window, m_backgroundColour.GetColor() );
1965 gdk_window_clear( window );
1966 }
1967 else
1968 {
1969 GtkStyle *style = GetWidgetStyle();
1970 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
1971 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
1972 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
1973 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
1974 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
1975 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
1976 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
1977 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
1978 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
1979 }
1980 }
1981
1982 wxColour wxWindow::GetForegroundColour() const
1983 {
1984 return m_foregroundColour;
1985 }
1986
1987 void wxWindow::SetForegroundColour( const wxColour &colour )
1988 {
1989 wxCHECK_RET( m_widget != NULL, "invalid window" );
1990
1991 m_foregroundColour = colour;
1992 if (!m_foregroundColour.Ok()) return;
1993
1994 if (!m_wxwindow)
1995 {
1996 GtkStyle *style = GetWidgetStyle();
1997 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
1998 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
1999 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2000 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2001 }
2002 }
2003
2004 GtkStyle *wxWindow::GetWidgetStyle()
2005 {
2006 if (!m_widgetStyle)
2007 m_widgetStyle =
2008 gtk_style_copy(
2009 gtk_widget_get_style( m_widget ) );
2010 return m_widgetStyle;
2011 }
2012
2013 bool wxWindow::Validate()
2014 {
2015 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2016
2017 wxNode *node = GetChildren()->First();
2018 while (node)
2019 {
2020 wxWindow *child = (wxWindow *)node->Data();
2021 if (child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this))
2022 { return FALSE; }
2023 node = node->Next();
2024 }
2025 return TRUE;
2026 }
2027
2028 bool wxWindow::TransferDataToWindow()
2029 {
2030 wxCHECK_MSG( m_widget != NULL, FALSE, "invalid window" );
2031
2032 wxNode *node = GetChildren()->First();
2033 while (node)
2034 {
2035 wxWindow *child = (wxWindow *)node->Data();
2036 if (child->GetValidator() && /* child->GetValidator()->Ok() && */
2037 !child->GetValidator()->TransferToWindow() )
2038 {
2039 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK|wxICON_EXCLAMATION );
2040 return FALSE;
2041 }
2042 node = node->Next();
2043 }
2044 return TRUE;
2045 }
2046
2047 bool wxWindow::TransferDataFromWindow()
2048 {
2049 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2050
2051 wxNode *node = GetChildren()->First();
2052 while (node)
2053 {
2054 wxWindow *child = (wxWindow *)node->Data();
2055 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
2056 { return FALSE; }
2057 node = node->Next();
2058 }
2059 return TRUE;
2060 }
2061
2062 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable& accel )
2063 {
2064 m_acceleratorTable = accel;
2065 }
2066
2067 void wxWindow::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
2068 {
2069 TransferDataToWindow();
2070 }
2071
2072 void wxWindow::InitDialog()
2073 {
2074 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2075
2076 wxInitDialogEvent event(GetId());
2077 event.SetEventObject( this );
2078 GetEventHandler()->ProcessEvent(event);
2079 }
2080
2081 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2082 {
2083 menu->SetInvokingWindow( win );
2084 wxNode *node = menu->m_items.First();
2085 while (node)
2086 {
2087 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2088 if (menuitem->IsSubMenu())
2089 SetInvokingWindow( menuitem->GetSubMenu(), win );
2090 node = node->Next();
2091 }
2092 }
2093
2094 bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
2095 {
2096 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2097
2098 SetInvokingWindow( menu, this );
2099 gtk_menu_popup(
2100 GTK_MENU(menu->m_menu),
2101 (GtkWidget *)NULL, // parent menu shell
2102 (GtkWidget *)NULL, // parent menu item
2103 (GtkMenuPositionFunc)NULL,
2104 NULL, // client data
2105 0, // button used to activate it
2106 0//gs_timeLastClick // the time of activation
2107 );
2108 return TRUE;
2109 }
2110
2111 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2112 {
2113 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2114
2115 GtkWidget *dnd_widget = GetConnectWidget();
2116
2117 DisconnectDnDWidget( dnd_widget );
2118
2119 if (m_pDropTarget) delete m_pDropTarget;
2120 m_pDropTarget = dropTarget;
2121
2122 ConnectDnDWidget( dnd_widget );
2123 }
2124
2125 wxDropTarget *wxWindow::GetDropTarget() const
2126 {
2127 return m_pDropTarget;
2128 }
2129
2130 void wxWindow::ConnectDnDWidget( GtkWidget *widget )
2131 {
2132 if (!m_pDropTarget) return;
2133
2134 m_pDropTarget->RegisterWidget( widget );
2135
2136 gtk_signal_connect( GTK_OBJECT(widget), "drop_data_available_event",
2137 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2138 }
2139
2140 void wxWindow::DisconnectDnDWidget( GtkWidget *widget )
2141 {
2142 if (!m_pDropTarget) return;
2143
2144 gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
2145 GTK_SIGNAL_FUNC(gtk_window_drop_callback), (gpointer)this );
2146
2147 m_pDropTarget->UnregisterWidget( widget );
2148 }
2149
2150 GtkWidget* wxWindow::GetConnectWidget()
2151 {
2152 GtkWidget *connect_widget = m_widget;
2153 if (m_wxwindow) connect_widget = m_wxwindow;
2154
2155 return connect_widget;
2156 }
2157
2158 bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2159 {
2160 if (m_wxwindow) return (window == m_wxwindow->window);
2161 return (window == m_widget->window);
2162 }
2163
2164 void wxWindow::SetFont( const wxFont &font )
2165 {
2166 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2167
2168 if (((wxFont*)&font)->Ok())
2169 m_font = font;
2170 else
2171 m_font = *wxSWISS_FONT;
2172
2173 GtkStyle *style = GetWidgetStyle();
2174 gdk_font_unref( style->font );
2175 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2176 }
2177
2178 wxFont *wxWindow::GetFont()
2179 {
2180 return &m_font;
2181 }
2182
2183 void wxWindow::SetWindowStyleFlag( long flag )
2184 {
2185 m_windowStyle = flag;
2186 }
2187
2188 long wxWindow::GetWindowStyleFlag() const
2189 {
2190 return m_windowStyle;
2191 }
2192
2193 void wxWindow::CaptureMouse()
2194 {
2195 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2196
2197 wxASSERT_MSG( (g_capturing == FALSE), "CaptureMouse called twice" );
2198
2199 GtkWidget *connect_widget = GetConnectWidget();
2200 gtk_grab_add( connect_widget );
2201 gdk_pointer_grab ( connect_widget->window, FALSE,
2202 (GdkEventMask)
2203 (GDK_BUTTON_PRESS_MASK |
2204 GDK_BUTTON_RELEASE_MASK |
2205 GDK_POINTER_MOTION_MASK),
2206 (GdkWindow *) NULL, (GdkCursor *) NULL, GDK_CURRENT_TIME );
2207 g_capturing = TRUE;
2208 }
2209
2210 void wxWindow::ReleaseMouse()
2211 {
2212 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2213
2214 wxASSERT_MSG( (g_capturing == TRUE), "ReleaseMouse called twice" );
2215
2216 GtkWidget *connect_widget = GetConnectWidget();
2217 gtk_grab_remove( connect_widget );
2218 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2219 g_capturing = FALSE;
2220 }
2221
2222 void wxWindow::SetTitle( const wxString &WXUNUSED(title) )
2223 {
2224 }
2225
2226 wxString wxWindow::GetTitle() const
2227 {
2228 return (wxString&)m_windowName;
2229 }
2230
2231 wxString wxWindow::GetLabel() const
2232 {
2233 return GetTitle();
2234 }
2235
2236 void wxWindow::SetName( const wxString &name )
2237 {
2238 m_windowName = name;
2239 }
2240
2241 wxString wxWindow::GetName() const
2242 {
2243 return (wxString&)m_windowName;
2244 }
2245
2246 bool wxWindow::IsShown() const
2247 {
2248 return m_isShown;
2249 }
2250
2251 bool wxWindow::IsRetained()
2252 {
2253 return FALSE;
2254 }
2255
2256 wxWindow *wxWindow::FindWindow( long id )
2257 {
2258 if (id == m_windowId) return this;
2259 wxNode *node = m_children.First();
2260 while (node)
2261 {
2262 wxWindow *child = (wxWindow*)node->Data();
2263 wxWindow *res = child->FindWindow( id );
2264 if (res) return res;
2265 node = node->Next();
2266 }
2267 return (wxWindow *) NULL;
2268 }
2269
2270 wxWindow *wxWindow::FindWindow( const wxString& name )
2271 {
2272 if (name == m_windowName) return this;
2273 wxNode *node = m_children.First();
2274 while (node)
2275 {
2276 wxWindow *child = (wxWindow*)node->Data();
2277 wxWindow *res = child->FindWindow( name );
2278 if (res) return res;
2279 node = node->Next();
2280 }
2281 return (wxWindow *) NULL;
2282 }
2283
2284 void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
2285 int range, bool refresh )
2286 {
2287 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2288
2289 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2290
2291 if (!m_wxwindow) return;
2292
2293 if (orient == wxHORIZONTAL)
2294 {
2295 float fpos = (float)pos;
2296 float frange = (float)range;
2297 float fthumb = (float)thumbVisible;
2298
2299 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2300 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2301 {
2302 SetScrollPos( orient, pos, refresh );
2303 return;
2304 }
2305
2306 m_oldHorizontalPos = fpos;
2307
2308 m_hAdjust->lower = 0.0;
2309 m_hAdjust->upper = frange;
2310 m_hAdjust->value = fpos;
2311 m_hAdjust->step_increment = 1.0;
2312 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2313 m_hAdjust->page_size = fthumb;
2314 }
2315 else
2316 {
2317 float fpos = (float)pos;
2318 float frange = (float)range;
2319 float fthumb = (float)thumbVisible;
2320
2321 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2322 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2323 {
2324 SetScrollPos( orient, pos, refresh );
2325 return;
2326 }
2327
2328 m_oldVerticalPos = fpos;
2329
2330 m_vAdjust->lower = 0.0;
2331 m_vAdjust->upper = frange;
2332 m_vAdjust->value = fpos;
2333 m_vAdjust->step_increment = 1.0;
2334 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2335 m_vAdjust->page_size = fthumb;
2336 }
2337
2338 if (m_wxwindow->window)
2339 {
2340 if (orient == wxHORIZONTAL)
2341 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2342 else
2343 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2344
2345 gtk_widget_set_usize( m_widget, m_width, m_height );
2346 }
2347 }
2348
2349 void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
2350 {
2351 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2352
2353 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2354
2355 if (!m_wxwindow) return;
2356
2357 if (orient == wxHORIZONTAL)
2358 {
2359 float fpos = (float)pos;
2360 m_oldHorizontalPos = fpos;
2361
2362 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2363 m_hAdjust->value = fpos;
2364 }
2365 else
2366 {
2367 float fpos = (float)pos;
2368 m_oldVerticalPos = fpos;
2369 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2370 m_vAdjust->value = fpos;
2371 }
2372
2373 if (!m_isScrolling)
2374 {
2375 if (m_wxwindow->window)
2376 {
2377 if (orient == wxHORIZONTAL)
2378 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2379 else
2380 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2381 }
2382 }
2383 }
2384
2385 int wxWindow::GetScrollThumb( int orient ) const
2386 {
2387 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2388
2389 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2390
2391 if (!m_wxwindow) return 0;
2392
2393 if (orient == wxHORIZONTAL)
2394 return (int)(m_hAdjust->page_size+0.5);
2395 else
2396 return (int)(m_vAdjust->page_size+0.5);
2397 }
2398
2399 int wxWindow::GetScrollPos( int orient ) const
2400 {
2401 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2402
2403 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2404
2405 if (!m_wxwindow) return 0;
2406
2407 if (orient == wxHORIZONTAL)
2408 return (int)(m_hAdjust->value+0.5);
2409 else
2410 return (int)(m_vAdjust->value+0.5);
2411 }
2412
2413 int wxWindow::GetScrollRange( int orient ) const
2414 {
2415 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2416
2417 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2418
2419 if (!m_wxwindow) return 0;
2420
2421 if (orient == wxHORIZONTAL)
2422 return (int)(m_hAdjust->upper+0.5);
2423 else
2424 return (int)(m_vAdjust->upper+0.5);
2425 }
2426
2427 void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
2428 {
2429 wxASSERT_MSG( (m_widget != NULL), "invalid window" );
2430
2431 wxASSERT_MSG( (m_wxwindow != NULL), "window needs client area" );
2432
2433 if (!m_wxwindow) return;
2434
2435 int cw = 0;
2436 int ch = 0;
2437 GetClientSize( &cw, &ch );
2438
2439 int w = cw - abs(dx);
2440 int h = ch - abs(dy);
2441 if ((h < 0) || (w < 0))
2442 {
2443 Refresh();
2444 return;
2445 }
2446 int s_x = 0;
2447 int s_y = 0;
2448 if (dx < 0) s_x = -dx;
2449 if (dy < 0) s_y = -dy;
2450 int d_x = 0;
2451 int d_y = 0;
2452 if (dx > 0) d_x = dx;
2453 if (dy > 0) d_y = dy;
2454
2455 if (!m_scrollGC)
2456 {
2457 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2458 gdk_gc_set_exposures( m_scrollGC, TRUE );
2459 }
2460
2461 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2462 m_wxwindow->window, s_x, s_y, w, h );
2463
2464 wxRect rect;
2465 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2466 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2467 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2468 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
2469
2470 Refresh( TRUE, &rect );
2471 }
2472
2473 //-------------------------------------------------------------------------------------
2474 // Layout
2475 //-------------------------------------------------------------------------------------
2476
2477 wxLayoutConstraints *wxWindow::GetConstraints() const
2478 {
2479 return m_constraints;
2480 }
2481
2482 void wxWindow::SetConstraints( wxLayoutConstraints *constraints )
2483 {
2484 if (m_constraints)
2485 {
2486 UnsetConstraints(m_constraints);
2487 delete m_constraints;
2488 }
2489 m_constraints = constraints;
2490 if (m_constraints)
2491 {
2492 // Make sure other windows know they're part of a 'meaningful relationship'
2493 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
2494 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2495 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
2496 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2497 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
2498 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2499 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
2500 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2501 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
2502 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2503 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
2504 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2505 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
2506 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2507 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
2508 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
2509 }
2510 ;
2511 }
2512 ;
2513
2514 void wxWindow::SetAutoLayout( bool autoLayout )
2515 {
2516 m_autoLayout = autoLayout;
2517 }
2518
2519 bool wxWindow::GetAutoLayout() const
2520 {
2521 return m_autoLayout;
2522 }
2523
2524 wxSizer *wxWindow::GetSizer() const
2525 {
2526 return m_windowSizer;
2527 }
2528
2529 void wxWindow::SetSizerParent( wxWindow *win )
2530 {
2531 m_sizerParent = win;
2532 }
2533
2534 wxWindow *wxWindow::GetSizerParent() const
2535 {
2536 return m_sizerParent;
2537 }
2538
2539 // This removes any dangling pointers to this window
2540 // in other windows' constraintsInvolvedIn lists.
2541 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
2542 {
2543 if (c)
2544 {
2545 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2546 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2547 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
2548 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2549 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
2550 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2551 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
2552 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2553 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
2554 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2555 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
2556 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2557 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
2558 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2559 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
2560 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
2561 }
2562 }
2563
2564 // Back-pointer to other windows we're involved with, so if we delete
2565 // this window, we must delete any constraints we're involved with.
2566 void wxWindow::AddConstraintReference(wxWindow *otherWin)
2567 {
2568 if (!m_constraintsInvolvedIn)
2569 m_constraintsInvolvedIn = new wxList;
2570 if (!m_constraintsInvolvedIn->Member(otherWin))
2571 m_constraintsInvolvedIn->Append(otherWin);
2572 }
2573
2574 // REMOVE back-pointer to other windows we're involved with.
2575 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
2576 {
2577 if (m_constraintsInvolvedIn)
2578 m_constraintsInvolvedIn->DeleteObject(otherWin);
2579 }
2580
2581 // Reset any constraints that mention this window
2582 void wxWindow::DeleteRelatedConstraints()
2583 {
2584 if (m_constraintsInvolvedIn)
2585 {
2586 wxNode *node = m_constraintsInvolvedIn->First();
2587 while (node)
2588 {
2589 wxWindow *win = (wxWindow *)node->Data();
2590 wxNode *next = node->Next();
2591 wxLayoutConstraints *constr = win->GetConstraints();
2592
2593 // Reset any constraints involving this window
2594 if (constr)
2595 {
2596 constr->left.ResetIfWin((wxWindow *)this);
2597 constr->top.ResetIfWin((wxWindow *)this);
2598 constr->right.ResetIfWin((wxWindow *)this);
2599 constr->bottom.ResetIfWin((wxWindow *)this);
2600 constr->width.ResetIfWin((wxWindow *)this);
2601 constr->height.ResetIfWin((wxWindow *)this);
2602 constr->centreX.ResetIfWin((wxWindow *)this);
2603 constr->centreY.ResetIfWin((wxWindow *)this);
2604 }
2605 delete node;
2606 node = next;
2607 }
2608 delete m_constraintsInvolvedIn;
2609 m_constraintsInvolvedIn = (wxList *) NULL;
2610 }
2611 }
2612
2613 void wxWindow::SetSizer(wxSizer *sizer)
2614 {
2615 m_windowSizer = sizer;
2616 if (sizer)
2617 sizer->SetSizerParent((wxWindow *)this);
2618 }
2619
2620 /*
2621 * New version
2622 */
2623
2624 bool wxWindow::Layout()
2625 {
2626 if (GetConstraints())
2627 {
2628 int w, h;
2629 GetClientSize(&w, &h);
2630 GetConstraints()->width.SetValue(w);
2631 GetConstraints()->height.SetValue(h);
2632 }
2633
2634 // If top level (one sizer), evaluate the sizer's constraints.
2635 if (GetSizer())
2636 {
2637 int noChanges;
2638 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2639 GetSizer()->LayoutPhase1(&noChanges);
2640 GetSizer()->LayoutPhase2(&noChanges);
2641 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2642 return TRUE;
2643 }
2644 else
2645 {
2646 // Otherwise, evaluate child constraints
2647 ResetConstraints(); // Mark all constraints as unevaluated
2648 DoPhase(1); // Just one phase need if no sizers involved
2649 DoPhase(2);
2650 SetConstraintSizes(); // Recursively set the real window sizes
2651 }
2652 return TRUE;
2653 }
2654
2655
2656 // Do a phase of evaluating constraints:
2657 // the default behaviour. wxSizers may do a similar
2658 // thing, but also impose their own 'constraints'
2659 // and order the evaluation differently.
2660 bool wxWindow::LayoutPhase1(int *noChanges)
2661 {
2662 wxLayoutConstraints *constr = GetConstraints();
2663 if (constr)
2664 {
2665 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
2666 }
2667 else
2668 return TRUE;
2669 }
2670
2671 bool wxWindow::LayoutPhase2(int *noChanges)
2672 {
2673 *noChanges = 0;
2674
2675 // Layout children
2676 DoPhase(1);
2677 DoPhase(2);
2678 return TRUE;
2679 }
2680
2681 // Do a phase of evaluating child constraints
2682 bool wxWindow::DoPhase(int phase)
2683 {
2684 int noIterations = 0;
2685 int maxIterations = 500;
2686 int noChanges = 1;
2687 int noFailures = 0;
2688 wxList succeeded;
2689 while ((noChanges > 0) && (noIterations < maxIterations))
2690 {
2691 noChanges = 0;
2692 noFailures = 0;
2693 wxNode *node = GetChildren()->First();
2694 while (node)
2695 {
2696 wxWindow *child = (wxWindow *)node->Data();
2697 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
2698 {
2699 wxLayoutConstraints *constr = child->GetConstraints();
2700 if (constr)
2701 {
2702 if (succeeded.Member(child))
2703 {
2704 }
2705 else
2706 {
2707 int tempNoChanges = 0;
2708 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
2709 noChanges += tempNoChanges;
2710 if (success)
2711 {
2712 succeeded.Append(child);
2713 }
2714 }
2715 }
2716 }
2717 node = node->Next();
2718 }
2719 noIterations ++;
2720 }
2721 return TRUE;
2722 }
2723
2724 void wxWindow::ResetConstraints()
2725 {
2726 wxLayoutConstraints *constr = GetConstraints();
2727 if (constr)
2728 {
2729 constr->left.SetDone(FALSE);
2730 constr->top.SetDone(FALSE);
2731 constr->right.SetDone(FALSE);
2732 constr->bottom.SetDone(FALSE);
2733 constr->width.SetDone(FALSE);
2734 constr->height.SetDone(FALSE);
2735 constr->centreX.SetDone(FALSE);
2736 constr->centreY.SetDone(FALSE);
2737 }
2738 wxNode *node = GetChildren()->First();
2739 while (node)
2740 {
2741 wxWindow *win = (wxWindow *)node->Data();
2742 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2743 win->ResetConstraints();
2744 node = node->Next();
2745 }
2746 }
2747
2748 // Need to distinguish between setting the 'fake' size for
2749 // windows and sizers, and setting the real values.
2750 void wxWindow::SetConstraintSizes(bool recurse)
2751 {
2752 wxLayoutConstraints *constr = GetConstraints();
2753 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
2754 constr->width.GetDone() && constr->height.GetDone())
2755 {
2756 int x = constr->left.GetValue();
2757 int y = constr->top.GetValue();
2758 int w = constr->width.GetValue();
2759 int h = constr->height.GetValue();
2760
2761 // If we don't want to resize this window, just move it...
2762 if ((constr->width.GetRelationship() != wxAsIs) ||
2763 (constr->height.GetRelationship() != wxAsIs))
2764 {
2765 // Calls Layout() recursively. AAAGH. How can we stop that.
2766 // Simply take Layout() out of non-top level OnSizes.
2767 SizerSetSize(x, y, w, h);
2768 }
2769 else
2770 {
2771 SizerMove(x, y);
2772 }
2773 }
2774 else if (constr)
2775 {
2776 char *windowClass = this->GetClassInfo()->GetClassName();
2777
2778 wxString winName;
2779 if (GetName() == "")
2780 winName = _("unnamed");
2781 else
2782 winName = GetName();
2783 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass, (const char *)winName);
2784 if (!constr->left.GetDone())
2785 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2786 if (!constr->right.GetDone())
2787 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2788 if (!constr->width.GetDone())
2789 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2790 if (!constr->height.GetDone())
2791 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2792 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2793 }
2794
2795 if (recurse)
2796 {
2797 wxNode *node = GetChildren()->First();
2798 while (node)
2799 {
2800 wxWindow *win = (wxWindow *)node->Data();
2801 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
2802 win->SetConstraintSizes();
2803 node = node->Next();
2804 }
2805 }
2806 }
2807
2808 // This assumes that all sizers are 'on' the same
2809 // window, i.e. the parent of this window.
2810 void wxWindow::TransformSizerToActual(int *x, int *y) const
2811 {
2812 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
2813 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
2814 return;
2815
2816 int xp, yp;
2817 m_sizerParent->GetPosition(&xp, &yp);
2818 m_sizerParent->TransformSizerToActual(&xp, &yp);
2819 *x += xp;
2820 *y += yp;
2821 }
2822
2823 void wxWindow::SizerSetSize(int x, int y, int w, int h)
2824 {
2825 int xx = x;
2826 int yy = y;
2827 TransformSizerToActual(&xx, &yy);
2828 SetSize(xx, yy, w, h);
2829 }
2830
2831 void wxWindow::SizerMove(int x, int y)
2832 {
2833 int xx = x;
2834 int yy = y;
2835 TransformSizerToActual(&xx, &yy);
2836 Move(xx, yy);
2837 }
2838
2839 // Only set the size/position of the constraint (if any)
2840 void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
2841 {
2842 wxLayoutConstraints *constr = GetConstraints();
2843 if (constr)
2844 {
2845 if (x != -1)
2846 {
2847 constr->left.SetValue(x);
2848 constr->left.SetDone(TRUE);
2849 }
2850 if (y != -1)
2851 {
2852 constr->top.SetValue(y);
2853 constr->top.SetDone(TRUE);
2854 }
2855 if (w != -1)
2856 {
2857 constr->width.SetValue(w);
2858 constr->width.SetDone(TRUE);
2859 }
2860 if (h != -1)
2861 {
2862 constr->height.SetValue(h);
2863 constr->height.SetDone(TRUE);
2864 }
2865 }
2866 }
2867
2868 void wxWindow::MoveConstraint(int x, int y)
2869 {
2870 wxLayoutConstraints *constr = GetConstraints();
2871 if (constr)
2872 {
2873 if (x != -1)
2874 {
2875 constr->left.SetValue(x);
2876 constr->left.SetDone(TRUE);
2877 }
2878 if (y != -1)
2879 {
2880 constr->top.SetValue(y);
2881 constr->top.SetDone(TRUE);
2882 }
2883 }
2884 }
2885
2886 void wxWindow::GetSizeConstraint(int *w, int *h) const
2887 {
2888 wxLayoutConstraints *constr = GetConstraints();
2889 if (constr)
2890 {
2891 *w = constr->width.GetValue();
2892 *h = constr->height.GetValue();
2893 }
2894 else
2895 GetSize(w, h);
2896 }
2897
2898 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
2899 {
2900 wxLayoutConstraints *constr = GetConstraints();
2901 if (constr)
2902 {
2903 *w = constr->width.GetValue();
2904 *h = constr->height.GetValue();
2905 }
2906 else
2907 GetClientSize(w, h);
2908 }
2909
2910 void wxWindow::GetPositionConstraint(int *x, int *y) const
2911 {
2912 wxLayoutConstraints *constr = GetConstraints();
2913 if (constr)
2914 {
2915 *x = constr->left.GetValue();
2916 *y = constr->top.GetValue();
2917 }
2918 else
2919 GetPosition(x, y);
2920 }
2921
2922 bool wxWindow::AcceptsFocus() const
2923 {
2924 return IsEnabled() && IsShown();
2925 }
2926
2927 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
2928 {
2929 UpdateWindowUI();
2930 }