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