1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
24 #if wxUSE_DRAG_AND_DROP
28 #include "wx/statusbr.h"
30 #include "wx/settings.h"
37 #include "gdk/gdkprivate.h"
38 #include "gdk/gdkkeysyms.h"
39 #include "wx/gtk/win_gtk.h"
41 //-----------------------------------------------------------------------------
42 // documentation on internals
43 //-----------------------------------------------------------------------------
46 I have been asked several times about writing some documentation about
47 the GTK port of wxWindows, especially its internal structures. Obviously,
48 you cannot understand wxGTK without knowing a little about the GTK, but
49 some more information about what the wxWindow, which is the base class
50 for all other window classes, does seems required as well.
52 What does wxWindow do? It contains the common interface for the following
53 jobs of its descendants:
55 1) Define the rudimentary behaviour common to all window classes, such as
56 resizing, intercepting user input (so as to make it possible to use these
57 events for special purposes in a derived class), window names etc.
59 2) Provide the possibility to contain and manage children, if the derived
60 class is allowed to contain children, which holds true for those window
61 classes which do not display a native GTK widget. To name them, these
62 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
63 work classes are a special case and are handled a bit differently from
64 the rest. The same holds true for the wxNotebook class.
66 3) Provide the possibility to draw into a client area of a window. This,
67 too, only holds true for classes that do not display a native GTK widget
70 4) Provide the entire mechanism for scrolling widgets. This actual inter-
71 face for this is usually in wxScrolledWindow, but the GTK implementation
74 5) A multitude of helper or extra methods for special purposes, such as
75 Drag'n'Drop, managing validators etc.
77 Normally one might expect, that one wxWindows window would always correspond
78 to one GTK widget. Under GTK, there is no such allround widget that has all
79 the functionality. Moreover, the GTK defines a client area as a different
80 widget from the actual widget you are handling. Last but not least some
81 special classes (e.g. wxFrame) handle different categories of widgets and
82 still have the possibility to draw something in the client area.
83 It was therefore required to write a special purpose GTK widget, that would
84 represent a client area in the sense of wxWindows capable to do the jobs
85 2), 3) and 4). I have written this class and it resides in win_gtk.c of
88 All windows must have a widget, with which they interact with other under-
89 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
90 thw wxWindow class has a member variable called m_widget which holds a
91 pointer to this widget. When the window class represents a GTK native widget,
92 this is (in most cases) the only GTK widget the class manages. E.g. the
93 wxStatitText class handles only a GtkLabel widget a pointer to which you
94 can find in m_widget (defined in wxWindow)
96 When the class has a client area for drawing into and for containing children
97 it has to handle the client area widget (of the type GtkMyFixed, defined in
98 win_gtk.c), but there could be any number of widgets, handled by a class
99 The common rule for all windows is only, that the widget that interacts with
100 the rest of GTK must be referenced in m_widget and all other widgets must be
101 children of this widget on the GTK level. The top-most widget, which also
102 represents the client area, must be in the m_wxwindow field and must be of
105 As I said, the window classes that display a GTK native widget only have
106 one widget, so in the case of e.g. the wxButton class m_widget holds a
107 pointer to a GtkButton widget. But windows with client areas (for drawing
108 and children) have a m_widget field that is a pointer to a GtkScrolled-
109 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
110 one is (in the GTK sense) a child of the GtkScrolledWindow.
112 If the m_wxwindow field is set, then all input to this widget is inter-
113 cepted and sent to the wxWindows class. If not, all input to the widget
114 that gets pointed to by m_widget gets intercepted and sent to the class.
118 //-------------------------------------------------------------------------
119 // conditional compilation
120 //-------------------------------------------------------------------------
122 #if (GTK_MINOR_VERSION == 1)
123 #if (GTK_MICRO_VERSION >= 5)
124 #define NEW_GTK_SCROLL_CODE
128 //-----------------------------------------------------------------------------
130 //-----------------------------------------------------------------------------
134 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
135 GdkEvent
*WXUNUSED(event
),
138 printf( "FOCUS NOW AT: " );
145 void debug_focus_in( GtkWidget
* widget
, const char* name
, const char *window
)
153 char *s
= new char[tmp
.Length()+1];
155 strcpy( s
, WXSTRINGCAST tmp
);
157 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
158 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
163 //-----------------------------------------------------------------------------
165 //-----------------------------------------------------------------------------
167 extern wxList wxPendingDelete
;
168 extern wxList wxTopLevelWindows
;
169 extern bool g_blockEventsOnDrag
;
170 extern bool g_blockEventsOnScroll
;
171 static bool g_capturing
= FALSE
;
172 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
174 // hack: we need something to pass to gtk_menu_popup, so we store the time of
175 // the last click here
176 static guint32 gs_timeLastClick
= 0;
178 //-----------------------------------------------------------------------------
179 // "expose_event" (of m_wxwindow, not of m_widget)
180 //-----------------------------------------------------------------------------
182 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
184 if (!win
->HasVMT()) return;
186 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
188 gdk_event
->area
.width
,
189 gdk_event
->area
.height
);
191 if (gdk_event
->count
> 0) return;
194 printf( "OnExpose from " );
195 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
196 printf( win->GetClassInfo()->GetClassName() );
200 wxPaintEvent
event( win
->GetId() );
201 event
.SetEventObject( win
);
202 win
->GetEventHandler()->ProcessEvent( event
);
204 win
->m_updateRegion
.Clear();
207 //-----------------------------------------------------------------------------
208 // "draw" (of m_wxwindow, not of m_widget)
209 //-----------------------------------------------------------------------------
211 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
213 if (!win
->HasVMT()) return;
215 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
217 wxPaintEvent
event( win
->GetId() );
218 event
.SetEventObject( win
);
219 win
->GetEventHandler()->ProcessEvent( event
);
221 win
->m_updateRegion
.Clear();
224 //-----------------------------------------------------------------------------
225 // "key_press_event" from any window
226 //-----------------------------------------------------------------------------
228 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
230 if (!win
->HasVMT()) return FALSE
;
231 if (g_blockEventsOnDrag
) return FALSE
;
234 printf( "OnKeyPress from " );
235 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
236 printf( win->GetClassInfo()->GetClassName() );
241 switch (gdk_event
->keyval
)
243 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
244 case GDK_Tab
: key_code
= WXK_TAB
; break;
245 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
246 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
247 case GDK_Return
: key_code
= WXK_RETURN
; break;
248 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
249 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
250 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
251 case GDK_Delete
: key_code
= WXK_DELETE
; break;
252 case GDK_Home
: key_code
= WXK_HOME
; break;
253 case GDK_Left
: key_code
= WXK_LEFT
; break;
254 case GDK_Up
: key_code
= WXK_UP
; break;
255 case GDK_Right
: key_code
= WXK_RIGHT
; break;
256 case GDK_Down
: key_code
= WXK_DOWN
; break;
257 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
258 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
259 case GDK_Next
: key_code
= WXK_NEXT
; break;
260 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
261 case GDK_End
: key_code
= WXK_END
; break;
262 case GDK_Begin
: key_code
= WXK_HOME
; break;
263 case GDK_Select
: key_code
= WXK_SELECT
; break;
264 case GDK_Print
: key_code
= WXK_PRINT
; break;
265 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
266 case GDK_Insert
: key_code
= WXK_INSERT
; break;
267 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
268 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
269 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
270 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
271 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
272 case GDK_KP_Up
: key_code
= WXK_UP
; break;
273 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
274 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
275 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
276 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
277 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
278 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
279 case GDK_KP_End
: key_code
= WXK_END
; break;
280 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
281 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
282 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
283 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
284 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
285 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
286 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
287 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
288 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
289 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
290 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
291 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
292 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
293 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
294 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
295 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
296 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
297 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
298 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
299 case GDK_F1
: key_code
= WXK_F1
; break;
300 case GDK_F2
: key_code
= WXK_F2
; break;
301 case GDK_F3
: key_code
= WXK_F3
; break;
302 case GDK_F4
: key_code
= WXK_F4
; break;
303 case GDK_F5
: key_code
= WXK_F5
; break;
304 case GDK_F6
: key_code
= WXK_F6
; break;
305 case GDK_F7
: key_code
= WXK_F7
; break;
306 case GDK_F8
: key_code
= WXK_F8
; break;
307 case GDK_F9
: key_code
= WXK_F9
; break;
308 case GDK_F10
: key_code
= WXK_F10
; break;
309 case GDK_F11
: key_code
= WXK_F11
; break;
310 case GDK_F12
: key_code
= WXK_F12
; break;
313 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
314 key_code
= gdk_event
->keyval
;
318 if (!key_code
) return FALSE
;
320 wxKeyEvent
event( wxEVT_CHAR
);
321 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
322 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
323 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
324 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
325 event
.m_keyCode
= key_code
;
328 event
.SetEventObject( win
);
330 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
334 wxWindow
*ancestor
= win
;
337 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
340 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
341 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
344 ancestor
= ancestor
->GetParent();
348 // win is a control: tab can be propagated up
349 if ((!ret
) && (gdk_event
->keyval
== GDK_Tab
))
351 wxNavigationKeyEvent new_event
;
352 new_event
.SetDirection( !(gdk_event
->state
& GDK_SHIFT_MASK
) );
353 new_event
.SetWindowChange( FALSE
);
354 new_event
.SetCurrentFocus( win
);
355 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
359 // win is a panel: up can be propagated to the panel
360 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
361 (gdk_event->keyval == GDK_Up))
363 win->m_parent->SetFocus();
367 // win is a panel: left/right can be propagated to the panel
368 if ((!ret) && (win->m_wxwindow) &&
369 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
370 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
372 wxNavigationKeyEvent new_event;
373 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
374 new_event.SetCurrentFocus( win );
375 ret = win->GetEventHandler()->ProcessEvent( new_event );
381 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
387 //-----------------------------------------------------------------------------
388 // "button_press_event"
389 //-----------------------------------------------------------------------------
391 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
393 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
395 if (g_blockEventsOnDrag
) return TRUE
;
396 if (g_blockEventsOnScroll
) return TRUE
;
400 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
402 gtk_widget_grab_focus (win
->m_wxwindow
);
405 printf( "GrabFocus from " );
406 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
407 printf( win->GetClassInfo()->GetClassName() );
414 if (!win
->HasVMT()) return TRUE
;
417 printf( "OnButtonPress from " );
418 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
419 printf( win->GetClassInfo()->GetClassName() );
423 wxEventType event_type
= wxEVT_LEFT_DOWN
;
425 if (gdk_event
->button
== 1)
427 switch (gdk_event
->type
)
429 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
430 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
434 else if (gdk_event
->button
== 2)
436 switch (gdk_event
->type
)
438 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
439 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
443 else if (gdk_event
->button
== 3)
445 switch (gdk_event
->type
)
447 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
448 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
453 wxMouseEvent
event( event_type
);
454 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
455 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
456 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
457 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
458 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
459 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
460 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
462 event
.m_x
= (long)gdk_event
->x
;
463 event
.m_y
= (long)gdk_event
->y
;
465 // Some control don't have their own X window and thus cannot get
470 wxNode
*node
= win
->GetChildren().First();
473 wxWindow
*child
= (wxWindow
*)node
->Data();
475 if (child
->m_isStaticBox
)
477 // wxStaticBox is transparent in the box itself
480 int xx1
= child
->m_x
;
481 int yy1
= child
->m_y
;
482 int xx2
= child
->m_x
+ child
->m_width
;
483 int yy2
= child
->m_x
+ child
->m_height
;
486 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
488 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
490 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
492 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
495 event
.m_x
-= child
->m_x
;
496 event
.m_y
-= child
->m_y
;
503 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
504 (child
->m_x
<= event
.m_x
) &&
505 (child
->m_y
<= event
.m_y
) &&
506 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
507 (child
->m_y
+child
->m_height
>= event
.m_y
))
510 event
.m_x
-= child
->m_x
;
511 event
.m_y
-= child
->m_y
;
519 event
.SetEventObject( win
);
521 gs_timeLastClick
= gdk_event
->time
;
523 if (win
->GetEventHandler()->ProcessEvent( event
))
524 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
529 //-----------------------------------------------------------------------------
530 // "button_release_event"
531 //-----------------------------------------------------------------------------
533 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
535 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
537 if (g_blockEventsOnDrag
) return TRUE
;
538 if (g_blockEventsOnScroll
) return TRUE
;
540 if (!win
->HasVMT()) return TRUE
;
543 printf( "OnButtonRelease from " );
544 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
545 printf( win->GetClassInfo()->GetClassName() );
549 wxEventType event_type
= wxEVT_NULL
;
551 switch (gdk_event
->button
)
553 case 1: event_type
= wxEVT_LEFT_UP
; break;
554 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
555 case 3: event_type
= wxEVT_RIGHT_UP
; break;
558 wxMouseEvent
event( event_type
);
559 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
560 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
561 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
562 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
563 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
564 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
565 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
566 event
.m_x
= (long)gdk_event
->x
;
567 event
.m_y
= (long)gdk_event
->y
;
569 // Some control don't have their own X window and thus cannot get
574 wxNode
*node
= win
->GetChildren().First();
577 wxWindow
*child
= (wxWindow
*)node
->Data();
579 if (child
->m_isStaticBox
)
581 // wxStaticBox is transparent in the box itself
584 int xx1
= child
->m_x
;
585 int yy1
= child
->m_y
;
586 int xx2
= child
->m_x
+ child
->m_width
;
587 int yy2
= child
->m_x
+ child
->m_height
;
590 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
592 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
594 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
596 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
599 event
.m_x
-= child
->m_x
;
600 event
.m_y
-= child
->m_y
;
607 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
608 (child
->m_x
<= event
.m_x
) &&
609 (child
->m_y
<= event
.m_y
) &&
610 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
611 (child
->m_y
+child
->m_height
>= event
.m_y
))
614 event
.m_x
-= child
->m_x
;
615 event
.m_y
-= child
->m_y
;
623 event
.SetEventObject( win
);
625 if (win
->GetEventHandler()->ProcessEvent( event
))
626 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
631 //-----------------------------------------------------------------------------
632 // "motion_notify_event"
633 //-----------------------------------------------------------------------------
635 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
637 if (gdk_event
->is_hint
)
641 GdkModifierType state
;
642 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
645 gdk_event
->state
= state
;
648 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
650 if (g_blockEventsOnDrag
) return TRUE
;
651 if (g_blockEventsOnScroll
) return TRUE
;
653 if (!win
->HasVMT()) return TRUE
;
656 printf( "OnMotion from " );
657 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
658 printf( win->GetClassInfo()->GetClassName() );
662 wxMouseEvent
event( wxEVT_MOTION
);
663 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
664 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
665 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
666 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
667 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
668 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
669 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
671 event
.m_x
= (long)gdk_event
->x
;
672 event
.m_y
= (long)gdk_event
->y
;
674 // Some control don't have their own X window and thus cannot get
679 wxNode
*node
= win
->GetChildren().First();
682 wxWindow
*child
= (wxWindow
*)node
->Data();
684 if (child
->m_isStaticBox
)
686 // wxStaticBox is transparent in the box itself
689 int xx1
= child
->m_x
;
690 int yy1
= child
->m_y
;
691 int xx2
= child
->m_x
+ child
->m_width
;
692 int yy2
= child
->m_x
+ child
->m_height
;
695 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
697 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
699 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
701 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
704 event
.m_x
-= child
->m_x
;
705 event
.m_y
-= child
->m_y
;
712 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
713 (child
->m_x
<= event
.m_x
) &&
714 (child
->m_y
<= event
.m_y
) &&
715 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
716 (child
->m_y
+child
->m_height
>= event
.m_y
))
719 event
.m_x
-= child
->m_x
;
720 event
.m_y
-= child
->m_y
;
728 event
.SetEventObject( win
);
730 if (win
->GetEventHandler()->ProcessEvent( event
))
731 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
736 //-----------------------------------------------------------------------------
738 //-----------------------------------------------------------------------------
740 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
742 if (g_blockEventsOnDrag
) return TRUE
;
748 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
750 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
752 printf( "SetFocus flag from " );
753 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
754 printf( win->GetClassInfo()->GetClassName() );
760 if (!win
->HasVMT()) return TRUE
;
763 printf( "OnSetFocus from " );
764 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
765 printf( win->GetClassInfo()->GetClassName() );
767 printf( WXSTRINGCAST win->GetLabel() );
771 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
772 event
.SetEventObject( win
);
774 if (win
->GetEventHandler()->ProcessEvent( event
))
775 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
780 //-----------------------------------------------------------------------------
782 //-----------------------------------------------------------------------------
784 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
786 if (g_blockEventsOnDrag
) return TRUE
;
789 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
790 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
793 if (!win
->HasVMT()) return TRUE
;
796 printf( "OnKillFocus from " );
797 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
798 printf( win->GetClassInfo()->GetClassName() );
802 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
803 event
.SetEventObject( win
);
805 if (win
->GetEventHandler()->ProcessEvent( event
))
806 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
811 //-----------------------------------------------------------------------------
812 // "enter_notify_event"
813 //-----------------------------------------------------------------------------
815 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
817 if (g_blockEventsOnDrag
) return TRUE
;
819 if ((widget
->window
) && (win
->m_cursor
))
820 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
822 if (widget
->window
!= gdk_event
->window
) return TRUE
;
824 if (!win
->HasVMT()) return TRUE
;
827 printf( "OnEnter from " );
828 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
829 printf( win->GetClassInfo()->GetClassName() );
833 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
834 event
.SetEventObject( win
);
838 GdkModifierType state
= (GdkModifierType
)0;
840 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
842 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
843 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
844 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
845 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
846 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
847 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
848 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
853 if (win
->GetEventHandler()->ProcessEvent( event
))
854 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
859 //-----------------------------------------------------------------------------
860 // "leave_notify_event"
861 //-----------------------------------------------------------------------------
863 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
865 if (g_blockEventsOnDrag
) return TRUE
;
867 if ((widget
->window
) && (win
->m_cursor
))
868 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
870 if (widget
->window
!= gdk_event
->window
) return TRUE
;
872 if (!win
->HasVMT()) return TRUE
;
875 printf( "OnLeave from " );
876 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
877 printf( win->GetClassInfo()->GetClassName() );
881 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
882 event
.SetEventObject( win
);
886 GdkModifierType state
= (GdkModifierType
)0;
888 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
890 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
891 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
892 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
893 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
894 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
895 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
896 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
901 if (win
->GetEventHandler()->ProcessEvent( event
))
902 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
907 //-----------------------------------------------------------------------------
908 // "value_changed" from m_vAdjust
909 //-----------------------------------------------------------------------------
911 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
913 if (g_blockEventsOnDrag
) return;
916 printf( "OnVScroll from " );
917 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
918 printf( win->GetClassInfo()->GetClassName() );
922 if (!win
->HasVMT()) return;
924 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
925 if (fabs(diff
) < 0.2) return;
927 wxEventType command
= wxEVT_NULL
;
929 float line_step
= win
->m_vAdjust
->step_increment
;
930 float page_step
= win
->m_vAdjust
->page_increment
;
932 if (win
->m_isScrolling
)
934 command
= wxEVT_SCROLL_THUMBTRACK
;
938 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
939 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
940 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
941 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
942 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
943 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
944 else command
= wxEVT_SCROLL_THUMBTRACK
;
947 int value
= (int)(win
->m_vAdjust
->value
+0.5);
949 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
950 event
.SetEventObject( win
);
951 win
->GetEventHandler()->ProcessEvent( event
);
954 //-----------------------------------------------------------------------------
955 // "value_changed" from m_hAdjust
956 //-----------------------------------------------------------------------------
958 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
960 if (g_blockEventsOnDrag
) return;
963 printf( "OnHScroll from " );
964 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
965 printf( win->GetClassInfo()->GetClassName() );
969 if (!win
->HasVMT()) return;
971 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
972 if (fabs(diff
) < 0.2) return;
974 wxEventType command
= wxEVT_NULL
;
976 float line_step
= win
->m_hAdjust
->step_increment
;
977 float page_step
= win
->m_hAdjust
->page_increment
;
979 if (win
->m_isScrolling
)
981 command
= wxEVT_SCROLL_THUMBTRACK
;
985 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
986 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
987 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
988 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
989 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
990 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
991 else command
= wxEVT_SCROLL_THUMBTRACK
;
994 int value
= (int)(win
->m_hAdjust
->value
+0.5);
996 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
997 event
.SetEventObject( win
);
998 win
->GetEventHandler()->ProcessEvent( event
);
1001 //-----------------------------------------------------------------------------
1002 // "changed" from m_vAdjust
1003 //-----------------------------------------------------------------------------
1005 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1007 if (g_blockEventsOnDrag
) return;
1010 printf( "OnVScroll change from " );
1011 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1012 printf( win->GetClassInfo()->GetClassName() );
1016 if (!win
->HasVMT()) return;
1018 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1019 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1021 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
1022 event
.SetEventObject( win
);
1023 win
->GetEventHandler()->ProcessEvent( event
);
1026 //-----------------------------------------------------------------------------
1027 // "changed" from m_hAdjust
1028 //-----------------------------------------------------------------------------
1030 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1032 if (g_blockEventsOnDrag
) return;
1035 printf( "OnHScroll change from " );
1036 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1037 printf( win->GetClassInfo()->GetClassName() );
1041 if (!win
->HasVMT()) return;
1043 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1044 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1046 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
1047 event
.SetEventObject( win
);
1048 win
->GetEventHandler()->ProcessEvent( event
);
1051 //-----------------------------------------------------------------------------
1052 // "button_press_event" from scrollbar
1053 //-----------------------------------------------------------------------------
1055 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1056 GdkEventButton
*WXUNUSED(gdk_event
),
1059 // don't test here as we can release the mouse while being over
1060 // a different window then the slider
1062 // if (gdk_event->window != widget->slider) return FALSE;
1064 win
->m_isScrolling
= TRUE
;
1065 g_blockEventsOnScroll
= TRUE
;
1070 //-----------------------------------------------------------------------------
1071 // "button_release_event" from scrollbar
1072 //-----------------------------------------------------------------------------
1074 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1075 GdkEventButton
*WXUNUSED(gdk_event
),
1079 // don't test here as we can release the mouse while being over
1080 // a different window then the slider
1082 // if (gdk_event->window != widget->slider) return FALSE;
1084 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1086 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
1087 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1089 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1091 win
->m_isScrolling
= FALSE
;
1092 g_blockEventsOnScroll
= FALSE
;
1097 //-----------------------------------------------------------------------------
1098 // InsertChild for wxWindow.
1099 //-----------------------------------------------------------------------------
1101 // Callback for wxWindow. This very strange beast has to be used because
1102 // C++ has no virtual methods in a constructor. We have to emulate a
1103 // virtual function here as wxNotebook requires a different way to insert
1104 // a child in it. I had opted for creating a wxNotebookPage window class
1105 // which would have made this superfluous (such in the MDI window system),
1106 // but no-one was listening to me...
1108 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1110 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1111 GTK_WIDGET(child
->m_widget
),
1115 gtk_widget_set_usize( GTK_WIDGET(child
->m_widget
),
1120 //-----------------------------------------------------------------------------
1122 //-----------------------------------------------------------------------------
1124 wxWindow
* wxGetActiveWindow()
1126 return g_focusWindow
;
1129 //-----------------------------------------------------------------------------
1131 //-----------------------------------------------------------------------------
1133 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
1135 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
1136 EVT_SIZE(wxWindow::OnSize
)
1137 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
1138 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
1139 EVT_IDLE(wxWindow::OnIdle
)
1142 wxWindow::wxWindow()
1144 m_widget
= (GtkWidget
*) NULL
;
1145 m_wxwindow
= (GtkWidget
*) NULL
;
1146 m_parent
= (wxWindow
*) NULL
;
1147 m_children
.DeleteContents( FALSE
);
1160 m_eventHandler
= this;
1161 m_windowValidator
= (wxValidator
*) NULL
;
1165 m_cursor
= (wxCursor
*) NULL
;
1166 m_font
= *wxSWISS_FONT
;
1168 m_windowName
= "noname";
1170 m_constraints
= (wxLayoutConstraints
*) NULL
;
1171 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1172 m_windowSizer
= (wxSizer
*) NULL
;
1173 m_sizerParent
= (wxWindow
*) NULL
;
1174 m_autoLayout
= FALSE
;
1178 m_needParent
= TRUE
;
1180 m_hasScrolling
= FALSE
;
1181 m_isScrolling
= FALSE
;
1182 m_hAdjust
= (GtkAdjustment
*) NULL
;
1183 m_vAdjust
= (GtkAdjustment
*) NULL
;
1184 m_oldHorizontalPos
= 0.0;
1185 m_oldVerticalPos
= 0.0;
1190 #if wxUSE_DRAG_AND_DROP
1191 m_dropTarget
= (wxDropTarget
*) NULL
;
1194 m_scrollGC
= (GdkGC
*) NULL
;
1195 m_widgetStyle
= (GtkStyle
*) NULL
;
1197 m_insertCallback
= wxInsertChildInWindow
;
1199 m_clientObject
= (wxClientData
*) NULL
;
1200 m_clientData
= NULL
;
1202 m_isStaticBox
= FALSE
;
1203 m_acceptsFocus
= FALSE
;
1206 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1207 const wxPoint
&pos
, const wxSize
&size
,
1208 long style
, const wxString
&name
)
1210 m_insertCallback
= wxInsertChildInWindow
;
1211 Create( parent
, id
, pos
, size
, style
, name
);
1214 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1215 const wxPoint
&pos
, const wxSize
&size
,
1216 long style
, const wxString
&name
)
1220 m_needParent
= TRUE
;
1222 PreCreation( parent
, id
, pos
, size
, style
, name
);
1224 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1225 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1228 debug_focus_in( m_widget
, "wxWindow::m_widget", name
);
1231 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
1234 debug_focus_in( s_window
->hscrollbar
, "wxWindow::hsrcollbar", name
);
1235 debug_focus_in( s_window
->vscrollbar
, "wxWindow::vsrcollbar", name
);
1238 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1239 scroll_class
->scrollbar_spacing
= 0;
1241 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1243 m_oldHorizontalPos
= 0.0;
1244 m_oldVerticalPos
= 0.0;
1246 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
1247 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
1249 m_wxwindow
= gtk_myfixed_new();
1252 debug_focus_in( m_wxwindow
, "wxWindow::m_wxwindow", name
);
1255 #ifdef NEW_GTK_SCROLL_CODE
1256 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget
), m_wxwindow
);
1257 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->child
);
1259 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1260 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
1264 debug_focus_in( GTK_WIDGET(viewport
), "wxWindow::viewport", name
);
1267 if (m_windowStyle
& wxRAISED_BORDER
)
1269 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1271 else if (m_windowStyle
& wxSUNKEN_BORDER
)
1273 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1277 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1280 if ((m_windowStyle
& wxTAB_TRAVERSAL
) != 0)
1282 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1283 m_acceptsFocus
= FALSE
;
1287 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1288 m_acceptsFocus
= TRUE
;
1291 // shut the viewport up
1292 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1293 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1295 // I _really_ don't want scrollbars in the beginning
1296 m_vAdjust
->lower
= 0.0;
1297 m_vAdjust
->upper
= 1.0;
1298 m_vAdjust
->value
= 0.0;
1299 m_vAdjust
->step_increment
= 1.0;
1300 m_vAdjust
->page_increment
= 1.0;
1301 m_vAdjust
->page_size
= 5.0;
1302 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1303 m_hAdjust
->lower
= 0.0;
1304 m_hAdjust
->upper
= 1.0;
1305 m_hAdjust
->value
= 0.0;
1306 m_hAdjust
->step_increment
= 1.0;
1307 m_hAdjust
->page_increment
= 1.0;
1308 m_hAdjust
->page_size
= 5.0;
1309 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1311 // these handlers block mouse events to any window during scrolling
1312 // such as motion events and prevent GTK and wxWindows from fighting
1313 // over where the slider should be
1315 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
1316 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1318 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
1319 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1321 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
1322 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1324 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
1325 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1327 // these handers het notified when screen updates are required either when
1328 // scrolling or when the window size (and therefore scrollbar configuration)
1331 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1332 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1333 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1334 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1336 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1337 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1338 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1339 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1341 gtk_widget_show( m_wxwindow
);
1343 if (m_parent
) m_parent
->AddChild( this );
1345 (m_parent
->m_insertCallback
)( m_parent
, this );
1354 wxWindow::~wxWindow()
1358 #if wxUSE_DRAG_AND_DROP
1359 if (m_dropTarget
) delete m_dropTarget
;
1362 if (m_parent
) m_parent
->RemoveChild( this );
1363 if (m_widget
) Show( FALSE
);
1367 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
1369 if (m_scrollGC
) gdk_gc_unref( m_scrollGC
);
1371 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1373 if (m_widget
) gtk_widget_destroy( m_widget
);
1375 if (m_cursor
) delete m_cursor
;
1377 DeleteRelatedConstraints();
1380 // This removes any dangling pointers to this window
1381 // in other windows' constraintsInvolvedIn lists.
1382 UnsetConstraints(m_constraints
);
1383 delete m_constraints
;
1384 m_constraints
= (wxLayoutConstraints
*) NULL
;
1388 delete m_windowSizer
;
1389 m_windowSizer
= (wxSizer
*) NULL
;
1391 // If this is a child of a sizer, remove self from parent
1392 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1394 // Just in case the window has been Closed, but
1395 // we're then deleting immediately: don't leave
1396 // dangling pointers.
1397 wxPendingDelete
.DeleteObject(this);
1399 // Just in case we've loaded a top-level window via
1400 // wxWindow::LoadNativeDialog but we weren't a dialog
1402 wxTopLevelWindows
.DeleteObject(this);
1404 if (m_windowValidator
) delete m_windowValidator
;
1406 if (m_clientObject
) delete m_clientObject
;
1409 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1410 const wxPoint
&pos
, const wxSize
&size
,
1411 long style
, const wxString
&name
)
1413 wxASSERT_MSG( (!m_needParent
) || (parent
), "Need complete parent." );
1415 m_widget
= (GtkWidget
*) NULL
;
1416 m_wxwindow
= (GtkWidget
*) NULL
;
1419 m_children
.DeleteContents( FALSE
);
1422 if (m_width
== -1) m_width
= 20;
1424 if (m_height
== -1) m_height
= 20;
1429 if (!m_needParent
) // some reasonable defaults
1433 m_x
= (gdk_screen_width () - m_width
) / 2;
1434 if (m_x
< 10) m_x
= 10;
1438 m_y
= (gdk_screen_height () - m_height
) / 2;
1439 if (m_y
< 10) m_y
= 10;
1450 m_eventHandler
= this;
1452 m_windowId
= id
== -1 ? wxNewId() : id
;
1456 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1457 m_font
= *wxSWISS_FONT
;
1458 m_backgroundColour
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
1459 m_foregroundColour
= *wxBLACK
;
1460 m_windowStyle
= style
;
1461 m_windowName
= name
;
1463 m_constraints
= (wxLayoutConstraints
*) NULL
;
1464 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1465 m_windowSizer
= (wxSizer
*) NULL
;
1466 m_sizerParent
= (wxWindow
*) NULL
;
1467 m_autoLayout
= FALSE
;
1469 m_hasScrolling
= FALSE
;
1470 m_isScrolling
= FALSE
;
1471 m_hAdjust
= (GtkAdjustment
*) NULL
;
1472 m_vAdjust
= (GtkAdjustment
*) NULL
;
1473 m_oldHorizontalPos
= 0.0;
1474 m_oldVerticalPos
= 0.0;
1479 #if wxUSE_DRAG_AND_DROP
1480 m_dropTarget
= (wxDropTarget
*) NULL
;
1483 m_windowValidator
= (wxValidator
*) NULL
;
1484 m_scrollGC
= (GdkGC
*) NULL
;
1485 m_widgetStyle
= (GtkStyle
*) NULL
;
1487 m_clientObject
= (wxClientData
*)NULL
;
1488 m_clientData
= NULL
;
1490 m_isStaticBox
= FALSE
;
1493 void wxWindow::PostCreation()
1497 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1498 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1500 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1501 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1504 ConnectWidget( GetConnectWidget() );
1506 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1508 if (m_wxwindow
) gtk_widget_realize( m_wxwindow
);
1510 SetCursor( *wxSTANDARD_CURSOR
);
1515 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1517 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1518 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1520 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1521 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1523 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1524 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1526 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1527 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1529 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1530 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1532 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1533 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1535 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1536 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1538 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1539 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1542 bool wxWindow::HasVMT()
1547 bool wxWindow::Close( bool force
)
1549 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1551 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1552 event
.SetEventObject(this);
1553 event
.SetForce(force
);
1555 return GetEventHandler()->ProcessEvent(event
);
1558 bool wxWindow::Destroy()
1560 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1567 bool wxWindow::DestroyChildren()
1570 while ((node
= m_children
.First()) != (wxNode
*)NULL
)
1573 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1576 if (m_children
.Member(child
)) delete node
;
1582 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1584 // are we to set fonts here ?
1587 wxPoint
wxWindow::GetClientAreaOrigin() const
1589 return wxPoint(0,0);
1592 void wxWindow::AdjustForParentClientOrigin( int& x
, int& y
, int sizeFlags
)
1594 if (((sizeFlags
& wxSIZE_NO_ADJUSTMENTS
) == 0) && GetParent())
1596 wxPoint
pt(GetParent()->GetClientAreaOrigin());
1602 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1604 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1605 wxASSERT_MSG( (m_parent
!= NULL
), "wxWindow::SetSize requires parent.\n" );
1607 if (m_resizing
) return; // I don't like recursions
1610 if (m_parent
->m_wxwindow
== NULL
) // i.e. wxNotebook
1612 // don't set the size for children of wxNotebook, just take the values.
1620 int old_width
= m_width
;
1621 int old_height
= m_height
;
1623 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1625 if (x
!= -1) m_x
= x
;
1626 if (y
!= -1) m_y
= y
;
1627 if (width
!= -1) m_width
= width
;
1628 if (height
!= -1) m_height
= height
;
1638 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1640 if (width
== -1) m_width
= 80;
1643 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1645 if (height
== -1) m_height
= 26;
1648 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1649 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1650 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1651 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1653 wxPoint
pt( m_parent
->GetClientAreaOrigin() );
1654 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
+pt
.x
, m_y
+pt
.y
);
1656 if ((old_width
!= m_width
) || (old_height
!= m_height
))
1657 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1662 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1663 event
.SetEventObject( this );
1664 GetEventHandler()->ProcessEvent( event
);
1669 void wxWindow::SetSize( int width
, int height
)
1671 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1674 void wxWindow::Move( int x
, int y
)
1676 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1679 void wxWindow::GetSize( int *width
, int *height
) const
1681 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1683 if (width
) (*width
) = m_width
;
1684 if (height
) (*height
) = m_height
;
1687 void wxWindow::SetClientSize( int width
, int height
)
1689 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1693 SetSize( width
, height
);
1700 if (!m_hasScrolling
)
1702 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1704 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1705 (m_windowStyle
& wxSUNKEN_BORDER
))
1707 dw
+= 2 * window_class
->xthickness
;
1708 dh
+= 2 * window_class
->ythickness
;
1713 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1714 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1716 #ifdef NEW_GTK_SCROLL_CODE
1717 GtkWidget
*viewport
= scroll_window
->child
;
1719 GtkWidget
*viewport
= scroll_window
->viewport
;
1722 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1724 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1725 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1727 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1728 (m_windowStyle
& wxSUNKEN_BORDER
))
1730 dw
+= 2 * viewport_class
->xthickness
;
1731 dh
+= 2 * viewport_class
->ythickness
;
1734 if (scroll_window
->vscrollbar_visible
)
1736 dw
+= vscrollbar
->allocation
.width
;
1737 dw
+= scroll_class
->scrollbar_spacing
;
1740 if (scroll_window
->hscrollbar_visible
)
1742 dh
+= hscrollbar
->allocation
.height
;
1743 dw
+= scroll_class
->scrollbar_spacing
;
1747 SetSize( width
+dw
, height
+dh
);
1751 void wxWindow::GetClientSize( int *width
, int *height
) const
1753 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1757 if (width
) (*width
) = m_width
;
1758 if (height
) (*height
) = m_height
;
1765 if (!m_hasScrolling
)
1767 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1769 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1770 (m_windowStyle
& wxSUNKEN_BORDER
))
1772 dw
+= 2 * window_class
->xthickness
;
1773 dh
+= 2 * window_class
->ythickness
;
1778 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1779 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1781 #ifdef NEW_GTK_SCROLL_CODE
1782 GtkWidget
*viewport
= scroll_window
->child
;
1784 GtkWidget
*viewport
= scroll_window
->viewport
;
1787 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1789 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1790 (m_windowStyle
& wxSUNKEN_BORDER
))
1792 dw
+= 2 * viewport_class
->xthickness
;
1793 dh
+= 2 * viewport_class
->ythickness
;
1796 if (scroll_window
->vscrollbar_visible
)
1798 // dw += vscrollbar->allocation.width;
1799 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1800 dw
+= scroll_class
->scrollbar_spacing
;
1803 if (scroll_window
->hscrollbar_visible
)
1805 // dh += hscrollbar->allocation.height;
1807 dh
+= scroll_class
->scrollbar_spacing
;
1811 if (width
) (*width
) = m_width
- dw
;
1812 if (height
) (*height
) = m_height
- dh
;
1816 void wxWindow::GetPosition( int *x
, int *y
) const
1818 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1824 void wxWindow::ClientToScreen( int *x
, int *y
)
1826 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1828 GdkWindow
*source
= (GdkWindow
*) NULL
;
1830 source
= m_wxwindow
->window
;
1832 source
= m_widget
->window
;
1836 gdk_window_get_origin( source
, &org_x
, &org_y
);
1840 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1842 org_x
+= m_widget
->allocation
.x
;
1843 org_y
+= m_widget
->allocation
.y
;
1847 wxPoint
pt(GetClientAreaOrigin());
1855 void wxWindow::ScreenToClient( int *x
, int *y
)
1857 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1859 GdkWindow
*source
= (GdkWindow
*) NULL
;
1861 source
= m_wxwindow
->window
;
1863 source
= m_widget
->window
;
1867 gdk_window_get_origin( source
, &org_x
, &org_y
);
1871 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1873 org_x
+= m_widget
->allocation
.x
;
1874 org_y
+= m_widget
->allocation
.y
;
1878 wxPoint
pt(GetClientAreaOrigin());
1886 void wxWindow::Centre( int direction
)
1888 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1897 m_parent
->GetSize( &p_w
, &p_h
);
1898 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) x
= (p_w
- m_width
) / 2;
1899 if (direction
& wxVERTICAL
== wxVERTICAL
) y
= (p_h
- m_height
) / 2;
1903 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) x
= (gdk_screen_width () - m_width
) / 2;
1904 if (direction
& wxVERTICAL
== wxVERTICAL
) y
= (gdk_screen_height () - m_height
) / 2;
1910 void wxWindow::Fit()
1912 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1916 wxNode
*node
= m_children
.First();
1919 wxWindow
*win
= (wxWindow
*)node
->Data();
1921 win
->GetPosition(&wx
, &wy
);
1922 win
->GetSize(&ww
, &wh
);
1923 if (wx
+ ww
> maxX
) maxX
= wx
+ ww
;
1924 if (wy
+ wh
> maxY
) maxY
= wy
+ wh
;
1926 node
= node
->Next();
1929 SetClientSize(maxX
+ 7, maxY
+ 14);
1932 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1934 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1942 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1944 // if (GetAutoLayout()) Layout();
1947 bool wxWindow::Show( bool show
)
1949 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, "invalid window" );
1952 gtk_widget_show( m_widget
);
1954 gtk_widget_hide( m_widget
);
1961 void wxWindow::Enable( bool enable
)
1963 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
1965 m_isEnabled
= enable
;
1967 gtk_widget_set_sensitive( m_widget
, enable
);
1968 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1971 int wxWindow::GetCharHeight() const
1973 wxCHECK_MSG( (m_widget
!= NULL
), 12, "invalid window" );
1975 wxCHECK_MSG( m_font
.Ok(), 12, "invalid font" );
1977 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1979 return font
->ascent
+ font
->descent
;
1982 int wxWindow::GetCharWidth() const
1984 wxCHECK_MSG( (m_widget
!= NULL
), 8, "invalid window" );
1986 wxCHECK_MSG( m_font
.Ok(), 8, "invalid font" );
1988 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1990 return gdk_string_width( font
, "H" );
1993 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1994 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1996 wxFont fontToUse
= m_font
;
1997 if (theFont
) fontToUse
= *theFont
;
1999 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
2001 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2002 if (x
) (*x
) = gdk_string_width( font
, string
);
2003 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2004 if (descent
) (*descent
) = font
->descent
;
2005 if (externalLeading
) (*externalLeading
) = 0; // ??
2008 void wxWindow::MakeModal( bool modal
)
2012 // Disable all other windows
2013 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
2015 wxNode
*node
= wxTopLevelWindows
.First();
2018 wxWindow
*win
= (wxWindow
*)node
->Data();
2019 if (win
!= this) win
->Enable(!modal
);
2021 node
= node
->Next();
2026 void wxWindow::SetFocus()
2028 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2030 GtkWidget
*connect_widget
= GetConnectWidget();
2033 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2035 gtk_widget_grab_focus (connect_widget
);
2037 else if (GTK_IS_CONTAINER(connect_widget
))
2039 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2047 wxWindow
*wxWindow::FindFocus()
2049 return g_focusWindow
;
2052 bool wxWindow::AcceptsFocus() const
2054 return IsEnabled() && IsShown() && m_acceptsFocus
;
2057 bool wxWindow::OnClose()
2062 void wxWindow::AddChild( wxWindow
*child
)
2064 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2065 wxCHECK_RET( (child
!= NULL
), "invalid child" );
2067 m_children
.Append( child
);
2070 wxWindow
*wxWindow::ReParent( wxWindow
*newParent
)
2072 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, "invalid window" );
2074 wxWindow
*oldParent
= GetParent();
2076 if (oldParent
) oldParent
->RemoveChild( this );
2078 gtk_widget_unparent( m_widget
);
2082 newParent
->AddChild( this );
2083 (newParent
->m_insertCallback
)( newParent
, this );
2089 void wxWindow::RemoveChild( wxWindow
*child
)
2091 m_children
.DeleteObject( child
);
2092 child
->m_parent
= (wxWindow
*) NULL
;
2095 void wxWindow::SetReturnCode( int retCode
)
2097 m_retCode
= retCode
;
2100 int wxWindow::GetReturnCode()
2105 void wxWindow::Raise()
2107 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2109 if (m_widget
) gdk_window_raise( m_widget
->window
);
2112 void wxWindow::Lower()
2114 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2116 if (m_widget
) gdk_window_lower( m_widget
->window
);
2119 wxEvtHandler
*wxWindow::GetEventHandler() const
2121 return m_eventHandler
;
2124 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
2126 m_eventHandler
= handler
;
2129 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
2131 handler
->SetNextHandler(GetEventHandler());
2132 SetEventHandler(handler
);
2135 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
2137 if (GetEventHandler())
2139 wxEvtHandler
*handlerA
= GetEventHandler();
2140 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
2141 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
2142 SetEventHandler(handlerB
);
2146 return (wxEvtHandler
*) NULL
;
2152 return (wxEvtHandler
*) NULL
;
2155 wxValidator
*wxWindow::GetValidator()
2157 return m_windowValidator
;
2160 void wxWindow::SetValidator( const wxValidator
& validator
)
2162 if (m_windowValidator
) delete m_windowValidator
;
2163 m_windowValidator
= validator
.Clone();
2164 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
2167 void wxWindow::SetClientObject( wxClientData
*data
)
2169 if (m_clientObject
) delete m_clientObject
;
2170 m_clientObject
= data
;
2173 wxClientData
*wxWindow::GetClientObject()
2175 return m_clientObject
;
2178 void wxWindow::SetClientData( void *data
)
2180 m_clientData
= data
;
2183 void *wxWindow::GetClientData()
2185 return m_clientData
;
2188 bool wxWindow::IsBeingDeleted()
2193 void wxWindow::SetId( wxWindowID id
)
2198 wxWindowID
wxWindow::GetId() const
2203 void wxWindow::SetCursor( const wxCursor
&cursor
)
2205 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2209 if (cursor
== *m_cursor
) return;
2214 *m_cursor
= *wxSTANDARD_CURSOR
;
2217 if ((m_widget
) && (m_widget
->window
))
2218 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
2220 if ((m_wxwindow
) && (m_wxwindow
->window
))
2221 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
2224 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2229 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2231 wxCHECK_RET( (m_widget
!= NULL
), "invalid window" );
2233 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2237 gdk_window_clear_area( m_wxwindow
->window
,
2251 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2253 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2257 GdkRectangle gdk_rect
;
2258 gdk_rect
.x
= rect
->x
;
2259 gdk_rect
.y
= rect
->y
;
2260 gdk_rect
.width
= rect
->width
;
2261 gdk_rect
.height
= rect
->height
;
2264 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2266 gtk_widget_draw( m_widget
, &gdk_rect
);
2270 wxRegion
wxWindow::GetUpdateRegion() const
2272 return m_updateRegion
;
2275 bool wxWindow::IsExposed( int x
, int y
) const
2277 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
2280 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
2282 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
2285 bool wxWindow::IsExposed( const wxPoint
& pt
) const
2287 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
2290 bool wxWindow::IsExposed( const wxRect
& rect
) const
2292 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
2295 void wxWindow::Clear()
2297 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2299 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
2302 wxColour
wxWindow::GetBackgroundColour() const
2304 return m_backgroundColour
;
2307 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
2309 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2311 if (m_backgroundColour
== colour
) return;
2313 m_backgroundColour
= colour
;
2314 if (!m_backgroundColour
.Ok()) return;
2318 GdkWindow
*window
= m_wxwindow
->window
;
2319 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2320 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2321 gdk_window_clear( window
);
2324 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2325 if (sysbg
.Red() == colour
.Red() &&
2326 sysbg
.Green() == colour
.Green() &&
2327 sysbg
.Blue() == colour
.Blue())
2329 m_backgroundColour
= wxNullColour
;
2331 m_backgroundColour
= sysbg
;
2339 wxColour
wxWindow::GetForegroundColour() const
2341 return m_foregroundColour
;
2344 void wxWindow::SetForegroundColour( const wxColour
&colour
)
2346 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2348 if (m_foregroundColour
== colour
) return;
2350 m_foregroundColour
= colour
;
2351 if (!m_foregroundColour
.Ok()) return;
2353 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2354 if (sysbg
.Red() == colour
.Red() &&
2355 sysbg
.Green() == colour
.Green() &&
2356 sysbg
.Blue() == colour
.Blue())
2358 m_backgroundColour
= wxNullColour
;
2360 m_backgroundColour
= sysbg
;
2368 GtkStyle
*wxWindow::GetWidgetStyle()
2370 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2374 gtk_widget_get_style( m_widget
) );
2376 return m_widgetStyle
;
2379 void wxWindow::SetWidgetStyle()
2381 GtkStyle
*style
= GetWidgetStyle();
2383 gdk_font_unref( style
->font
);
2384 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2386 if (m_foregroundColour
.Ok())
2388 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2389 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2390 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2391 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2394 if (m_backgroundColour
.Ok())
2396 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2397 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2398 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2399 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2400 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2401 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2402 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2403 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2404 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2408 void wxWindow::ApplyWidgetStyle()
2412 bool wxWindow::Validate()
2414 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2416 wxNode
*node
= m_children
.First();
2419 wxWindow
*child
= (wxWindow
*)node
->Data();
2420 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
2424 node
= node
->Next();
2429 bool wxWindow::TransferDataToWindow()
2431 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2433 wxNode
*node
= m_children
.First();
2436 wxWindow
*child
= (wxWindow
*)node
->Data();
2437 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2438 !child
->GetValidator()->TransferToWindow() )
2440 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2443 node
= node
->Next();
2448 bool wxWindow::TransferDataFromWindow()
2450 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2452 wxNode
*node
= m_children
.First();
2455 wxWindow
*child
= (wxWindow
*)node
->Data();
2456 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2460 node
= node
->Next();
2465 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2467 m_acceleratorTable
= accel
;
2470 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2472 TransferDataToWindow();
2475 void wxWindow::InitDialog()
2477 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2479 wxInitDialogEvent
event(GetId());
2480 event
.SetEventObject( this );
2481 GetEventHandler()->ProcessEvent(event
);
2484 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2486 menu
->SetInvokingWindow( win
);
2487 wxNode
*node
= menu
->m_items
.First();
2490 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2491 if (menuitem
->IsSubMenu())
2493 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2495 node
= node
->Next();
2499 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2501 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid window" );
2503 wxCHECK_MSG( menu
!= NULL
, FALSE
, "invalid popup-menu" );
2505 SetInvokingWindow( menu
, this );
2507 GTK_MENU(menu
->m_menu
),
2508 (GtkWidget
*)NULL
, // parent menu shell
2509 (GtkWidget
*)NULL
, // parent menu item
2510 (GtkMenuPositionFunc
)NULL
,
2511 NULL
, // client data
2512 0, // button used to activate it
2513 0//gs_timeLastClick // the time of activation
2518 #if wxUSE_DRAG_AND_DROP
2520 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2522 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2524 GtkWidget
*dnd_widget
= GetConnectWidget();
2526 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2528 if (m_dropTarget
) delete m_dropTarget
;
2529 m_dropTarget
= dropTarget
;
2531 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2534 wxDropTarget
*wxWindow::GetDropTarget() const
2536 return m_dropTarget
;
2541 GtkWidget
* wxWindow::GetConnectWidget()
2543 GtkWidget
*connect_widget
= m_widget
;
2544 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2546 return connect_widget
;
2549 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2551 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2552 return (window
== m_widget
->window
);
2555 void wxWindow::SetFont( const wxFont
&font
)
2557 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2559 if (((wxFont
*)&font
)->Ok())
2562 m_font
= *wxSWISS_FONT
;
2564 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2565 if (sysbg
.Red() == m_backgroundColour
.Red() &&
2566 sysbg
.Green() == m_backgroundColour
.Green() &&
2567 sysbg
.Blue() == m_backgroundColour
.Blue())
2569 m_backgroundColour
= wxNullColour
;
2571 m_backgroundColour
= sysbg
;
2579 void wxWindow::SetWindowStyleFlag( long flag
)
2581 m_windowStyle
= flag
;
2584 long wxWindow::GetWindowStyleFlag() const
2586 return m_windowStyle
;
2589 void wxWindow::CaptureMouse()
2591 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2593 wxCHECK_RET( g_capturing
== FALSE
, "CaptureMouse called twice" );
2595 GtkWidget
*connect_widget
= GetConnectWidget();
2596 gtk_grab_add( connect_widget
);
2597 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2599 (GDK_BUTTON_PRESS_MASK
|
2600 GDK_BUTTON_RELEASE_MASK
|
2601 GDK_POINTER_MOTION_MASK
),
2608 void wxWindow::ReleaseMouse()
2610 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2612 wxCHECK_RET( g_capturing
== TRUE
, "ReleaseMouse called twice" );
2614 GtkWidget
*connect_widget
= GetConnectWidget();
2615 gtk_grab_remove( connect_widget
);
2616 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2617 g_capturing
= FALSE
;
2620 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2624 wxString
wxWindow::GetTitle() const
2626 return (wxString
&)m_windowName
;
2629 wxString
wxWindow::GetLabel() const
2634 void wxWindow::SetName( const wxString
&name
)
2636 m_windowName
= name
;
2639 wxString
wxWindow::GetName() const
2641 return (wxString
&)m_windowName
;
2644 bool wxWindow::IsShown() const
2649 bool wxWindow::IsRetained()
2654 wxWindow
*wxWindow::FindWindow( long id
)
2656 if (id
== m_windowId
) return this;
2657 wxNode
*node
= m_children
.First();
2660 wxWindow
*child
= (wxWindow
*)node
->Data();
2661 wxWindow
*res
= child
->FindWindow( id
);
2662 if (res
) return res
;
2663 node
= node
->Next();
2665 return (wxWindow
*) NULL
;
2668 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2670 if (name
== m_windowName
) return this;
2671 wxNode
*node
= m_children
.First();
2674 wxWindow
*child
= (wxWindow
*)node
->Data();
2675 wxWindow
*res
= child
->FindWindow( name
);
2676 if (res
) return res
;
2677 node
= node
->Next();
2679 return (wxWindow
*) NULL
;
2682 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2683 int range
, bool refresh
)
2685 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2687 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2689 m_hasScrolling
= TRUE
;
2691 if (orient
== wxHORIZONTAL
)
2693 float fpos
= (float)pos
;
2694 float frange
= (float)range
;
2695 float fthumb
= (float)thumbVisible
;
2696 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2697 if (fpos
< 0.0) fpos
= 0.0;
2699 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2700 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2702 SetScrollPos( orient
, pos
, refresh
);
2706 m_oldHorizontalPos
= fpos
;
2708 m_hAdjust
->lower
= 0.0;
2709 m_hAdjust
->upper
= frange
;
2710 m_hAdjust
->value
= fpos
;
2711 m_hAdjust
->step_increment
= 1.0;
2712 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2713 m_hAdjust
->page_size
= fthumb
;
2717 float fpos
= (float)pos
;
2718 float frange
= (float)range
;
2719 float fthumb
= (float)thumbVisible
;
2720 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2721 if (fpos
< 0.0) fpos
= 0.0;
2723 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2724 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2726 SetScrollPos( orient
, pos
, refresh
);
2730 m_oldVerticalPos
= fpos
;
2732 m_vAdjust
->lower
= 0.0;
2733 m_vAdjust
->upper
= frange
;
2734 m_vAdjust
->value
= fpos
;
2735 m_vAdjust
->step_increment
= 1.0;
2736 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2737 m_vAdjust
->page_size
= fthumb
;
2740 if (m_wxwindow
->window
)
2742 if (orient
== wxHORIZONTAL
)
2743 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2745 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2747 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2751 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2753 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2755 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2757 if (orient
== wxHORIZONTAL
)
2759 float fpos
= (float)pos
;
2760 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2761 if (fpos
< 0.0) fpos
= 0.0;
2762 m_oldHorizontalPos
= fpos
;
2764 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2765 m_hAdjust
->value
= fpos
;
2769 float fpos
= (float)pos
;
2770 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2771 if (fpos
< 0.0) fpos
= 0.0;
2772 m_oldVerticalPos
= fpos
;
2774 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2775 m_vAdjust
->value
= fpos
;
2780 if (m_wxwindow
->window
)
2782 if (orient
== wxHORIZONTAL
)
2783 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2785 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2790 int wxWindow::GetScrollThumb( int orient
) const
2792 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
2794 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
2796 if (orient
== wxHORIZONTAL
)
2797 return (int)(m_hAdjust
->page_size
+0.5);
2799 return (int)(m_vAdjust
->page_size
+0.5);
2802 int wxWindow::GetScrollPos( int orient
) const
2804 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
2806 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
2808 if (orient
== wxHORIZONTAL
)
2809 return (int)(m_hAdjust
->value
+0.5);
2811 return (int)(m_vAdjust
->value
+0.5);
2814 int wxWindow::GetScrollRange( int orient
) const
2816 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid window" );
2818 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, "window needs client area for scrolling" );
2820 if (orient
== wxHORIZONTAL
)
2821 return (int)(m_hAdjust
->upper
+0.5);
2823 return (int)(m_vAdjust
->upper
+0.5);
2826 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2828 wxCHECK_RET( m_widget
!= NULL
, "invalid window" );
2830 wxCHECK_RET( m_wxwindow
!= NULL
, "window needs client area for scrolling" );
2834 GetClientSize( &cw
, &ch
);
2836 int w
= cw
- abs(dx
);
2837 int h
= ch
- abs(dy
);
2838 if ((h
< 0) || (w
< 0))
2845 if (dx
< 0) s_x
= -dx
;
2846 if (dy
< 0) s_y
= -dy
;
2849 if (dx
> 0) d_x
= dx
;
2850 if (dy
> 0) d_y
= dy
;
2854 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2855 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2858 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2859 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2862 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2863 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2864 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2865 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2867 Refresh( TRUE
, &rect
);
2870 //-------------------------------------------------------------------------------------
2872 //-------------------------------------------------------------------------------------
2874 wxLayoutConstraints
*wxWindow::GetConstraints() const
2876 return m_constraints
;
2879 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2883 UnsetConstraints(m_constraints
);
2884 delete m_constraints
;
2886 m_constraints
= constraints
;
2889 // Make sure other windows know they're part of a 'meaningful relationship'
2890 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2891 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2892 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2893 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2894 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2895 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2896 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2897 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2898 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2899 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2900 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2901 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2902 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2903 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2904 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2905 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2911 void wxWindow::SetAutoLayout( bool autoLayout
)
2913 m_autoLayout
= autoLayout
;
2916 bool wxWindow::GetAutoLayout() const
2918 return m_autoLayout
;
2921 wxSizer
*wxWindow::GetSizer() const
2923 return m_windowSizer
;
2926 void wxWindow::SetSizerParent( wxWindow
*win
)
2928 m_sizerParent
= win
;
2931 wxWindow
*wxWindow::GetSizerParent() const
2933 return m_sizerParent
;
2936 // This removes any dangling pointers to this window
2937 // in other windows' constraintsInvolvedIn lists.
2938 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2942 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2943 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2944 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2945 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2946 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2947 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2948 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2949 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2950 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2951 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2952 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2953 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2954 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2955 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2956 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2957 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2961 // Back-pointer to other windows we're involved with, so if we delete
2962 // this window, we must delete any constraints we're involved with.
2963 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2965 if (!m_constraintsInvolvedIn
)
2966 m_constraintsInvolvedIn
= new wxList
;
2967 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2968 m_constraintsInvolvedIn
->Append(otherWin
);
2971 // REMOVE back-pointer to other windows we're involved with.
2972 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2974 if (m_constraintsInvolvedIn
)
2975 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2978 // Reset any constraints that mention this window
2979 void wxWindow::DeleteRelatedConstraints()
2981 if (m_constraintsInvolvedIn
)
2983 wxNode
*node
= m_constraintsInvolvedIn
->First();
2986 wxWindow
*win
= (wxWindow
*)node
->Data();
2987 wxNode
*next
= node
->Next();
2988 wxLayoutConstraints
*constr
= win
->GetConstraints();
2990 // Reset any constraints involving this window
2993 constr
->left
.ResetIfWin((wxWindow
*)this);
2994 constr
->top
.ResetIfWin((wxWindow
*)this);
2995 constr
->right
.ResetIfWin((wxWindow
*)this);
2996 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2997 constr
->width
.ResetIfWin((wxWindow
*)this);
2998 constr
->height
.ResetIfWin((wxWindow
*)this);
2999 constr
->centreX
.ResetIfWin((wxWindow
*)this);
3000 constr
->centreY
.ResetIfWin((wxWindow
*)this);
3005 delete m_constraintsInvolvedIn
;
3006 m_constraintsInvolvedIn
= (wxList
*) NULL
;
3010 void wxWindow::SetSizer(wxSizer
*sizer
)
3012 m_windowSizer
= sizer
;
3014 sizer
->SetSizerParent((wxWindow
*)this);
3021 bool wxWindow::Layout()
3023 if (GetConstraints())
3026 GetClientSize(&w
, &h
);
3027 GetConstraints()->width
.SetValue(w
);
3028 GetConstraints()->height
.SetValue(h
);
3031 // If top level (one sizer), evaluate the sizer's constraints.
3035 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
3036 GetSizer()->LayoutPhase1(&noChanges
);
3037 GetSizer()->LayoutPhase2(&noChanges
);
3038 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
3043 // Otherwise, evaluate child constraints
3044 ResetConstraints(); // Mark all constraints as unevaluated
3045 DoPhase(1); // Just one phase need if no sizers involved
3047 SetConstraintSizes(); // Recursively set the real window sizes
3053 // Do a phase of evaluating constraints:
3054 // the default behaviour. wxSizers may do a similar
3055 // thing, but also impose their own 'constraints'
3056 // and order the evaluation differently.
3057 bool wxWindow::LayoutPhase1(int *noChanges
)
3059 wxLayoutConstraints
*constr
= GetConstraints();
3062 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
3068 bool wxWindow::LayoutPhase2(int *noChanges
)
3078 // Do a phase of evaluating child constraints
3079 bool wxWindow::DoPhase(int phase
)
3081 int noIterations
= 0;
3082 int maxIterations
= 500;
3086 while ((noChanges
> 0) && (noIterations
< maxIterations
))
3090 wxNode
*node
= m_children
.First();
3093 wxWindow
*child
= (wxWindow
*)node
->Data();
3094 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
3096 wxLayoutConstraints
*constr
= child
->GetConstraints();
3099 if (succeeded
.Member(child
))
3104 int tempNoChanges
= 0;
3105 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
3106 noChanges
+= tempNoChanges
;
3109 succeeded
.Append(child
);
3114 node
= node
->Next();
3121 void wxWindow::ResetConstraints()
3123 wxLayoutConstraints
*constr
= GetConstraints();
3126 constr
->left
.SetDone(FALSE
);
3127 constr
->top
.SetDone(FALSE
);
3128 constr
->right
.SetDone(FALSE
);
3129 constr
->bottom
.SetDone(FALSE
);
3130 constr
->width
.SetDone(FALSE
);
3131 constr
->height
.SetDone(FALSE
);
3132 constr
->centreX
.SetDone(FALSE
);
3133 constr
->centreY
.SetDone(FALSE
);
3135 wxNode
*node
= m_children
.First();
3138 wxWindow
*win
= (wxWindow
*)node
->Data();
3139 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
3140 win
->ResetConstraints();
3141 node
= node
->Next();
3145 // Need to distinguish between setting the 'fake' size for
3146 // windows and sizers, and setting the real values.
3147 void wxWindow::SetConstraintSizes(bool recurse
)
3149 wxLayoutConstraints
*constr
= GetConstraints();
3150 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
3151 constr
->width
.GetDone() && constr
->height
.GetDone())
3153 int x
= constr
->left
.GetValue();
3154 int y
= constr
->top
.GetValue();
3155 int w
= constr
->width
.GetValue();
3156 int h
= constr
->height
.GetValue();
3158 // If we don't want to resize this window, just move it...
3159 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
3160 (constr
->height
.GetRelationship() != wxAsIs
))
3162 // Calls Layout() recursively. AAAGH. How can we stop that.
3163 // Simply take Layout() out of non-top level OnSizes.
3164 SizerSetSize(x
, y
, w
, h
);
3173 char *windowClass
= this->GetClassInfo()->GetClassName();
3176 if (GetName() == "")
3177 winName
= "unnamed";
3179 winName
= GetName();
3180 wxLogDebug( "Constraint(s) not satisfied for window of type %s, name %s:\n",
3181 (const char *)windowClass
,
3182 (const char *)winName
);
3183 if (!constr
->left
.GetDone()) wxLogDebug( " unsatisfied 'left' constraint.\n" );
3184 if (!constr
->right
.GetDone()) wxLogDebug( " unsatisfied 'right' constraint.\n" );
3185 if (!constr
->width
.GetDone()) wxLogDebug( " unsatisfied 'width' constraint.\n" );
3186 if (!constr
->height
.GetDone()) wxLogDebug( " unsatisfied 'height' constraint.\n" );
3187 wxLogDebug( "Please check constraints: try adding AsIs() constraints.\n" );
3192 wxNode
*node
= m_children
.First();
3195 wxWindow
*win
= (wxWindow
*)node
->Data();
3196 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
3197 win
->SetConstraintSizes();
3198 node
= node
->Next();
3203 // This assumes that all sizers are 'on' the same
3204 // window, i.e. the parent of this window.
3205 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
3207 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
3208 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
3212 m_sizerParent
->GetPosition(&xp
, &yp
);
3213 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
3218 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
3222 TransformSizerToActual(&xx
, &yy
);
3223 SetSize(xx
, yy
, w
, h
);
3226 void wxWindow::SizerMove(int x
, int y
)
3230 TransformSizerToActual(&xx
, &yy
);
3234 // Only set the size/position of the constraint (if any)
3235 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
3237 wxLayoutConstraints
*constr
= GetConstraints();
3242 constr
->left
.SetValue(x
);
3243 constr
->left
.SetDone(TRUE
);
3247 constr
->top
.SetValue(y
);
3248 constr
->top
.SetDone(TRUE
);
3252 constr
->width
.SetValue(w
);
3253 constr
->width
.SetDone(TRUE
);
3257 constr
->height
.SetValue(h
);
3258 constr
->height
.SetDone(TRUE
);
3263 void wxWindow::MoveConstraint(int x
, int y
)
3265 wxLayoutConstraints
*constr
= GetConstraints();
3270 constr
->left
.SetValue(x
);
3271 constr
->left
.SetDone(TRUE
);
3275 constr
->top
.SetValue(y
);
3276 constr
->top
.SetDone(TRUE
);
3281 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
3283 wxLayoutConstraints
*constr
= GetConstraints();
3286 *w
= constr
->width
.GetValue();
3287 *h
= constr
->height
.GetValue();
3293 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
3295 wxLayoutConstraints
*constr
= GetConstraints();
3298 *w
= constr
->width
.GetValue();
3299 *h
= constr
->height
.GetValue();
3302 GetClientSize(w
, h
);
3305 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
3307 wxLayoutConstraints
*constr
= GetConstraints();
3310 *x
= constr
->left
.GetValue();
3311 *y
= constr
->top
.GetValue();
3317 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )