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