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