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