1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "window.h"
17 #include "wx/window.h"
21 #include "wx/layout.h"
23 #include "wx/dialog.h"
24 #include "wx/msgdlg.h"
25 #include "wx/dcclient.h"
29 #include "wx/notebook.h"
30 #include "wx/statusbr.h"
32 #include "wx/gtk/win_gtk.h"
33 #include "gdk/gdkprivate.h"
34 #include "gdk/gdkkeysyms.h"
38 //-----------------------------------------------------------------------------
39 // documentation on internals
40 //-----------------------------------------------------------------------------
43 I have been asked several times about writing some documentation about
44 the GTK port of wxWindows, especially its internal structures. Obviously,
45 you cannot understand wxGTK without knowing a little about the GTK, but
46 some more information about what the wxWindow, which is the base class
47 for all other window classes, does seems required as well.
49 What does wxWindow do? It contains the common interface for the following
50 jobs of its descentants:
52 1) Define the rudimentary behaviour common to all window classes, such as
53 resizing, intercepting user input so as to make it possible to use these
54 events for special purposes in a derived class, window names etc.
56 2) Provide the possibility to contain and manage children, if the derived
57 class is allowed to contain children, which holds true for those window
58 classes, which do not display a native GTK widget. To name them, these
59 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
60 work classes are a special case and are handled a bit differently from
63 3) Provide the possibility to draw into a client area of a window. This,
64 too, only holds true for classes that do not display a native GTK widget
67 4) Provide the entire mechanism for scrolling widgets. This actaul inter-
68 face for this is usually in wxScrolledWidget, but the GTK implementation
71 5) A multitude of helper or extra methods for special purposes, such as
72 Drag'n'Drop, managing validators etc.
74 Normally one might expect, that one wxWindows class would always contain
75 one GTK widget. Under GTK, there is no such allround widget that has all
76 the functionality. Moreover, the GTK defines a client area as a different
77 widget from the actual widget you are handling. Last but not least some
78 special classes (e.g. wxFrame) handle different categories of widgets and
79 still have the possibility to draw something in the client area.
80 It was therefore required to write a special purpose GTK widget, that would
81 represent a client area in the sense of wxWindows capable to do the jobs
82 2), 3) and 4). I have written this class and it resides in win_gtk.c of
85 All windows must have a widget, with which they interact with other under-
86 lying GTK widget. It is this widget, e.g. that has to be resized etc and
87 thw wxWindow class has a member variable called m_widget which holds a
88 pointer to this widget. When the window class displays a GTK native widget,
89 this is the only GTK widget the class manages. When the class has a client
90 area for drawing into and for containing children it must have at least
91 one more GTK widget to handle (of the type GtkMyFixed, defined in win_gtk.c),
92 but there can be any number of widgets, handled by a class (e.g. the frame
93 class handles three). The common rule for all windows is only, that the
94 widget that interacts with the rest of GTK must be referenced in m_widget
95 and all other widgets must be children of this widget on the GTK level.
96 The top-most widget, which also represents the client area, must be in
97 the m_wxwindow field and must be of the type GtkMyFixed.
99 As I said, the window classes that display a GTK native widget only have
100 one widget, so in the case of e.g. the wxButton class m_widget holds a
101 pointer to a GtkButton widget. But windows with client areas (for drawing
102 and children) have a m_widget field that is a pointer to a GtkScrolled-
103 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
104 one is (in the GTK sense) a child of the GtkScrolledWindow.
106 If the m_wxwindow field is set, then all input to this widget is inter-
107 cepted and sent to the wxWindows class. If not, all input to the widget
108 that gets pointed to by m_widget gets intercepted and sent to the class.
112 //-----------------------------------------------------------------------------
114 //-----------------------------------------------------------------------------
116 extern wxList wxPendingDelete
;
117 extern wxList wxTopLevelWindows
;
118 extern bool g_blockEventsOnDrag
;
119 static bool g_capturing
= FALSE
;
121 // hack: we need something to pass to gtk_menu_popup, so we store the time of
122 // the last click here
123 static guint32 gs_timeLastClick
= 0;
125 //-----------------------------------------------------------------------------
126 // "expose_event" (of m_wxwindow, not of m_widget)
127 //-----------------------------------------------------------------------------
129 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
131 if (!win
->HasVMT()) return;
132 if (g_blockEventsOnDrag
) return;
134 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
136 gdk_event
->area
.width
,
137 gdk_event
->area
.height
);
139 if (gdk_event
->count
> 0) return;
142 printf( "OnExpose from " );
143 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
144 printf( win->GetClassInfo()->GetClassName() );
148 wxPaintEvent
event( win
->GetId() );
149 event
.SetEventObject( win
);
150 win
->GetEventHandler()->ProcessEvent( event
);
152 win
->m_updateRegion
.Clear();
155 //-----------------------------------------------------------------------------
156 // "draw" (of m_wxwindow, not of m_widget)
157 //-----------------------------------------------------------------------------
159 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
161 if (!win
->HasVMT()) return;
162 if (g_blockEventsOnDrag
) return;
164 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
166 wxPaintEvent
event( win
->GetId() );
167 event
.SetEventObject( win
);
168 win
->GetEventHandler()->ProcessEvent( event
);
170 win
->m_updateRegion
.Clear();
173 //-----------------------------------------------------------------------------
175 //-----------------------------------------------------------------------------
177 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
179 if (!win
->HasVMT()) return FALSE
;
180 if (g_blockEventsOnDrag
) return FALSE
;
183 printf( "OnKeyPress from " );
184 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
185 printf( win->GetClassInfo()->GetClassName() );
190 switch (gdk_event
->keyval
)
192 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
193 case GDK_Tab
: key_code
= WXK_TAB
; break;
194 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
195 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
196 case GDK_Return
: key_code
= WXK_RETURN
; break;
197 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
198 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
199 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
200 case GDK_Delete
: key_code
= WXK_DELETE
; break;
201 case GDK_Home
: key_code
= WXK_HOME
; break;
202 case GDK_Left
: key_code
= WXK_LEFT
; break;
203 case GDK_Up
: key_code
= WXK_UP
; break;
204 case GDK_Right
: key_code
= WXK_RIGHT
; break;
205 case GDK_Down
: key_code
= WXK_DOWN
; break;
206 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
207 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
208 case GDK_Next
: key_code
= WXK_NEXT
; break;
209 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
210 case GDK_End
: key_code
= WXK_END
; break;
211 case GDK_Begin
: key_code
= WXK_HOME
; break;
212 case GDK_Select
: key_code
= WXK_SELECT
; break;
213 case GDK_Print
: key_code
= WXK_PRINT
; break;
214 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
215 case GDK_Insert
: key_code
= WXK_INSERT
; break;
216 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
217 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
218 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
219 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
220 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
221 case GDK_KP_Up
: key_code
= WXK_UP
; break;
222 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
223 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
224 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
225 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
226 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
227 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
228 case GDK_KP_End
: key_code
= WXK_END
; break;
229 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
230 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
231 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
232 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
233 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
234 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
235 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
236 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
237 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
238 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
239 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
240 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
241 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
242 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
243 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
244 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
245 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
246 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
247 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
248 case GDK_F1
: key_code
= WXK_F1
; break;
249 case GDK_F2
: key_code
= WXK_F2
; break;
250 case GDK_F3
: key_code
= WXK_F3
; break;
251 case GDK_F4
: key_code
= WXK_F4
; break;
252 case GDK_F5
: key_code
= WXK_F5
; break;
253 case GDK_F6
: key_code
= WXK_F6
; break;
254 case GDK_F7
: key_code
= WXK_F7
; break;
255 case GDK_F8
: key_code
= WXK_F8
; break;
256 case GDK_F9
: key_code
= WXK_F9
; break;
257 case GDK_F10
: key_code
= WXK_F10
; break;
258 case GDK_F11
: key_code
= WXK_F11
; break;
259 case GDK_F12
: key_code
= WXK_F12
; break;
262 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
263 key_code
= gdk_event
->keyval
;
267 if (!key_code
) return FALSE
;
269 wxKeyEvent
event( wxEVT_CHAR
);
270 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
271 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
272 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
273 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
274 event
.m_keyCode
= key_code
;
277 event
.SetEventObject( win
);
279 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
283 wxWindow
*ancestor
= win
;
286 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
289 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
290 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
293 ancestor
= ancestor
->GetParent();
299 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
300 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
306 //-----------------------------------------------------------------------------
307 // "button_press_event"
308 //-----------------------------------------------------------------------------
310 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
312 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
314 if (g_blockEventsOnDrag
) return TRUE
;
318 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
320 gtk_widget_grab_focus (win
->m_wxwindow
);
323 printf( "GrabFocus from " );
324 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
325 printf( win->GetClassInfo()->GetClassName() );
332 if (!win
->HasVMT()) return TRUE
;
335 printf( "OnButtonPress from " );
336 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
337 printf( win->GetClassInfo()->GetClassName() );
341 wxEventType event_type
= wxEVT_LEFT_DOWN
;
343 if (gdk_event
->button
== 1)
345 switch (gdk_event
->type
)
347 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
348 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
352 else if (gdk_event
->button
== 2)
354 switch (gdk_event
->type
)
356 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
357 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
361 else if (gdk_event
->button
== 3)
363 switch (gdk_event
->type
)
365 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
366 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
371 wxMouseEvent
event( event_type
);
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_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
377 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
378 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
380 event
.m_x
= (long)gdk_event
->x
;
381 event
.m_y
= (long)gdk_event
->y
;
383 // Some control don't have their own X window and thus cannot get
388 wxNode
*node
= win
->GetChildren()->First();
391 wxWindow
*child
= (wxWindow
*)node
->Data();
392 if ((child
->m_x
<= event
.m_x
) &&
393 (child
->m_y
<= event
.m_y
) &&
394 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
395 (child
->m_y
+child
->m_height
>= event
.m_y
))
398 event
.m_x
-= child
->m_x
;
399 event
.m_y
-= child
->m_y
;
406 event
.SetEventObject( win
);
408 gs_timeLastClick
= gdk_event
->time
;
410 if (win
->GetEventHandler()->ProcessEvent( event
))
411 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
416 //-----------------------------------------------------------------------------
417 // "button_release_event"
418 //-----------------------------------------------------------------------------
420 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
422 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
424 if (g_blockEventsOnDrag
) return TRUE
;
426 if (!win
->HasVMT()) return TRUE
;
429 printf( "OnButtonRelease from " );
430 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
431 printf( win->GetClassInfo()->GetClassName() );
435 wxEventType event_type
= wxEVT_NULL
;
437 switch (gdk_event
->button
)
439 case 1: event_type
= wxEVT_LEFT_UP
; break;
440 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
441 case 3: event_type
= wxEVT_RIGHT_UP
; break;
444 wxMouseEvent
event( event_type
);
445 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
446 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
447 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
448 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
449 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
450 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
451 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
452 event
.m_x
= (long)gdk_event
->x
;
453 event
.m_y
= (long)gdk_event
->y
;
455 // Some control don't have their own X window and thus cannot get
460 wxNode
*node
= win
->GetChildren()->First();
463 wxWindow
*child
= (wxWindow
*)node
->Data();
464 if ((child
->m_x
<= event
.m_x
) &&
465 (child
->m_y
<= event
.m_y
) &&
466 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
467 (child
->m_y
+child
->m_height
>= event
.m_y
))
470 event
.m_x
-= child
->m_x
;
471 event
.m_y
-= child
->m_y
;
478 event
.SetEventObject( win
);
480 if (win
->GetEventHandler()->ProcessEvent( event
))
481 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
486 //-----------------------------------------------------------------------------
487 // "motion_notify_event"
488 //-----------------------------------------------------------------------------
490 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
492 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
494 if (g_blockEventsOnDrag
) return TRUE
;
496 if (!win
->HasVMT()) return TRUE
;
499 printf( "OnMotion from " );
500 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
501 printf( win->GetClassInfo()->GetClassName() );
505 wxMouseEvent
event( wxEVT_MOTION
);
506 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
507 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
508 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
509 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
510 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
511 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
512 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
514 event
.m_x
= (long)gdk_event
->x
;
515 event
.m_y
= (long)gdk_event
->y
;
517 // Some control don't have their own X window and thus cannot get
522 wxNode
*node
= win
->GetChildren()->First();
525 wxWindow
*child
= (wxWindow
*)node
->Data();
526 if ((child
->m_x
<= event
.m_x
) &&
527 (child
->m_y
<= event
.m_y
) &&
528 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
529 (child
->m_y
+child
->m_height
>= event
.m_y
))
532 event
.m_x
-= child
->m_x
;
533 event
.m_y
-= child
->m_y
;
540 event
.SetEventObject( win
);
542 if (win
->GetEventHandler()->ProcessEvent( event
))
543 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
548 //-----------------------------------------------------------------------------
550 //-----------------------------------------------------------------------------
552 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
554 if (g_blockEventsOnDrag
) return TRUE
;
557 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
559 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
561 printf( "SetFocus flag from " );
562 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
563 printf( win->GetClassInfo()->GetClassName() );
569 if (!win
->HasVMT()) return TRUE
;
572 printf( "OnSetFocus from " );
573 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
574 printf( win->GetClassInfo()->GetClassName() );
576 printf( WXSTRINGCAST win->GetLabel() );
580 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
581 event
.SetEventObject( win
);
583 if (win
->GetEventHandler()->ProcessEvent( event
))
584 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
589 //-----------------------------------------------------------------------------
591 //-----------------------------------------------------------------------------
593 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
595 if (g_blockEventsOnDrag
) return TRUE
;
598 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
599 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
602 if (!win
->HasVMT()) return TRUE
;
605 printf( "OnKillFocus from " );
606 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
607 printf( win->GetClassInfo()->GetClassName() );
611 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
612 event
.SetEventObject( win
);
614 if (win
->GetEventHandler()->ProcessEvent( event
))
615 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
620 //-----------------------------------------------------------------------------
621 // "enter_notify_event"
622 //-----------------------------------------------------------------------------
624 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
626 if (widget
->window
!= gdk_event
->window
) return TRUE
;
628 if (g_blockEventsOnDrag
) return TRUE
;
630 if (!win
->HasVMT()) return TRUE
;
633 printf( "OnEnter from " );
634 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
635 printf( win->GetClassInfo()->GetClassName() );
639 if ((widget
->window
) && (win
->m_cursor
))
640 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
642 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
643 event
.SetEventObject( win
);
645 if (win
->GetEventHandler()->ProcessEvent( event
))
646 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
651 //-----------------------------------------------------------------------------
652 // "leave_notify_event"
653 //-----------------------------------------------------------------------------
655 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
657 if (widget
->window
!= gdk_event
->window
) return TRUE
;
659 if (g_blockEventsOnDrag
) return TRUE
;
661 if (!win
->HasVMT()) return TRUE
;
664 printf( "OnLeave from " );
665 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
666 printf( win->GetClassInfo()->GetClassName() );
670 if ((widget
->window
) && (win
->m_cursor
))
671 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
673 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
674 event
.SetEventObject( win
);
676 if (win
->GetEventHandler()->ProcessEvent( event
))
677 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
682 //-----------------------------------------------------------------------------
683 // "value_changed" from m_vAdjust
684 //-----------------------------------------------------------------------------
686 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
688 if (g_blockEventsOnDrag
) return;
691 printf( "OnVScroll from " );
692 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
693 printf( win->GetClassInfo()->GetClassName() );
697 if (!win
->HasVMT()) return;
699 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
700 if (fabs(diff
) < 0.2) return;
702 wxEventType command
= wxEVT_NULL
;
704 float line_step
= win
->m_vAdjust
->step_increment
;
705 float page_step
= win
->m_vAdjust
->page_increment
;
707 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
708 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
709 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
710 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
711 else command
= wxEVT_SCROLL_THUMBTRACK
;
713 int value
= (int)(win
->m_vAdjust
->value
+0.5);
715 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
716 event
.SetEventObject( win
);
717 win
->GetEventHandler()->ProcessEvent( event
);
720 //-----------------------------------------------------------------------------
721 // "value_changed" from m_hAdjust
722 //-----------------------------------------------------------------------------
724 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
726 if (g_blockEventsOnDrag
) return;
729 printf( "OnHScroll from " );
730 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
731 printf( win->GetClassInfo()->GetClassName() );
735 if (!win
->HasVMT()) return;
737 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
738 if (fabs(diff
) < 0.2) return;
740 wxEventType command
= wxEVT_NULL
;
742 float line_step
= win
->m_hAdjust
->step_increment
;
743 float page_step
= win
->m_hAdjust
->page_increment
;
745 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
746 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
747 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
748 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
749 else command
= wxEVT_SCROLL_THUMBTRACK
;
751 int value
= (int)(win
->m_hAdjust
->value
+0.5);
753 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
754 event
.SetEventObject( win
);
755 win
->GetEventHandler()->ProcessEvent( event
);
758 //-----------------------------------------------------------------------------
759 // "changed" from m_vAdjust
760 //-----------------------------------------------------------------------------
762 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
764 if (g_blockEventsOnDrag
) return;
767 printf( "OnVScroll change from " );
768 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
769 printf( win->GetClassInfo()->GetClassName() );
773 if (!win
->HasVMT()) return;
775 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
776 int value
= (int)(win
->m_vAdjust
->value
+0.5);
778 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
779 event
.SetEventObject( win
);
780 win
->GetEventHandler()->ProcessEvent( event
);
783 //-----------------------------------------------------------------------------
784 // "changed" from m_hAdjust
785 //-----------------------------------------------------------------------------
787 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
789 if (g_blockEventsOnDrag
) return;
792 printf( "OnHScroll change from " );
793 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
794 printf( win->GetClassInfo()->GetClassName() );
798 if (!win
->HasVMT()) return;
800 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
801 int value
= (int)(win
->m_hAdjust
->value
+0.5);
803 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
804 event
.SetEventObject( win
);
805 win
->GetEventHandler()->ProcessEvent( event
);
808 //-----------------------------------------------------------------------------
809 // "button_press_event" from scrollbar
810 //-----------------------------------------------------------------------------
812 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
814 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
816 win
->m_isScrolling
= TRUE
;
821 //-----------------------------------------------------------------------------
822 // "button_release_event" from scrollbar
823 //-----------------------------------------------------------------------------
825 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
827 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
829 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
831 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
832 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
834 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
836 win
->m_isScrolling
= FALSE
;
841 //-----------------------------------------------------------------------------
842 // "drop_data_available_event"
843 //-----------------------------------------------------------------------------
845 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
847 if (!win
->HasVMT()) return;
849 if (win
->GetDropTarget())
853 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
854 win
->GetDropTarget()->Drop( event
, x
, y
);
858 g_free (event->dropdataavailable.data);
859 g_free (event->dropdataavailable.data_type);
863 //-----------------------------------------------------------------------------
865 //-----------------------------------------------------------------------------
867 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
869 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
870 EVT_SIZE(wxWindow::OnSize
)
871 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
872 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
873 EVT_IDLE(wxWindow::OnIdle
)
878 m_widget
= (GtkWidget
*) NULL
;
879 m_wxwindow
= (GtkWidget
*) NULL
;
880 m_parent
= (wxWindow
*) NULL
;
881 m_children
.DeleteContents( FALSE
);
891 m_eventHandler
= this;
892 m_windowValidator
= (wxValidator
*) NULL
;
894 m_cursor
= (wxCursor
*) NULL
;
895 m_font
= *wxSWISS_FONT
;
897 m_windowName
= "noname";
898 m_constraints
= (wxLayoutConstraints
*) NULL
;
899 m_constraintsInvolvedIn
= (wxList
*) NULL
;
900 m_windowSizer
= (wxSizer
*) NULL
;
901 m_sizerParent
= (wxWindow
*) NULL
;
902 m_autoLayout
= FALSE
;
906 m_hasScrolling
= FALSE
;
907 m_isScrolling
= FALSE
;
908 m_hAdjust
= (GtkAdjustment
*) NULL
;
909 m_vAdjust
= (GtkAdjustment
*) NULL
;
910 m_oldHorizontalPos
= 0.0;
911 m_oldVerticalPos
= 0.0;
914 m_pDropTarget
= (wxDropTarget
*) NULL
;
916 m_hasOwnStyle
= FALSE
;
919 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
920 const wxPoint
&pos
, const wxSize
&size
,
921 long style
, const wxString
&name
)
927 m_cursor
= (wxCursor
*) NULL
;
929 PreCreation( parent
, id
, pos
, size
, style
, name
);
931 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
932 m_hasScrolling
= TRUE
;
934 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
936 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
937 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
939 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
940 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
942 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
943 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
945 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
946 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
948 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
949 scroll_class
->scrollbar_spacing
= 0;
951 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
953 m_oldHorizontalPos
= 0.0;
954 m_oldVerticalPos
= 0.0;
956 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
957 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
959 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
960 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
961 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
962 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
964 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
965 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
966 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
967 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
969 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
971 if (m_windowStyle
& wxRAISED_BORDER
)
973 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
975 else if (m_windowStyle
& wxSUNKEN_BORDER
)
977 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
981 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
984 m_wxwindow
= gtk_myfixed_new();
986 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
988 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
989 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
991 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
993 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
995 // shut the viewport up
996 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
997 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
999 // I _really_ don't want scrollbars in the beginning
1000 m_vAdjust
->lower
= 0.0;
1001 m_vAdjust
->upper
= 1.0;
1002 m_vAdjust
->value
= 0.0;
1003 m_vAdjust
->step_increment
= 1.0;
1004 m_vAdjust
->page_increment
= 1.0;
1005 m_vAdjust
->page_size
= 5.0;
1006 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1007 m_hAdjust
->lower
= 0.0;
1008 m_hAdjust
->upper
= 1.0;
1009 m_hAdjust
->value
= 0.0;
1010 m_hAdjust
->step_increment
= 1.0;
1011 m_hAdjust
->page_increment
= 1.0;
1012 m_hAdjust
->page_size
= 5.0;
1013 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1015 gtk_widget_show( m_wxwindow
);
1024 wxWindow::~wxWindow(void)
1028 if (m_pDropTarget
) delete m_pDropTarget
;
1030 if (m_parent
) m_parent
->RemoveChild( this );
1031 if (m_widget
) Show( FALSE
);
1035 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1037 if (m_widget
) gtk_widget_destroy( m_widget
);
1041 DeleteRelatedConstraints();
1044 // This removes any dangling pointers to this window
1045 // in other windows' constraintsInvolvedIn lists.
1046 UnsetConstraints(m_constraints
);
1047 delete m_constraints
;
1048 m_constraints
= (wxLayoutConstraints
*) NULL
;
1052 delete m_windowSizer
;
1053 m_windowSizer
= (wxSizer
*) NULL
;
1055 // If this is a child of a sizer, remove self from parent
1056 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1058 // Just in case the window has been Closed, but
1059 // we're then deleting immediately: don't leave
1060 // dangling pointers.
1061 wxPendingDelete
.DeleteObject(this);
1063 // Just in case we've loaded a top-level window via
1064 // wxWindow::LoadNativeDialog but we weren't a dialog
1066 wxTopLevelWindows
.DeleteObject(this);
1068 if (m_windowValidator
) delete m_windowValidator
;
1071 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1072 const wxPoint
&pos
, const wxSize
&size
,
1073 long style
, const wxString
&name
)
1075 if (m_needParent
&& (parent
== NULL
))
1076 wxFatalError( "Need complete parent.", name
);
1078 m_widget
= (GtkWidget
*) NULL
;
1081 m_children
.DeleteContents( FALSE
);
1085 if (m_width
== -1) m_width
= 20;
1087 if (m_height
== -1) m_height
= 20;
1093 m_eventHandler
= this;
1096 if (m_cursor
== NULL
)
1097 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1098 m_font
= *wxSWISS_FONT
;
1099 m_backgroundColour
= wxWHITE
;
1100 m_foregroundColour
= wxBLACK
;
1101 m_windowStyle
= style
;
1102 m_windowName
= name
;
1103 m_constraints
= (wxLayoutConstraints
*) NULL
;
1104 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1105 m_windowSizer
= (wxSizer
*) NULL
;
1106 m_sizerParent
= (wxWindow
*) NULL
;
1107 m_autoLayout
= FALSE
;
1108 m_hasScrolling
= FALSE
;
1109 m_isScrolling
= FALSE
;
1110 m_pDropTarget
= (wxDropTarget
*) NULL
;
1112 m_windowValidator
= (wxValidator
*) NULL
;
1113 m_hasOwnStyle
= FALSE
;
1116 void wxWindow::PostCreation(void)
1118 if (m_parent
) m_parent
->AddChild( this );
1122 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1123 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1125 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1126 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1129 ConnectWidget( GetConnectWidget() );
1131 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1135 gtk_widget_realize( m_wxwindow
);
1136 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1139 SetCursor( *wxSTANDARD_CURSOR
);
1144 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1146 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1147 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1149 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1150 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1152 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1153 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1155 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1156 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1158 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1159 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1161 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1162 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1164 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1165 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1167 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1168 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1171 bool wxWindow::HasVMT(void)
1176 bool wxWindow::Close( bool force
)
1178 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1180 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1181 event
.SetEventObject(this);
1182 event
.SetForce(force
);
1184 return GetEventHandler()->ProcessEvent(event
);
1187 bool wxWindow::Destroy(void)
1189 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1196 bool wxWindow::DestroyChildren(void)
1201 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1204 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1207 if (GetChildren()->Member(child
)) delete node
;
1214 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1216 // are we to set fonts here ?
1219 void wxWindow::ImplementSetSize(void)
1221 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1222 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1223 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1224 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1225 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1228 void wxWindow::ImplementSetPosition(void)
1230 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1232 if ((m_x
!= -1) || (m_y
!= -1))
1233 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1239 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1243 if ((m_parent
) && (m_parent
->m_wxwindow
))
1244 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1246 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1249 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1251 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1253 if (m_resizing
) return; // I don't like recursions
1261 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1263 if (newX
== -1) newX
= m_x
;
1264 if (newY
== -1) newY
= m_y
;
1265 if (newW
== -1) newW
= m_width
;
1266 if (newH
== -1) newH
= m_height
;
1269 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1271 if (newW
== -1) newW
= 80;
1274 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1276 if (newH
== -1) newH
= 26;
1279 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1283 ImplementSetPosition();
1285 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1293 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1294 event
.SetEventObject( this );
1295 ProcessEvent( event
);
1300 void wxWindow::SetSize( int width
, int height
)
1302 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1305 void wxWindow::Move( int x
, int y
)
1307 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1310 void wxWindow::GetSize( int *width
, int *height
) const
1312 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1314 if (width
) (*width
) = m_width
;
1315 if (height
) (*height
) = m_height
;
1318 void wxWindow::SetClientSize( int width
, int height
)
1320 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1324 SetSize( width
, height
);
1331 if (!m_hasScrolling
)
1334 do we have sunken dialogs ?
1336 GtkStyleClass *window_class = m_wxwindow->style->klass;
1338 dw += 2 * window_class->xthickness;
1339 dh += 2 * window_class->ythickness;
1344 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1345 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1347 GtkWidget
*viewport
= scroll_window
->viewport
;
1348 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1350 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1351 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1353 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1354 (m_windowStyle
& wxSUNKEN_BORDER
))
1356 dw
+= 2 * viewport_class
->xthickness
;
1357 dh
+= 2 * viewport_class
->ythickness
;
1360 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1362 dw
+= vscrollbar
->allocation
.width
;
1363 dw
+= scroll_class
->scrollbar_spacing
;
1366 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1368 dh
+= hscrollbar
->allocation
.height
;
1369 dw
+= scroll_class
->scrollbar_spacing
;
1373 SetSize( width
+dw
, height
+dh
);
1377 void wxWindow::GetClientSize( int *width
, int *height
) const
1379 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1383 if (width
) (*width
) = m_width
;
1384 if (height
) (*height
) = m_height
;
1391 if (!m_hasScrolling
)
1394 do we have sunken dialogs ?
1396 GtkStyleClass *window_class = m_wxwindow->style->klass;
1398 dw += 2 * window_class->xthickness;
1399 dh += 2 * window_class->ythickness;
1404 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1405 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1407 GtkWidget
*viewport
= scroll_window
->viewport
;
1408 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1410 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1411 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1413 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1414 (m_windowStyle
& wxSUNKEN_BORDER
))
1416 dw
+= 2 * viewport_class
->xthickness
;
1417 dh
+= 2 * viewport_class
->ythickness
;
1420 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1422 // dw += vscrollbar->allocation.width;
1423 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1424 dw
+= scroll_class
->scrollbar_spacing
;
1427 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1429 // dh += hscrollbar->allocation.height;
1431 dh
+= scroll_class
->scrollbar_spacing
;
1435 if (width
) (*width
) = m_width
- dw
;
1436 if (height
) (*height
) = m_height
- dh
;
1440 void wxWindow::GetPosition( int *x
, int *y
) const
1442 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1448 void wxWindow::ClientToScreen( int *x
, int *y
)
1450 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1452 GdkWindow
*source
= (GdkWindow
*) NULL
;
1454 source
= m_wxwindow
->window
;
1456 source
= m_widget
->window
;
1460 gdk_window_get_origin( source
, &org_x
, &org_y
);
1464 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1466 org_x
+= m_widget
->allocation
.x
;
1467 org_y
+= m_widget
->allocation
.y
;
1475 void wxWindow::ScreenToClient( int *x
, int *y
)
1477 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1479 GdkWindow
*source
= (GdkWindow
*) NULL
;
1481 source
= m_wxwindow
->window
;
1483 source
= m_widget
->window
;
1487 gdk_window_get_origin( source
, &org_x
, &org_y
);
1491 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1493 org_x
+= m_widget
->allocation
.x
;
1494 org_y
+= m_widget
->allocation
.y
;
1502 void wxWindow::Centre( int direction
)
1504 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1506 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1508 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1509 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1510 ImplementSetPosition();
1518 m_parent
->GetSize( &p_w
, &p_h
);
1519 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1520 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1521 ImplementSetPosition();
1526 void wxWindow::Fit(void)
1528 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1532 wxNode
*node
= GetChildren()->First();
1535 wxWindow
*win
= (wxWindow
*)node
->Data();
1537 win
->GetPosition(&wx
, &wy
);
1538 win
->GetSize(&ww
, &wh
);
1539 if ( wx
+ ww
> maxX
)
1541 if ( wy
+ wh
> maxY
)
1544 node
= node
->Next();
1546 SetClientSize(maxX
+ 5, maxY
+ 10);
1549 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1551 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1559 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1561 //if (GetAutoLayout()) Layout();
1564 bool wxWindow::Show( bool show
)
1566 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1569 gtk_widget_show( m_widget
);
1571 gtk_widget_hide( m_widget
);
1576 void wxWindow::Enable( bool enable
)
1578 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1580 m_isEnabled
= enable
;
1581 gtk_widget_set_sensitive( m_widget
, enable
);
1582 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1585 int wxWindow::GetCharHeight(void) const
1587 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1591 wxFAIL_MSG( "invalid font" );
1595 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1596 return font
->ascent
+ font
->descent
;
1599 int wxWindow::GetCharWidth(void) const
1601 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1605 wxFAIL_MSG( "invalid font" );
1609 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1610 return gdk_string_width( font
, "H" );
1613 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1614 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1616 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1618 wxFont fontToUse
= m_font
;
1619 if (theFont
) fontToUse
= *theFont
;
1621 if (!fontToUse
.Ok())
1623 wxFAIL_MSG( "invalid font" );
1626 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1628 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1629 if (x
) (*x
) = gdk_string_width( font
, string
);
1630 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1631 if (descent
) (*descent
) = font
->descent
;
1632 if (externalLeading
) (*externalLeading
) = 0; // ??
1635 void wxWindow::MakeModal( bool modal
)
1638 // Disable all other windows
1639 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1641 wxNode
*node
= wxTopLevelWindows
.First();
1644 wxWindow
*win
= (wxWindow
*)node
->Data();
1646 win
->Enable(!modal
);
1648 node
= node
->Next();
1653 void wxWindow::SetFocus(void)
1655 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1657 GtkWidget
*connect_widget
= GetConnectWidget();
1660 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1662 gtk_widget_grab_focus (connect_widget
);
1667 bool wxWindow::OnClose(void)
1672 void wxWindow::AddChild( wxWindow
*child
)
1674 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1675 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1676 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1677 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1679 // Addchild is (often) called before the program
1680 // has left the parents constructor so that no
1681 // virtual tables work yet. The approach below
1682 // practically imitates virtual tables, i.e. it
1683 // implements a different AddChild() behaviour
1684 // for wxFrame, wxDialog, wxWindow and
1685 // wxMDIParentFrame.
1687 // wxFrame and wxDialog as children aren't placed into the parents
1689 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1690 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1692 m_children
.Append( child
);
1694 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1695 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1700 // In the case of an wxMDIChildFrame descendant, we use the
1701 // client windows's AddChild()
1703 if (IS_KIND_OF(this,wxMDIParentFrame
))
1705 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1707 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1710 client
->AddChild( child
);
1716 // wxNotebook is very special, so it has a private AddChild()
1718 if (IS_KIND_OF(this,wxNotebook
))
1720 wxNotebook
*tab
= (wxNotebook
*)this;
1721 tab
->AddChild( child
);
1725 // wxFrame has a private AddChild
1727 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1729 wxFrame
*frame
= (wxFrame
*)this;
1730 frame
->AddChild( child
);
1736 m_children
.Append( child
);
1737 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1738 child
->m_x
, child
->m_y
);
1740 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1743 wxList
*wxWindow::GetChildren(void)
1745 return (&m_children
);
1748 void wxWindow::RemoveChild( wxWindow
*child
)
1751 GetChildren()->DeleteObject( child
);
1752 child
->m_parent
= (wxWindow
*) NULL
;
1755 void wxWindow::SetReturnCode( int retCode
)
1757 m_retCode
= retCode
;
1760 int wxWindow::GetReturnCode(void)
1765 void wxWindow::Raise(void)
1767 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1769 if (m_widget
) gdk_window_raise( m_widget
->window
);
1772 void wxWindow::Lower(void)
1774 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1776 if (m_widget
) gdk_window_lower( m_widget
->window
);
1779 wxEvtHandler
*wxWindow::GetEventHandler(void)
1781 return m_eventHandler
;
1784 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1786 m_eventHandler
= handler
;
1789 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1791 handler
->SetNextHandler(GetEventHandler());
1792 SetEventHandler(handler
);
1795 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1797 if (GetEventHandler())
1799 wxEvtHandler
*handlerA
= GetEventHandler();
1800 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1801 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1802 SetEventHandler(handlerB
);
1806 return (wxEvtHandler
*) NULL
;
1812 return (wxEvtHandler
*) NULL
;
1815 wxValidator
*wxWindow::GetValidator(void)
1817 return m_windowValidator
;
1820 void wxWindow::SetValidator( const wxValidator
& validator
)
1822 if (m_windowValidator
) delete m_windowValidator
;
1823 m_windowValidator
= validator
.Clone();
1824 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1827 bool wxWindow::IsBeingDeleted(void)
1832 void wxWindow::SetId( wxWindowID id
)
1837 wxWindowID
wxWindow::GetId(void)
1842 void wxWindow::SetCursor( const wxCursor
&cursor
)
1844 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1846 if (m_cursor
== NULL
)
1848 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1849 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1854 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1859 *m_cursor
= *wxSTANDARD_CURSOR
;
1862 if ((m_widget
) && (m_widget
->window
))
1863 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1865 if ((m_wxwindow
) && (m_wxwindow
->window
))
1866 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1869 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1871 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1873 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1876 gdk_window_clear_area( m_wxwindow
->window
,
1890 GetClientSize( &w
, &h
);
1892 GdkRectangle gdk_rect
;
1896 gdk_rect
.height
= h
;
1897 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1902 GdkRectangle gdk_rect
;
1903 gdk_rect
.x
= rect
->x
;
1904 gdk_rect
.y
= rect
->y
;
1905 gdk_rect
.width
= rect
->width
;
1906 gdk_rect
.height
= rect
->height
;
1909 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1911 gtk_widget_draw( m_widget
, &gdk_rect
);
1915 wxRegion
wxWindow::GetUpdateRegion() const
1917 return m_updateRegion
;
1920 bool wxWindow::IsExposed( int x
, int y
) const
1922 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1925 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1927 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1930 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1932 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1935 bool wxWindow::IsExposed( const wxRect
& rect
) const
1937 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1940 void wxWindow::Clear(void)
1942 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1944 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1947 wxColour
wxWindow::GetBackgroundColour(void) const
1949 return m_backgroundColour
;
1952 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1954 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1956 m_backgroundColour
= colour
;
1959 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1960 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1961 gdk_window_clear( m_wxwindow
->window
);
1966 wxColour
wxWindow::GetForegroundColour(void) const
1968 return m_foregroundColour
;
1971 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1973 m_foregroundColour
= colour
;
1976 bool wxWindow::Validate(void)
1978 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1980 wxNode
*node
= GetChildren()->First();
1983 wxWindow
*child
= (wxWindow
*)node
->Data();
1984 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1986 node
= node
->Next();
1991 bool wxWindow::TransferDataToWindow(void)
1993 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1995 wxNode
*node
= GetChildren()->First();
1998 wxWindow
*child
= (wxWindow
*)node
->Data();
1999 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
2000 !child
->GetValidator()->TransferToWindow() )
2002 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
2005 node
= node
->Next();
2010 bool wxWindow::TransferDataFromWindow(void)
2012 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2014 wxNode
*node
= GetChildren()->First();
2017 wxWindow
*child
= (wxWindow
*)node
->Data();
2018 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2020 node
= node
->Next();
2025 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2027 m_acceleratorTable
= accel
;
2030 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2032 TransferDataToWindow();
2035 void wxWindow::InitDialog(void)
2037 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2039 wxInitDialogEvent
event(GetId());
2040 event
.SetEventObject( this );
2041 GetEventHandler()->ProcessEvent(event
);
2044 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2046 menu
->SetInvokingWindow( win
);
2047 wxNode
*node
= menu
->m_items
.First();
2050 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2051 if (menuitem
->IsSubMenu())
2052 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2053 node
= node
->Next();
2057 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2059 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2061 SetInvokingWindow( menu
, this );
2063 GTK_MENU(menu
->m_menu
),
2064 (GtkWidget
*)NULL
, // parent menu shell
2065 (GtkWidget
*)NULL
, // parent menu item
2066 (GtkMenuPositionFunc
)NULL
,
2067 NULL
, // client data
2068 0, // button used to activate it
2069 0//gs_timeLastClick // the time of activation
2074 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2076 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2078 GtkWidget
*dnd_widget
= GetConnectWidget();
2080 DisconnectDnDWidget( dnd_widget
);
2082 if (m_pDropTarget
) delete m_pDropTarget
;
2083 m_pDropTarget
= dropTarget
;
2085 ConnectDnDWidget( dnd_widget
);
2088 wxDropTarget
*wxWindow::GetDropTarget() const
2090 return m_pDropTarget
;
2093 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2095 if (!m_pDropTarget
) return;
2097 m_pDropTarget
->RegisterWidget( widget
);
2099 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2100 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2103 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2105 if (!m_pDropTarget
) return;
2107 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2108 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2110 m_pDropTarget
->UnregisterWidget( widget
);
2113 GtkWidget
* wxWindow::GetConnectWidget(void)
2115 GtkWidget
*connect_widget
= m_widget
;
2116 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2118 return connect_widget
;
2121 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2123 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2124 return (window
== m_widget
->window
);
2127 void wxWindow::SetFont( const wxFont
&font
)
2129 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2131 if (((wxFont
*)&font
)->Ok())
2134 m_font
= *wxSWISS_FONT
;
2136 GtkStyle
*style
= (GtkStyle
*) NULL
;
2139 m_hasOwnStyle
= TRUE
;
2140 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2144 style
= gtk_widget_get_style( m_widget
);
2147 gdk_font_unref( style
->font
);
2148 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2150 gtk_widget_set_style( m_widget
, style
);
2153 wxFont
*wxWindow::GetFont(void)
2158 void wxWindow::SetWindowStyleFlag( long flag
)
2160 m_windowStyle
= flag
;
2163 long wxWindow::GetWindowStyleFlag(void) const
2165 return m_windowStyle
;
2168 void wxWindow::CaptureMouse(void)
2170 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2172 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2174 GtkWidget
*connect_widget
= GetConnectWidget();
2175 gtk_grab_add( connect_widget
);
2176 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2178 (GDK_BUTTON_PRESS_MASK
|
2179 GDK_BUTTON_RELEASE_MASK
|
2180 GDK_POINTER_MOTION_MASK
),
2181 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2185 void wxWindow::ReleaseMouse(void)
2187 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2189 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2191 GtkWidget
*connect_widget
= GetConnectWidget();
2192 gtk_grab_remove( connect_widget
);
2193 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2194 g_capturing
= FALSE
;
2197 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2201 wxString
wxWindow::GetTitle(void) const
2203 return (wxString
&)m_windowName
;
2206 wxString
wxWindow::GetLabel(void) const
2211 void wxWindow::SetName( const wxString
&name
)
2213 m_windowName
= name
;
2216 wxString
wxWindow::GetName(void) const
2218 return (wxString
&)m_windowName
;
2221 bool wxWindow::IsShown(void) const
2226 bool wxWindow::IsRetained(void)
2231 wxWindow
*wxWindow::FindWindow( long id
)
2233 if (id
== m_windowId
) return this;
2234 wxNode
*node
= m_children
.First();
2237 wxWindow
*child
= (wxWindow
*)node
->Data();
2238 wxWindow
*res
= child
->FindWindow( id
);
2239 if (res
) return res
;
2240 node
= node
->Next();
2242 return (wxWindow
*) NULL
;
2245 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2247 if (name
== m_windowName
) return this;
2248 wxNode
*node
= m_children
.First();
2251 wxWindow
*child
= (wxWindow
*)node
->Data();
2252 wxWindow
*res
= child
->FindWindow( name
);
2253 if (res
) return res
;
2254 node
= node
->Next();
2256 return (wxWindow
*) NULL
;
2259 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2260 int range
, bool refresh
)
2262 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2264 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2266 if (!m_wxwindow
) return;
2268 if (orient
== wxHORIZONTAL
)
2270 float fpos
= (float)pos
;
2271 float frange
= (float)range
;
2272 float fthumb
= (float)thumbVisible
;
2274 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2275 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2277 SetScrollPos( orient
, pos
, refresh
);
2281 m_oldHorizontalPos
= fpos
;
2283 m_hAdjust
->lower
= 0.0;
2284 m_hAdjust
->upper
= frange
;
2285 m_hAdjust
->value
= fpos
;
2286 m_hAdjust
->step_increment
= 1.0;
2287 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2288 m_hAdjust
->page_size
= fthumb
;
2292 float fpos
= (float)pos
;
2293 float frange
= (float)range
;
2294 float fthumb
= (float)thumbVisible
;
2296 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2297 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2299 SetScrollPos( orient
, pos
, refresh
);
2303 m_oldVerticalPos
= fpos
;
2305 m_vAdjust
->lower
= 0.0;
2306 m_vAdjust
->upper
= frange
;
2307 m_vAdjust
->value
= fpos
;
2308 m_vAdjust
->step_increment
= 1.0;
2309 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2310 m_vAdjust
->page_size
= fthumb
;
2313 if (m_wxwindow
->window
)
2315 if (orient
== wxHORIZONTAL
)
2316 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2318 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2320 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2324 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2326 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2328 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2330 if (!m_wxwindow
) return;
2332 if (orient
== wxHORIZONTAL
)
2334 float fpos
= (float)pos
;
2335 m_oldHorizontalPos
= fpos
;
2337 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2338 m_hAdjust
->value
= fpos
;
2342 float fpos
= (float)pos
;
2343 m_oldVerticalPos
= fpos
;
2344 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2345 m_vAdjust
->value
= fpos
;
2350 if (m_wxwindow
->window
)
2352 if (orient
== wxHORIZONTAL
)
2353 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2355 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2360 int wxWindow::GetScrollThumb( int orient
) const
2362 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2364 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2366 if (!m_wxwindow
) return 0;
2368 if (orient
== wxHORIZONTAL
)
2369 return (int)(m_hAdjust
->page_size
+0.5);
2371 return (int)(m_vAdjust
->page_size
+0.5);
2374 int wxWindow::GetScrollPos( int orient
) const
2376 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2378 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2380 if (!m_wxwindow
) return 0;
2382 if (orient
== wxHORIZONTAL
)
2383 return (int)(m_hAdjust
->value
+0.5);
2385 return (int)(m_vAdjust
->value
+0.5);
2388 int wxWindow::GetScrollRange( int orient
) const
2390 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2392 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2394 if (!m_wxwindow
) return 0;
2396 if (orient
== wxHORIZONTAL
)
2397 return (int)(m_hAdjust
->upper
+0.5);
2399 return (int)(m_vAdjust
->upper
+0.5);
2402 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2404 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2406 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2408 if (!m_wxwindow
) return;
2412 GetClientSize( &cw
, &ch
);
2414 int w
= cw
- abs(dx
);
2415 int h
= ch
- abs(dy
);
2416 if ((h
< 0) || (w
< 0))
2423 if (dx
< 0) s_x
= -dx
;
2424 if (dy
< 0) s_y
= -dy
;
2427 if (dx
> 0) d_x
= dx
;
2428 if (dy
> 0) d_y
= dy
;
2429 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2430 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2433 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2434 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2435 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2436 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2438 Refresh( TRUE
, &rect
);
2441 //-------------------------------------------------------------------------------------
2443 //-------------------------------------------------------------------------------------
2445 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2447 return m_constraints
;
2450 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2454 UnsetConstraints(m_constraints
);
2455 delete m_constraints
;
2457 m_constraints
= constraints
;
2460 // Make sure other windows know they're part of a 'meaningful relationship'
2461 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2462 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2463 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2464 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2465 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2466 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2467 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2468 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2469 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2470 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2471 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2472 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2473 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2474 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2475 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2476 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2482 void wxWindow::SetAutoLayout( bool autoLayout
)
2484 m_autoLayout
= autoLayout
;
2487 bool wxWindow::GetAutoLayout(void) const
2489 return m_autoLayout
;
2492 wxSizer
*wxWindow::GetSizer(void) const
2494 return m_windowSizer
;
2497 void wxWindow::SetSizerParent( wxWindow
*win
)
2499 m_sizerParent
= win
;
2502 wxWindow
*wxWindow::GetSizerParent(void) const
2504 return m_sizerParent
;
2507 // This removes any dangling pointers to this window
2508 // in other windows' constraintsInvolvedIn lists.
2509 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2513 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2514 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2515 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2516 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2517 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2518 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2519 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2520 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2521 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2522 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2523 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2524 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2525 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2526 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2527 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2528 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2532 // Back-pointer to other windows we're involved with, so if we delete
2533 // this window, we must delete any constraints we're involved with.
2534 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2536 if (!m_constraintsInvolvedIn
)
2537 m_constraintsInvolvedIn
= new wxList
;
2538 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2539 m_constraintsInvolvedIn
->Append(otherWin
);
2542 // REMOVE back-pointer to other windows we're involved with.
2543 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2545 if (m_constraintsInvolvedIn
)
2546 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2549 // Reset any constraints that mention this window
2550 void wxWindow::DeleteRelatedConstraints(void)
2552 if (m_constraintsInvolvedIn
)
2554 wxNode
*node
= m_constraintsInvolvedIn
->First();
2557 wxWindow
*win
= (wxWindow
*)node
->Data();
2558 wxNode
*next
= node
->Next();
2559 wxLayoutConstraints
*constr
= win
->GetConstraints();
2561 // Reset any constraints involving this window
2564 constr
->left
.ResetIfWin((wxWindow
*)this);
2565 constr
->top
.ResetIfWin((wxWindow
*)this);
2566 constr
->right
.ResetIfWin((wxWindow
*)this);
2567 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2568 constr
->width
.ResetIfWin((wxWindow
*)this);
2569 constr
->height
.ResetIfWin((wxWindow
*)this);
2570 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2571 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2576 delete m_constraintsInvolvedIn
;
2577 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2581 void wxWindow::SetSizer(wxSizer
*sizer
)
2583 m_windowSizer
= sizer
;
2585 sizer
->SetSizerParent((wxWindow
*)this);
2592 bool wxWindow::Layout(void)
2594 if (GetConstraints())
2597 GetClientSize(&w
, &h
);
2598 GetConstraints()->width
.SetValue(w
);
2599 GetConstraints()->height
.SetValue(h
);
2602 // If top level (one sizer), evaluate the sizer's constraints.
2606 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2607 GetSizer()->LayoutPhase1(&noChanges
);
2608 GetSizer()->LayoutPhase2(&noChanges
);
2609 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2614 // Otherwise, evaluate child constraints
2615 ResetConstraints(); // Mark all constraints as unevaluated
2616 DoPhase(1); // Just one phase need if no sizers involved
2618 SetConstraintSizes(); // Recursively set the real window sizes
2624 // Do a phase of evaluating constraints:
2625 // the default behaviour. wxSizers may do a similar
2626 // thing, but also impose their own 'constraints'
2627 // and order the evaluation differently.
2628 bool wxWindow::LayoutPhase1(int *noChanges
)
2630 wxLayoutConstraints
*constr
= GetConstraints();
2633 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2639 bool wxWindow::LayoutPhase2(int *noChanges
)
2649 // Do a phase of evaluating child constraints
2650 bool wxWindow::DoPhase(int phase
)
2652 int noIterations
= 0;
2653 int maxIterations
= 500;
2657 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2661 wxNode
*node
= GetChildren()->First();
2664 wxWindow
*child
= (wxWindow
*)node
->Data();
2665 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2667 wxLayoutConstraints
*constr
= child
->GetConstraints();
2670 if (succeeded
.Member(child
))
2675 int tempNoChanges
= 0;
2676 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2677 noChanges
+= tempNoChanges
;
2680 succeeded
.Append(child
);
2685 node
= node
->Next();
2692 void wxWindow::ResetConstraints(void)
2694 wxLayoutConstraints
*constr
= GetConstraints();
2697 constr
->left
.SetDone(FALSE
);
2698 constr
->top
.SetDone(FALSE
);
2699 constr
->right
.SetDone(FALSE
);
2700 constr
->bottom
.SetDone(FALSE
);
2701 constr
->width
.SetDone(FALSE
);
2702 constr
->height
.SetDone(FALSE
);
2703 constr
->centreX
.SetDone(FALSE
);
2704 constr
->centreY
.SetDone(FALSE
);
2706 wxNode
*node
= GetChildren()->First();
2709 wxWindow
*win
= (wxWindow
*)node
->Data();
2710 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2711 win
->ResetConstraints();
2712 node
= node
->Next();
2716 // Need to distinguish between setting the 'fake' size for
2717 // windows and sizers, and setting the real values.
2718 void wxWindow::SetConstraintSizes(bool recurse
)
2720 wxLayoutConstraints
*constr
= GetConstraints();
2721 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2722 constr
->width
.GetDone() && constr
->height
.GetDone())
2724 int x
= constr
->left
.GetValue();
2725 int y
= constr
->top
.GetValue();
2726 int w
= constr
->width
.GetValue();
2727 int h
= constr
->height
.GetValue();
2729 // If we don't want to resize this window, just move it...
2730 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2731 (constr
->height
.GetRelationship() != wxAsIs
))
2733 // Calls Layout() recursively. AAAGH. How can we stop that.
2734 // Simply take Layout() out of non-top level OnSizes.
2735 SizerSetSize(x
, y
, w
, h
);
2744 char *windowClass
= this->GetClassInfo()->GetClassName();
2747 if (GetName() == "")
2748 winName
= _("unnamed");
2750 winName
= GetName();
2751 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2752 if (!constr
->left
.GetDone())
2753 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2754 if (!constr
->right
.GetDone())
2755 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2756 if (!constr
->width
.GetDone())
2757 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2758 if (!constr
->height
.GetDone())
2759 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2760 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2765 wxNode
*node
= GetChildren()->First();
2768 wxWindow
*win
= (wxWindow
*)node
->Data();
2769 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2770 win
->SetConstraintSizes();
2771 node
= node
->Next();
2776 // This assumes that all sizers are 'on' the same
2777 // window, i.e. the parent of this window.
2778 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2780 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2781 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2785 m_sizerParent
->GetPosition(&xp
, &yp
);
2786 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2791 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2795 TransformSizerToActual(&xx
, &yy
);
2796 SetSize(xx
, yy
, w
, h
);
2799 void wxWindow::SizerMove(int x
, int y
)
2803 TransformSizerToActual(&xx
, &yy
);
2807 // Only set the size/position of the constraint (if any)
2808 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2810 wxLayoutConstraints
*constr
= GetConstraints();
2815 constr
->left
.SetValue(x
);
2816 constr
->left
.SetDone(TRUE
);
2820 constr
->top
.SetValue(y
);
2821 constr
->top
.SetDone(TRUE
);
2825 constr
->width
.SetValue(w
);
2826 constr
->width
.SetDone(TRUE
);
2830 constr
->height
.SetValue(h
);
2831 constr
->height
.SetDone(TRUE
);
2836 void wxWindow::MoveConstraint(int x
, int y
)
2838 wxLayoutConstraints
*constr
= GetConstraints();
2843 constr
->left
.SetValue(x
);
2844 constr
->left
.SetDone(TRUE
);
2848 constr
->top
.SetValue(y
);
2849 constr
->top
.SetDone(TRUE
);
2854 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2856 wxLayoutConstraints
*constr
= GetConstraints();
2859 *w
= constr
->width
.GetValue();
2860 *h
= constr
->height
.GetValue();
2866 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2868 wxLayoutConstraints
*constr
= GetConstraints();
2871 *w
= constr
->width
.GetValue();
2872 *h
= constr
->height
.GetValue();
2875 GetClientSize(w
, h
);
2878 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2880 wxLayoutConstraints
*constr
= GetConstraints();
2883 *x
= constr
->left
.GetValue();
2884 *y
= constr
->top
.GetValue();
2890 bool wxWindow::AcceptsFocus() const
2892 return IsEnabled() && IsShown();
2895 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )