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