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