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 bool g_capturing
= FALSE
;
121 //-----------------------------------------------------------------------------
122 // "expose_event" (of m_wxwindow, not of m_widget)
123 //-----------------------------------------------------------------------------
125 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
127 if (!win
->HasVMT()) return;
128 if (g_blockEventsOnDrag
) return;
130 win
->m_updateRegion
.Union( gdk_event
->area
.x
,
132 gdk_event
->area
.width
,
133 gdk_event
->area
.height
);
135 if (gdk_event
->count
> 0) return;
138 printf( "OnExpose from " );
139 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
140 printf( win->GetClassInfo()->GetClassName() );
144 wxPaintEvent
event( win
->GetId() );
145 event
.SetEventObject( win
);
146 win
->GetEventHandler()->ProcessEvent( event
);
148 win
->m_updateRegion
.Clear();
151 //-----------------------------------------------------------------------------
152 // "draw" (of m_wxwindow, not of m_widget)
153 //-----------------------------------------------------------------------------
155 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
157 if (!win
->HasVMT()) return;
158 if (g_blockEventsOnDrag
) return;
160 win
->m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
162 wxPaintEvent
event( win
->GetId() );
163 event
.SetEventObject( win
);
164 win
->GetEventHandler()->ProcessEvent( event
);
166 win
->m_updateRegion
.Clear();
169 //-----------------------------------------------------------------------------
171 //-----------------------------------------------------------------------------
173 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
175 if (!win
->HasVMT()) return FALSE
;
176 if (g_blockEventsOnDrag
) return FALSE
;
179 printf( "OnKeyPress from " );
180 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
181 printf( win->GetClassInfo()->GetClassName() );
186 switch (gdk_event
->keyval
)
188 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
189 case GDK_Tab
: key_code
= WXK_TAB
; break;
190 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
191 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
192 case GDK_Return
: key_code
= WXK_RETURN
; break;
193 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
194 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
195 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
196 case GDK_Delete
: key_code
= WXK_DELETE
; break;
197 case GDK_Home
: key_code
= WXK_HOME
; break;
198 case GDK_Left
: key_code
= WXK_LEFT
; break;
199 case GDK_Up
: key_code
= WXK_UP
; break;
200 case GDK_Right
: key_code
= WXK_RIGHT
; break;
201 case GDK_Down
: key_code
= WXK_DOWN
; break;
202 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
203 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
204 case GDK_Next
: key_code
= WXK_NEXT
; break;
205 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
206 case GDK_End
: key_code
= WXK_END
; break;
207 case GDK_Begin
: key_code
= WXK_HOME
; break;
208 case GDK_Select
: key_code
= WXK_SELECT
; break;
209 case GDK_Print
: key_code
= WXK_PRINT
; break;
210 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
211 case GDK_Insert
: key_code
= WXK_INSERT
; break;
212 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
213 case GDK_KP_Tab
: key_code
= WXK_TAB
; break;
214 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
215 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
216 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
217 case GDK_KP_Up
: key_code
= WXK_UP
; break;
218 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
219 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
220 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
221 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
222 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
223 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
224 case GDK_KP_End
: key_code
= WXK_END
; break;
225 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
226 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
227 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
228 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
229 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
230 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
231 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
232 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
233 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
234 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
235 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
236 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
237 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
238 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
239 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
240 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
241 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
242 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
243 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
244 case GDK_F1
: key_code
= WXK_F1
; break;
245 case GDK_F2
: key_code
= WXK_F2
; break;
246 case GDK_F3
: key_code
= WXK_F3
; break;
247 case GDK_F4
: key_code
= WXK_F4
; break;
248 case GDK_F5
: key_code
= WXK_F5
; break;
249 case GDK_F6
: key_code
= WXK_F6
; break;
250 case GDK_F7
: key_code
= WXK_F7
; break;
251 case GDK_F8
: key_code
= WXK_F8
; break;
252 case GDK_F9
: key_code
= WXK_F9
; break;
253 case GDK_F10
: key_code
= WXK_F10
; break;
254 case GDK_F11
: key_code
= WXK_F11
; break;
255 case GDK_F12
: key_code
= WXK_F12
; break;
258 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
259 key_code
= gdk_event
->keyval
;
263 if (!key_code
) return FALSE
;
265 wxKeyEvent
event( wxEVT_CHAR
);
266 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
267 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
268 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
269 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
270 event
.m_keyCode
= key_code
;
273 event
.SetEventObject( win
);
275 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
279 wxWindow
*ancestor
= win
;
282 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
285 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
286 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
289 ancestor
= ancestor
->GetParent();
295 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
296 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
302 //-----------------------------------------------------------------------------
303 // "button_press_event"
304 //-----------------------------------------------------------------------------
306 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
308 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
310 if (g_blockEventsOnDrag
) return TRUE
;
314 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
316 gtk_widget_grab_focus (win
->m_wxwindow
);
319 printf( "GrabFocus from " );
320 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
321 printf( win->GetClassInfo()->GetClassName() );
328 if (!win
->HasVMT()) return TRUE
;
331 printf( "OnButtonPress from " );
332 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
333 printf( win->GetClassInfo()->GetClassName() );
337 wxEventType event_type
= wxEVT_LEFT_DOWN
;
339 if (gdk_event
->button
== 1)
341 switch (gdk_event
->type
)
343 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
344 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
348 else if (gdk_event
->button
== 2)
350 switch (gdk_event
->type
)
352 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
353 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
357 else if (gdk_event
->button
== 3)
359 switch (gdk_event
->type
)
361 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
362 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
367 wxMouseEvent
event( event_type
);
368 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
369 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
370 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
371 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
372 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
373 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
374 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
376 event
.m_x
= (long)gdk_event
->x
;
377 event
.m_y
= (long)gdk_event
->y
;
379 // Some control don't have their own X window and thus cannot get
384 wxNode
*node
= win
->GetChildren()->First();
387 wxWindow
*child
= (wxWindow
*)node
->Data();
388 if ((child
->m_x
<= event
.m_x
) &&
389 (child
->m_y
<= event
.m_y
) &&
390 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
391 (child
->m_y
+child
->m_height
>= event
.m_y
))
394 event
.m_x
-= child
->m_x
;
395 event
.m_y
-= child
->m_y
;
402 event
.SetEventObject( win
);
404 if (win
->GetEventHandler()->ProcessEvent( event
))
405 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
410 //-----------------------------------------------------------------------------
411 // "button_release_event"
412 //-----------------------------------------------------------------------------
414 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
416 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
418 if (g_blockEventsOnDrag
) return TRUE
;
420 if (!win
->HasVMT()) return TRUE
;
423 printf( "OnButtonRelease from " );
424 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
425 printf( win->GetClassInfo()->GetClassName() );
429 wxEventType event_type
= wxEVT_NULL
;
431 switch (gdk_event
->button
)
433 case 1: event_type
= wxEVT_LEFT_UP
; break;
434 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
435 case 3: event_type
= wxEVT_RIGHT_UP
; break;
438 wxMouseEvent
event( event_type
);
439 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
440 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
441 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
442 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
443 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
444 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
445 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
446 event
.m_x
= (long)gdk_event
->x
;
447 event
.m_y
= (long)gdk_event
->y
;
449 // Some control don't have their own X window and thus cannot get
454 wxNode
*node
= win
->GetChildren()->First();
457 wxWindow
*child
= (wxWindow
*)node
->Data();
458 if ((child
->m_x
<= event
.m_x
) &&
459 (child
->m_y
<= event
.m_y
) &&
460 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
461 (child
->m_y
+child
->m_height
>= event
.m_y
))
464 event
.m_x
-= child
->m_x
;
465 event
.m_y
-= child
->m_y
;
472 event
.SetEventObject( win
);
474 if (win
->GetEventHandler()->ProcessEvent( event
))
475 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
480 //-----------------------------------------------------------------------------
481 // "motion_notify_event"
482 //-----------------------------------------------------------------------------
484 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
486 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return TRUE
;
488 if (g_blockEventsOnDrag
) return TRUE
;
490 if (!win
->HasVMT()) return TRUE
;
493 printf( "OnMotion from " );
494 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
495 printf( win->GetClassInfo()->GetClassName() );
499 wxMouseEvent
event( wxEVT_MOTION
);
500 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
501 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
502 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
503 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
504 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
505 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
506 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
508 event
.m_x
= (long)gdk_event
->x
;
509 event
.m_y
= (long)gdk_event
->y
;
511 // Some control don't have their own X window and thus cannot get
516 wxNode
*node
= win
->GetChildren()->First();
519 wxWindow
*child
= (wxWindow
*)node
->Data();
520 if ((child
->m_x
<= event
.m_x
) &&
521 (child
->m_y
<= event
.m_y
) &&
522 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
523 (child
->m_y
+child
->m_height
>= event
.m_y
))
526 event
.m_x
-= child
->m_x
;
527 event
.m_y
-= child
->m_y
;
534 event
.SetEventObject( win
);
536 if (win
->GetEventHandler()->ProcessEvent( event
))
537 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
542 //-----------------------------------------------------------------------------
544 //-----------------------------------------------------------------------------
546 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
548 if (g_blockEventsOnDrag
) return TRUE
;
551 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
553 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
555 printf( "SetFocus flag from " );
556 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
557 printf( win->GetClassInfo()->GetClassName() );
563 if (!win
->HasVMT()) return TRUE
;
566 printf( "OnSetFocus from " );
567 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
568 printf( win->GetClassInfo()->GetClassName() );
570 printf( WXSTRINGCAST win->GetLabel() );
574 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
575 event
.SetEventObject( win
);
577 if (win
->GetEventHandler()->ProcessEvent( event
))
578 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
583 //-----------------------------------------------------------------------------
585 //-----------------------------------------------------------------------------
587 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
589 if (g_blockEventsOnDrag
) return TRUE
;
592 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
593 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
596 if (!win
->HasVMT()) return TRUE
;
599 printf( "OnKillFocus from " );
600 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
601 printf( win->GetClassInfo()->GetClassName() );
605 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
606 event
.SetEventObject( win
);
608 if (win
->GetEventHandler()->ProcessEvent( event
))
609 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
614 //-----------------------------------------------------------------------------
615 // "enter_notify_event"
616 //-----------------------------------------------------------------------------
618 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
620 if (widget
->window
!= gdk_event
->window
) return TRUE
;
622 if (g_blockEventsOnDrag
) return TRUE
;
624 if (!win
->HasVMT()) return TRUE
;
627 printf( "OnEnter from " );
628 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
629 printf( win->GetClassInfo()->GetClassName() );
633 if ((widget
->window
) && (win
->m_cursor
))
634 gdk_window_set_cursor( widget
->window
, win
->m_cursor
->GetCursor() );
636 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
637 event
.SetEventObject( win
);
639 if (win
->GetEventHandler()->ProcessEvent( event
))
640 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
645 //-----------------------------------------------------------------------------
646 // "leave_notify_event"
647 //-----------------------------------------------------------------------------
649 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
651 if (widget
->window
!= gdk_event
->window
) return TRUE
;
653 if (g_blockEventsOnDrag
) return TRUE
;
655 if (!win
->HasVMT()) return TRUE
;
658 printf( "OnLeave from " );
659 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
660 printf( win->GetClassInfo()->GetClassName() );
664 if ((widget
->window
) && (win
->m_cursor
))
665 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
667 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
668 event
.SetEventObject( win
);
670 if (win
->GetEventHandler()->ProcessEvent( event
))
671 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
676 //-----------------------------------------------------------------------------
677 // "value_changed" from m_vAdjust
678 //-----------------------------------------------------------------------------
680 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
682 if (g_blockEventsOnDrag
) return;
685 printf( "OnVScroll from " );
686 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
687 printf( win->GetClassInfo()->GetClassName() );
691 if (!win
->HasVMT()) return;
693 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
694 if (fabs(diff
) < 0.2) return;
696 wxEventType command
= wxEVT_NULL
;
698 float line_step
= win
->m_vAdjust
->step_increment
;
699 float page_step
= win
->m_vAdjust
->page_increment
;
701 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
702 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
703 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
704 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
705 else command
= wxEVT_SCROLL_THUMBTRACK
;
707 int value
= (int)(win
->m_vAdjust
->value
+0.5);
709 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
710 event
.SetEventObject( win
);
711 win
->GetEventHandler()->ProcessEvent( event
);
714 //-----------------------------------------------------------------------------
715 // "value_changed" from m_hAdjust
716 //-----------------------------------------------------------------------------
718 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
720 if (g_blockEventsOnDrag
) return;
723 printf( "OnHScroll from " );
724 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
725 printf( win->GetClassInfo()->GetClassName() );
729 if (!win
->HasVMT()) return;
731 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
732 if (fabs(diff
) < 0.2) return;
734 wxEventType command
= wxEVT_NULL
;
736 float line_step
= win
->m_hAdjust
->step_increment
;
737 float page_step
= win
->m_hAdjust
->page_increment
;
739 if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
740 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
741 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
742 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
743 else command
= wxEVT_SCROLL_THUMBTRACK
;
745 int value
= (int)(win
->m_hAdjust
->value
+0.5);
747 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
748 event
.SetEventObject( win
);
749 win
->GetEventHandler()->ProcessEvent( event
);
752 //-----------------------------------------------------------------------------
753 // "changed" from m_vAdjust
754 //-----------------------------------------------------------------------------
756 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
758 if (g_blockEventsOnDrag
) return;
761 printf( "OnVScroll change from " );
762 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
763 printf( win->GetClassInfo()->GetClassName() );
767 if (!win
->HasVMT()) return;
769 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
770 int value
= (int)(win
->m_vAdjust
->value
+0.5);
772 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
773 event
.SetEventObject( win
);
774 win
->GetEventHandler()->ProcessEvent( event
);
777 //-----------------------------------------------------------------------------
778 // "changed" from m_hAdjust
779 //-----------------------------------------------------------------------------
781 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
783 if (g_blockEventsOnDrag
) return;
786 printf( "OnHScroll change from " );
787 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
788 printf( win->GetClassInfo()->GetClassName() );
792 if (!win
->HasVMT()) return;
794 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
795 int value
= (int)(win
->m_hAdjust
->value
+0.5);
797 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
798 event
.SetEventObject( win
);
799 win
->GetEventHandler()->ProcessEvent( event
);
802 //-----------------------------------------------------------------------------
803 // "button_press_event" from scrollbar
804 //-----------------------------------------------------------------------------
806 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
808 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
810 win
->m_isScrolling
= TRUE
;
815 //-----------------------------------------------------------------------------
816 // "button_release_event" from scrollbar
817 //-----------------------------------------------------------------------------
819 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
821 if (gdk_event
->window
!= widget
->slider
) return FALSE
;
823 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(win
->m_widget
);
825 if (widget
== GTK_RANGE(s_window
->vscrollbar
))
826 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
828 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
830 win
->m_isScrolling
= FALSE
;
835 //-----------------------------------------------------------------------------
836 // "drop_data_available_event"
837 //-----------------------------------------------------------------------------
839 static void gtk_window_drop_callback( GtkWidget
*widget
, GdkEvent
*event
, wxWindow
*win
)
841 if (!win
->HasVMT()) return;
843 if (win
->GetDropTarget())
847 gdk_window_get_pointer( widget
->window
, &x
, &y
, (GdkModifierType
*) NULL
);
848 win
->GetDropTarget()->Drop( event
, x
, y
);
852 g_free (event->dropdataavailable.data);
853 g_free (event->dropdataavailable.data_type);
857 //-----------------------------------------------------------------------------
859 //-----------------------------------------------------------------------------
861 IMPLEMENT_DYNAMIC_CLASS(wxWindow
,wxEvtHandler
)
863 BEGIN_EVENT_TABLE(wxWindow
, wxEvtHandler
)
864 EVT_SIZE(wxWindow::OnSize
)
865 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged
)
866 EVT_INIT_DIALOG(wxWindow::OnInitDialog
)
867 EVT_IDLE(wxWindow::OnIdle
)
872 m_widget
= (GtkWidget
*) NULL
;
873 m_wxwindow
= (GtkWidget
*) NULL
;
874 m_parent
= (wxWindow
*) NULL
;
875 m_children
.DeleteContents( FALSE
);
885 m_eventHandler
= this;
886 m_windowValidator
= (wxValidator
*) NULL
;
888 m_cursor
= (wxCursor
*) NULL
;
889 m_font
= *wxSWISS_FONT
;
891 m_windowName
= "noname";
892 m_constraints
= (wxLayoutConstraints
*) NULL
;
893 m_constraintsInvolvedIn
= (wxList
*) NULL
;
894 m_windowSizer
= (wxSizer
*) NULL
;
895 m_sizerParent
= (wxWindow
*) NULL
;
896 m_autoLayout
= FALSE
;
900 m_hasScrolling
= FALSE
;
901 m_isScrolling
= FALSE
;
902 m_hAdjust
= (GtkAdjustment
*) NULL
;
903 m_vAdjust
= (GtkAdjustment
*) NULL
;
904 m_oldHorizontalPos
= 0.0;
905 m_oldVerticalPos
= 0.0;
908 m_pDropTarget
= (wxDropTarget
*) NULL
;
910 m_hasOwnStyle
= FALSE
;
913 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
914 const wxPoint
&pos
, const wxSize
&size
,
915 long style
, const wxString
&name
)
921 m_cursor
= (wxCursor
*) NULL
;
923 PreCreation( parent
, id
, pos
, size
, style
, name
);
925 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
926 m_hasScrolling
= TRUE
;
928 GtkScrolledWindow
*s_window
= GTK_SCROLLED_WINDOW(m_widget
);
930 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_press_event",
931 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
933 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_press_event",
934 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
936 gtk_signal_connect( GTK_OBJECT(s_window
->vscrollbar
), "button_release_event",
937 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
939 gtk_signal_connect( GTK_OBJECT(s_window
->hscrollbar
), "button_release_event",
940 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
942 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
943 scroll_class
->scrollbar_spacing
= 0;
945 gtk_scrolled_window_set_policy( s_window
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
947 m_oldHorizontalPos
= 0.0;
948 m_oldVerticalPos
= 0.0;
950 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->hscrollbar
) );
951 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(s_window
->vscrollbar
) );
953 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
954 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
955 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
956 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
958 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
959 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
960 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
961 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
963 GtkViewport
*viewport
= GTK_VIEWPORT(s_window
->viewport
);
965 if (m_windowStyle
& wxRAISED_BORDER
)
967 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
969 else if (m_windowStyle
& wxSUNKEN_BORDER
)
971 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
975 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
978 m_wxwindow
= gtk_myfixed_new();
980 if (m_wxwindow
) GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
982 if (m_windowStyle
& wxTAB_TRAVERSAL
== wxTAB_TRAVERSAL
)
983 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
985 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
987 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
989 // shut the viewport up
990 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
991 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
993 // I _really_ don't want scrollbars in the beginning
994 m_vAdjust
->lower
= 0.0;
995 m_vAdjust
->upper
= 1.0;
996 m_vAdjust
->value
= 0.0;
997 m_vAdjust
->step_increment
= 1.0;
998 m_vAdjust
->page_increment
= 1.0;
999 m_vAdjust
->page_size
= 5.0;
1000 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1001 m_hAdjust
->lower
= 0.0;
1002 m_hAdjust
->upper
= 1.0;
1003 m_hAdjust
->value
= 0.0;
1004 m_hAdjust
->step_increment
= 1.0;
1005 m_hAdjust
->page_increment
= 1.0;
1006 m_hAdjust
->page_size
= 5.0;
1007 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1009 gtk_widget_show( m_wxwindow
);
1018 wxWindow::~wxWindow(void)
1022 if (m_pDropTarget
) delete m_pDropTarget
;
1024 if (m_parent
) m_parent
->RemoveChild( this );
1025 if (m_widget
) Show( FALSE
);
1029 if (m_wxwindow
) gtk_widget_destroy( m_wxwindow
);
1031 if (m_widget
) gtk_widget_destroy( m_widget
);
1035 DeleteRelatedConstraints();
1038 // This removes any dangling pointers to this window
1039 // in other windows' constraintsInvolvedIn lists.
1040 UnsetConstraints(m_constraints
);
1041 delete m_constraints
;
1042 m_constraints
= (wxLayoutConstraints
*) NULL
;
1046 delete m_windowSizer
;
1047 m_windowSizer
= (wxSizer
*) NULL
;
1049 // If this is a child of a sizer, remove self from parent
1050 if (m_sizerParent
) m_sizerParent
->RemoveChild((wxWindow
*)this);
1052 // Just in case the window has been Closed, but
1053 // we're then deleting immediately: don't leave
1054 // dangling pointers.
1055 wxPendingDelete
.DeleteObject(this);
1057 // Just in case we've loaded a top-level window via
1058 // wxWindow::LoadNativeDialog but we weren't a dialog
1060 wxTopLevelWindows
.DeleteObject(this);
1062 if (m_windowValidator
) delete m_windowValidator
;
1065 void wxWindow::PreCreation( wxWindow
*parent
, wxWindowID id
,
1066 const wxPoint
&pos
, const wxSize
&size
,
1067 long style
, const wxString
&name
)
1069 if (m_needParent
&& (parent
== NULL
))
1070 wxFatalError( "Need complete parent.", name
);
1072 m_widget
= (GtkWidget
*) NULL
;
1075 m_children
.DeleteContents( FALSE
);
1079 if (m_width
== -1) m_width
= 20;
1081 if (m_height
== -1) m_height
= 20;
1087 m_eventHandler
= this;
1090 if (m_cursor
== NULL
)
1091 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1092 m_font
= *wxSWISS_FONT
;
1093 m_backgroundColour
= wxWHITE
;
1094 m_foregroundColour
= wxBLACK
;
1095 m_windowStyle
= style
;
1096 m_windowName
= name
;
1097 m_constraints
= (wxLayoutConstraints
*) NULL
;
1098 m_constraintsInvolvedIn
= (wxList
*) NULL
;
1099 m_windowSizer
= (wxSizer
*) NULL
;
1100 m_sizerParent
= (wxWindow
*) NULL
;
1101 m_autoLayout
= FALSE
;
1102 m_hasScrolling
= FALSE
;
1103 m_isScrolling
= FALSE
;
1104 m_pDropTarget
= (wxDropTarget
*) NULL
;
1106 m_windowValidator
= (wxValidator
*) NULL
;
1107 m_hasOwnStyle
= FALSE
;
1110 void wxWindow::PostCreation(void)
1112 if (m_parent
) m_parent
->AddChild( this );
1116 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1117 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1119 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1120 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1123 ConnectWidget( GetConnectWidget() );
1125 if (m_widget
&& m_parent
) gtk_widget_realize( m_widget
);
1129 gtk_widget_realize( m_wxwindow
);
1130 gdk_gc_set_exposures( m_wxwindow
->style
->fg_gc
[0], TRUE
);
1133 SetCursor( *wxSTANDARD_CURSOR
);
1138 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1140 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1141 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1143 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1144 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1146 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1147 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1149 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1150 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1152 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1153 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1155 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1156 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1158 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1159 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1161 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1162 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1165 bool wxWindow::HasVMT(void)
1170 bool wxWindow::Close( bool force
)
1172 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1174 wxCloseEvent
event(wxEVT_CLOSE_WINDOW
, m_windowId
);
1175 event
.SetEventObject(this);
1176 event
.SetForce(force
);
1178 return GetEventHandler()->ProcessEvent(event
);
1181 bool wxWindow::Destroy(void)
1183 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1190 bool wxWindow::DestroyChildren(void)
1195 while ((node
= GetChildren()->First()) != (wxNode
*)NULL
)
1198 if ((child
= (wxWindow
*)node
->Data()) != (wxWindow
*)NULL
)
1201 if (GetChildren()->Member(child
)) delete node
;
1208 void wxWindow::PrepareDC( wxDC
&WXUNUSED(dc
) )
1210 // are we to set fonts here ?
1213 void wxWindow::ImplementSetSize(void)
1215 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1216 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1217 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_minWidth
;
1218 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_minHeight
;
1219 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
1222 void wxWindow::ImplementSetPosition(void)
1224 if (IS_KIND_OF(this,wxFrame
) || IS_KIND_OF(this,wxDialog
))
1226 if ((m_x
!= -1) || (m_y
!= -1))
1227 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
1233 wxFAIL_MSG( "wxWindow::SetSize error.\n" );
1237 if ((m_parent
) && (m_parent
->m_wxwindow
))
1238 gtk_myfixed_move( GTK_MYFIXED(m_parent
->m_wxwindow
), m_widget
, m_x
, m_y
);
1240 // Don't do anything for children of wxNotebook and wxMDIChildFrame
1243 void wxWindow::SetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1245 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1247 if (m_resizing
) return; // I don't like recursions
1255 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1257 if (newX
== -1) newX
= m_x
;
1258 if (newY
== -1) newY
= m_y
;
1259 if (newW
== -1) newW
= m_width
;
1260 if (newH
== -1) newH
= m_height
;
1263 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1265 if (newW
== -1) newW
= 80;
1268 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1270 if (newH
== -1) newH
= 26;
1273 if ((m_x
!= newX
) || (m_y
!= newY
) || (!m_sizeSet
))
1277 ImplementSetPosition();
1279 if ((m_width
!= newW
) || (m_height
!= newH
) || (!m_sizeSet
))
1287 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1288 event
.SetEventObject( this );
1289 ProcessEvent( event
);
1294 void wxWindow::SetSize( int width
, int height
)
1296 SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING
);
1299 void wxWindow::Move( int x
, int y
)
1301 SetSize( x
, y
, -1, -1, wxSIZE_USE_EXISTING
);
1304 void wxWindow::GetSize( int *width
, int *height
) const
1306 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1308 if (width
) (*width
) = m_width
;
1309 if (height
) (*height
) = m_height
;
1312 void wxWindow::SetClientSize( int width
, int height
)
1314 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1318 SetSize( width
, height
);
1325 if (!m_hasScrolling
)
1328 do we have sunken dialogs ?
1330 GtkStyleClass *window_class = m_wxwindow->style->klass;
1332 dw += 2 * window_class->xthickness;
1333 dh += 2 * window_class->ythickness;
1338 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1339 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1341 GtkWidget
*viewport
= scroll_window
->viewport
;
1342 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1344 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1345 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1347 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1348 (m_windowStyle
& wxSUNKEN_BORDER
))
1350 dw
+= 2 * viewport_class
->xthickness
;
1351 dh
+= 2 * viewport_class
->ythickness
;
1354 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1356 dw
+= vscrollbar
->allocation
.width
;
1357 dw
+= scroll_class
->scrollbar_spacing
;
1360 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1362 dh
+= hscrollbar
->allocation
.height
;
1363 dw
+= scroll_class
->scrollbar_spacing
;
1367 SetSize( width
+dw
, height
+dh
);
1371 void wxWindow::GetClientSize( int *width
, int *height
) const
1373 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1377 if (width
) (*width
) = m_width
;
1378 if (height
) (*height
) = m_height
;
1385 if (!m_hasScrolling
)
1388 do we have sunken dialogs ?
1390 GtkStyleClass *window_class = m_wxwindow->style->klass;
1392 dw += 2 * window_class->xthickness;
1393 dh += 2 * window_class->ythickness;
1398 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1399 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1401 GtkWidget
*viewport
= scroll_window
->viewport
;
1402 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1404 GtkWidget
*hscrollbar
= scroll_window
->hscrollbar
;
1405 GtkWidget
*vscrollbar
= scroll_window
->vscrollbar
;
1407 if ((m_windowStyle
& wxRAISED_BORDER
) ||
1408 (m_windowStyle
& wxSUNKEN_BORDER
))
1410 dw
+= 2 * viewport_class
->xthickness
;
1411 dh
+= 2 * viewport_class
->ythickness
;
1414 if (GTK_WIDGET_VISIBLE(vscrollbar
))
1416 // dw += vscrollbar->allocation.width;
1417 dw
+= 15; // range.slider_width = 11 + 2*2pts edge
1418 dw
+= scroll_class
->scrollbar_spacing
;
1421 if (GTK_WIDGET_VISIBLE(hscrollbar
))
1423 // dh += hscrollbar->allocation.height;
1425 dh
+= scroll_class
->scrollbar_spacing
;
1429 if (width
) (*width
) = m_width
- dw
;
1430 if (height
) (*height
) = m_height
- dh
;
1434 void wxWindow::GetPosition( int *x
, int *y
) const
1436 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1442 void wxWindow::ClientToScreen( int *x
, int *y
)
1444 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1446 GdkWindow
*source
= (GdkWindow
*) NULL
;
1448 source
= m_wxwindow
->window
;
1450 source
= m_widget
->window
;
1454 gdk_window_get_origin( source
, &org_x
, &org_y
);
1458 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1460 org_x
+= m_widget
->allocation
.x
;
1461 org_y
+= m_widget
->allocation
.y
;
1469 void wxWindow::ScreenToClient( int *x
, int *y
)
1471 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1473 GdkWindow
*source
= (GdkWindow
*) NULL
;
1475 source
= m_wxwindow
->window
;
1477 source
= m_widget
->window
;
1481 gdk_window_get_origin( source
, &org_x
, &org_y
);
1485 if (GTK_WIDGET_NO_WINDOW (m_widget
))
1487 org_x
+= m_widget
->allocation
.x
;
1488 org_y
+= m_widget
->allocation
.y
;
1496 void wxWindow::Centre( int direction
)
1498 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1500 if (IS_KIND_OF(this,wxDialog
) || IS_KIND_OF(this,wxFrame
))
1502 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (gdk_screen_width () - m_width
) / 2;
1503 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (gdk_screen_height () - m_height
) / 2;
1504 ImplementSetPosition();
1512 m_parent
->GetSize( &p_w
, &p_h
);
1513 if (direction
& wxHORIZONTAL
== wxHORIZONTAL
) m_x
= (p_w
- m_width
) / 2;
1514 if (direction
& wxVERTICAL
== wxVERTICAL
) m_y
= (p_h
- m_height
) / 2;
1515 ImplementSetPosition();
1520 void wxWindow::Fit(void)
1522 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1526 wxNode
*node
= GetChildren()->First();
1529 wxWindow
*win
= (wxWindow
*)node
->Data();
1531 win
->GetPosition(&wx
, &wy
);
1532 win
->GetSize(&ww
, &wh
);
1533 if ( wx
+ ww
> maxX
)
1535 if ( wy
+ wh
> maxY
)
1538 node
= node
->Next();
1540 SetClientSize(maxX
+ 5, maxY
+ 10);
1543 void wxWindow::SetSizeHints( int minW
, int minH
, int maxW
, int maxH
, int WXUNUSED(incW
), int WXUNUSED(incH
) )
1545 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1553 void wxWindow::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1555 //if (GetAutoLayout()) Layout();
1558 bool wxWindow::Show( bool show
)
1560 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1563 gtk_widget_show( m_widget
);
1565 gtk_widget_hide( m_widget
);
1570 void wxWindow::Enable( bool enable
)
1572 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1574 m_isEnabled
= enable
;
1575 gtk_widget_set_sensitive( m_widget
, enable
);
1576 if (m_wxwindow
) gtk_widget_set_sensitive( m_wxwindow
, enable
);
1579 int wxWindow::GetCharHeight(void) const
1581 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1585 wxFAIL_MSG( "invalid font" );
1589 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1590 return font
->ascent
+ font
->descent
;
1593 int wxWindow::GetCharWidth(void) const
1595 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1599 wxFAIL_MSG( "invalid font" );
1603 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
1604 return gdk_string_width( font
, "H" );
1607 void wxWindow::GetTextExtent( const wxString
& string
, int *x
, int *y
,
1608 int *descent
, int *externalLeading
, const wxFont
*theFont
, bool WXUNUSED(use16
) ) const
1610 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1612 wxFont fontToUse
= m_font
;
1613 if (theFont
) fontToUse
= *theFont
;
1615 if (!fontToUse
.Ok())
1617 wxFAIL_MSG( "invalid font" );
1620 wxASSERT_MSG( (m_font
.Ok()), "invalid font" );
1622 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
1623 if (x
) (*x
) = gdk_string_width( font
, string
);
1624 if (y
) (*y
) = font
->ascent
+ font
->descent
;
1625 if (descent
) (*descent
) = font
->descent
;
1626 if (externalLeading
) (*externalLeading
) = 0; // ??
1629 void wxWindow::MakeModal( bool modal
)
1632 // Disable all other windows
1633 if (this->IsKindOf(CLASSINFO(wxDialog
)) || this->IsKindOf(CLASSINFO(wxFrame
)))
1635 wxNode
*node
= wxTopLevelWindows
.First();
1638 wxWindow
*win
= (wxWindow
*)node
->Data();
1640 win
->Enable(!modal
);
1642 node
= node
->Next();
1647 void wxWindow::SetFocus(void)
1649 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1651 GtkWidget
*connect_widget
= GetConnectWidget();
1654 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) && !GTK_WIDGET_HAS_FOCUS (connect_widget
) )
1656 gtk_widget_grab_focus (connect_widget
);
1661 bool wxWindow::OnClose(void)
1666 void wxWindow::AddChild( wxWindow
*child
)
1668 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1669 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window need client area" );
1670 wxASSERT_MSG( (child
!= NULL
), "invalid child" );
1671 wxASSERT_MSG( (child
->m_widget
!= NULL
), "invalid child" );
1673 // Addchild is (often) called before the program
1674 // has left the parents constructor so that no
1675 // virtual tables work yet. The approach below
1676 // practically imitates virtual tables, i.e. it
1677 // implements a different AddChild() behaviour
1678 // for wxFrame, wxDialog, wxWindow and
1679 // wxMDIParentFrame.
1681 // wxFrame and wxDialog as children aren't placed into the parents
1683 if (( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
) ) &&
1684 (!IS_KIND_OF(child
,wxMDIChildFrame
)))
1686 m_children
.Append( child
);
1688 if ((child
->m_x
!= -1) && (child
->m_y
!= -1))
1689 gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y
);
1694 // In the case of an wxMDIChildFrame descendant, we use the
1695 // client windows's AddChild()
1697 if (IS_KIND_OF(this,wxMDIParentFrame
))
1699 if (IS_KIND_OF(child
,wxMDIChildFrame
))
1701 wxMDIClientWindow
*client
= ((wxMDIParentFrame
*)this)->GetClientWindow();
1704 client
->AddChild( child
);
1710 // wxNotebook is very special, so it has a private AddChild()
1712 if (IS_KIND_OF(this,wxNotebook
))
1714 wxNotebook
*tab
= (wxNotebook
*)this;
1715 tab
->AddChild( child
);
1719 // wxFrame has a private AddChild
1721 if (IS_KIND_OF(this,wxFrame
) && !IS_KIND_OF(this,wxMDIChildFrame
))
1723 wxFrame
*frame
= (wxFrame
*)this;
1724 frame
->AddChild( child
);
1730 m_children
.Append( child
);
1731 if (m_wxwindow
) gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
,
1732 child
->m_x
, child
->m_y
);
1734 gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height
);
1737 wxList
*wxWindow::GetChildren(void)
1739 return (&m_children
);
1742 void wxWindow::RemoveChild( wxWindow
*child
)
1745 GetChildren()->DeleteObject( child
);
1746 child
->m_parent
= (wxWindow
*) NULL
;
1749 void wxWindow::SetReturnCode( int retCode
)
1751 m_retCode
= retCode
;
1754 int wxWindow::GetReturnCode(void)
1759 void wxWindow::Raise(void)
1761 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1763 if (m_widget
) gdk_window_raise( m_widget
->window
);
1766 void wxWindow::Lower(void)
1768 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1770 if (m_widget
) gdk_window_lower( m_widget
->window
);
1773 wxEvtHandler
*wxWindow::GetEventHandler(void)
1775 return m_eventHandler
;
1778 void wxWindow::SetEventHandler( wxEvtHandler
*handler
)
1780 m_eventHandler
= handler
;
1783 void wxWindow::PushEventHandler(wxEvtHandler
*handler
)
1785 handler
->SetNextHandler(GetEventHandler());
1786 SetEventHandler(handler
);
1789 wxEvtHandler
*wxWindow::PopEventHandler(bool deleteHandler
)
1791 if (GetEventHandler())
1793 wxEvtHandler
*handlerA
= GetEventHandler();
1794 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
1795 handlerA
->SetNextHandler((wxEvtHandler
*) NULL
);
1796 SetEventHandler(handlerB
);
1800 return (wxEvtHandler
*) NULL
;
1806 return (wxEvtHandler
*) NULL
;
1809 wxValidator
*wxWindow::GetValidator(void)
1811 return m_windowValidator
;
1814 void wxWindow::SetValidator( const wxValidator
& validator
)
1816 if (m_windowValidator
) delete m_windowValidator
;
1817 m_windowValidator
= validator
.Clone();
1818 if (m_windowValidator
) m_windowValidator
->SetWindow(this);
1821 bool wxWindow::IsBeingDeleted(void)
1826 void wxWindow::SetId( wxWindowID id
)
1831 wxWindowID
wxWindow::GetId(void)
1836 void wxWindow::SetCursor( const wxCursor
&cursor
)
1838 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1840 if (m_cursor
== NULL
)
1842 wxFAIL_MSG( "wxWindow::SetCursor m_cursor == NULL" );
1843 m_cursor
= new wxCursor( wxCURSOR_ARROW
);
1848 if (*((wxCursor
*)&cursor
) == m_cursor
) return;
1853 *m_cursor
= *wxSTANDARD_CURSOR
;
1856 if ((m_widget
) && (m_widget
->window
))
1857 gdk_window_set_cursor( m_widget
->window
, m_cursor
->GetCursor() );
1859 if ((m_wxwindow
) && (m_wxwindow
->window
))
1860 gdk_window_set_cursor( m_wxwindow
->window
, m_cursor
->GetCursor() );
1863 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
1865 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1867 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
1870 gdk_window_clear_area( m_wxwindow
->window
,
1884 GetClientSize( &w
, &h
);
1886 GdkRectangle gdk_rect
;
1890 gdk_rect
.height
= h
;
1891 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1896 GdkRectangle gdk_rect
;
1897 gdk_rect
.x
= rect
->x
;
1898 gdk_rect
.y
= rect
->y
;
1899 gdk_rect
.width
= rect
->width
;
1900 gdk_rect
.height
= rect
->height
;
1903 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
1905 gtk_widget_draw( m_widget
, &gdk_rect
);
1909 wxRegion
wxWindow::GetUpdateRegion() const
1911 return m_updateRegion
;
1914 bool wxWindow::IsExposed( int x
, int y
) const
1916 return (m_updateRegion
.Contains( x
, y
) != wxOutRegion
);
1919 bool wxWindow::IsExposed( int x
, int y
, int w
, int h
) const
1921 return (m_updateRegion
.Contains( x
, y
, w
, h
) != wxOutRegion
);
1924 bool wxWindow::IsExposed( const wxPoint
& pt
) const
1926 return (m_updateRegion
.Contains( pt
.x
, pt
.y
) != wxOutRegion
);
1929 bool wxWindow::IsExposed( const wxRect
& rect
) const
1931 return (m_updateRegion
.Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
) != wxOutRegion
);
1934 void wxWindow::Clear(void)
1936 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1938 if (m_wxwindow
&& m_wxwindow
->window
) gdk_window_clear( m_wxwindow
->window
);
1941 wxColour
wxWindow::GetBackgroundColour(void) const
1943 return m_backgroundColour
;
1946 void wxWindow::SetBackgroundColour( const wxColour
&colour
)
1948 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1950 m_backgroundColour
= colour
;
1953 m_backgroundColour
.CalcPixel( m_wxwindow
->style
->colormap
);
1954 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
1955 gdk_window_clear( m_wxwindow
->window
);
1960 wxColour
wxWindow::GetForegroundColour(void) const
1962 return m_foregroundColour
;
1965 void wxWindow::SetForegroundColour( const wxColour
&colour
)
1967 m_foregroundColour
= colour
;
1970 bool wxWindow::Validate(void)
1972 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1974 wxNode
*node
= GetChildren()->First();
1977 wxWindow
*child
= (wxWindow
*)node
->Data();
1978 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->Validate(this))
1980 node
= node
->Next();
1985 bool wxWindow::TransferDataToWindow(void)
1987 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
1989 wxNode
*node
= GetChildren()->First();
1992 wxWindow
*child
= (wxWindow
*)node
->Data();
1993 if (child
->GetValidator() && /* child->GetValidator()->Ok() && */
1994 !child
->GetValidator()->TransferToWindow() )
1996 wxMessageBox( _("Application Error"), _("Could not transfer data to window"), wxOK
|wxICON_EXCLAMATION
);
1999 node
= node
->Next();
2004 bool wxWindow::TransferDataFromWindow(void)
2006 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2008 wxNode
*node
= GetChildren()->First();
2011 wxWindow
*child
= (wxWindow
*)node
->Data();
2012 if ( child
->GetValidator() && /* child->GetValidator()->Ok() && */ !child
->GetValidator()->TransferFromWindow() )
2014 node
= node
->Next();
2019 void wxWindow::SetAcceleratorTable( const wxAcceleratorTable
& accel
)
2021 m_acceleratorTable
= accel
;
2024 void wxWindow::OnInitDialog( wxInitDialogEvent
&WXUNUSED(event
) )
2026 TransferDataToWindow();
2029 void wxWindow::InitDialog(void)
2031 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2033 wxInitDialogEvent
event(GetId());
2034 event
.SetEventObject( this );
2035 GetEventHandler()->ProcessEvent(event
);
2038 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2040 menu
->SetInvokingWindow( win
);
2041 wxNode
*node
= menu
->m_items
.First();
2044 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2045 if (menuitem
->IsSubMenu())
2046 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2047 node
= node
->Next();
2051 bool wxWindow::PopupMenu( wxMenu
*menu
, int WXUNUSED(x
), int WXUNUSED(y
) )
2053 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2055 SetInvokingWindow( menu
, this );
2056 gtk_menu_popup( GTK_MENU(menu
->m_menu
), (GtkWidget
*) NULL
, (GtkWidget
*) NULL
, (GtkMenuPositionFunc
) NULL
, NULL
, 0, 0 );
2060 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2062 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2064 GtkWidget
*dnd_widget
= GetConnectWidget();
2066 DisconnectDnDWidget( dnd_widget
);
2068 if (m_pDropTarget
) delete m_pDropTarget
;
2069 m_pDropTarget
= dropTarget
;
2071 ConnectDnDWidget( dnd_widget
);
2074 wxDropTarget
*wxWindow::GetDropTarget() const
2076 return m_pDropTarget
;
2079 void wxWindow::ConnectDnDWidget( GtkWidget
*widget
)
2081 if (!m_pDropTarget
) return;
2083 m_pDropTarget
->RegisterWidget( widget
);
2085 gtk_signal_connect( GTK_OBJECT(widget
), "drop_data_available_event",
2086 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2089 void wxWindow::DisconnectDnDWidget( GtkWidget
*widget
)
2091 if (!m_pDropTarget
) return;
2093 gtk_signal_disconnect_by_func( GTK_OBJECT(widget
),
2094 GTK_SIGNAL_FUNC(gtk_window_drop_callback
), (gpointer
)this );
2096 m_pDropTarget
->UnregisterWidget( widget
);
2099 GtkWidget
* wxWindow::GetConnectWidget(void)
2101 GtkWidget
*connect_widget
= m_widget
;
2102 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2104 return connect_widget
;
2107 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2109 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2110 return (window
== m_widget
->window
);
2113 void wxWindow::SetFont( const wxFont
&font
)
2115 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2117 if (((wxFont
*)&font
)->Ok())
2120 m_font
= *wxSWISS_FONT
;
2122 GtkStyle
*style
= (GtkStyle
*) NULL
;
2125 m_hasOwnStyle
= TRUE
;
2126 style
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2130 style
= gtk_widget_get_style( m_widget
);
2133 gdk_font_unref( style
->font
);
2134 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2136 gtk_widget_set_style( m_widget
, style
);
2139 wxFont
*wxWindow::GetFont(void)
2144 void wxWindow::SetWindowStyleFlag( long flag
)
2146 m_windowStyle
= flag
;
2149 long wxWindow::GetWindowStyleFlag(void) const
2151 return m_windowStyle
;
2154 void wxWindow::CaptureMouse(void)
2156 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2158 wxASSERT_MSG( (g_capturing
== FALSE
), "CaptureMouse called twice" );
2160 GtkWidget
*connect_widget
= GetConnectWidget();
2161 gtk_grab_add( connect_widget
);
2162 gdk_pointer_grab ( connect_widget
->window
, FALSE
,
2164 (GDK_BUTTON_PRESS_MASK
|
2165 GDK_BUTTON_RELEASE_MASK
|
2166 GDK_POINTER_MOTION_MASK
),
2167 (GdkWindow
*) NULL
, (GdkCursor
*) NULL
, GDK_CURRENT_TIME
);
2171 void wxWindow::ReleaseMouse(void)
2173 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2175 wxASSERT_MSG( (g_capturing
== TRUE
), "ReleaseMouse called twice" );
2177 GtkWidget
*connect_widget
= GetConnectWidget();
2178 gtk_grab_remove( connect_widget
);
2179 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2180 g_capturing
= FALSE
;
2183 void wxWindow::SetTitle( const wxString
&WXUNUSED(title
) )
2187 wxString
wxWindow::GetTitle(void) const
2189 return (wxString
&)m_windowName
;
2192 wxString
wxWindow::GetLabel(void) const
2197 void wxWindow::SetName( const wxString
&name
)
2199 m_windowName
= name
;
2202 wxString
wxWindow::GetName(void) const
2204 return (wxString
&)m_windowName
;
2207 bool wxWindow::IsShown(void) const
2212 bool wxWindow::IsRetained(void)
2217 wxWindow
*wxWindow::FindWindow( long id
)
2219 if (id
== m_windowId
) return this;
2220 wxNode
*node
= m_children
.First();
2223 wxWindow
*child
= (wxWindow
*)node
->Data();
2224 wxWindow
*res
= child
->FindWindow( id
);
2225 if (res
) return res
;
2226 node
= node
->Next();
2228 return (wxWindow
*) NULL
;
2231 wxWindow
*wxWindow::FindWindow( const wxString
& name
)
2233 if (name
== m_windowName
) return this;
2234 wxNode
*node
= m_children
.First();
2237 wxWindow
*child
= (wxWindow
*)node
->Data();
2238 wxWindow
*res
= child
->FindWindow( name
);
2239 if (res
) return res
;
2240 node
= node
->Next();
2242 return (wxWindow
*) NULL
;
2245 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2246 int range
, bool refresh
)
2248 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2250 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2252 if (!m_wxwindow
) return;
2254 if (orient
== wxHORIZONTAL
)
2256 float fpos
= (float)pos
;
2257 float frange
= (float)range
;
2258 float fthumb
= (float)thumbVisible
;
2260 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2261 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2263 SetScrollPos( orient
, pos
, refresh
);
2267 m_oldHorizontalPos
= fpos
;
2269 m_hAdjust
->lower
= 0.0;
2270 m_hAdjust
->upper
= frange
;
2271 m_hAdjust
->value
= fpos
;
2272 m_hAdjust
->step_increment
= 1.0;
2273 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2274 m_hAdjust
->page_size
= fthumb
;
2278 float fpos
= (float)pos
;
2279 float frange
= (float)range
;
2280 float fthumb
= (float)thumbVisible
;
2282 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2283 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2285 SetScrollPos( orient
, pos
, refresh
);
2289 m_oldVerticalPos
= fpos
;
2291 m_vAdjust
->lower
= 0.0;
2292 m_vAdjust
->upper
= frange
;
2293 m_vAdjust
->value
= fpos
;
2294 m_vAdjust
->step_increment
= 1.0;
2295 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2296 m_vAdjust
->page_size
= fthumb
;
2299 if (m_wxwindow
->window
)
2301 if (orient
== wxHORIZONTAL
)
2302 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2304 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2306 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2310 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2312 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2314 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2316 if (!m_wxwindow
) return;
2318 if (orient
== wxHORIZONTAL
)
2320 float fpos
= (float)pos
;
2321 m_oldHorizontalPos
= fpos
;
2323 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2324 m_hAdjust
->value
= fpos
;
2328 float fpos
= (float)pos
;
2329 m_oldVerticalPos
= fpos
;
2330 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2331 m_vAdjust
->value
= fpos
;
2336 if (m_wxwindow
->window
)
2338 if (orient
== wxHORIZONTAL
)
2339 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2341 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2346 int wxWindow::GetScrollThumb( int orient
) const
2348 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2350 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2352 if (!m_wxwindow
) return 0;
2354 if (orient
== wxHORIZONTAL
)
2355 return (int)(m_hAdjust
->page_size
+0.5);
2357 return (int)(m_vAdjust
->page_size
+0.5);
2360 int wxWindow::GetScrollPos( 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
->value
+0.5);
2371 return (int)(m_vAdjust
->value
+0.5);
2374 int wxWindow::GetScrollRange( 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
->upper
+0.5);
2385 return (int)(m_vAdjust
->upper
+0.5);
2388 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2390 wxASSERT_MSG( (m_widget
!= NULL
), "invalid window" );
2392 wxASSERT_MSG( (m_wxwindow
!= NULL
), "window needs client area" );
2394 if (!m_wxwindow
) return;
2398 GetClientSize( &cw
, &ch
);
2400 int w
= cw
- abs(dx
);
2401 int h
= ch
- abs(dy
);
2402 if ((h
< 0) || (w
< 0))
2409 if (dx
< 0) s_x
= -dx
;
2410 if (dy
< 0) s_y
= -dy
;
2413 if (dx
> 0) d_x
= dx
;
2414 if (dy
> 0) d_y
= dy
;
2415 gdk_window_copy_area( m_wxwindow
->window
, m_wxwindow
->style
->fg_gc
[0], d_x
, d_y
,
2416 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2419 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2420 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2421 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2422 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2424 Refresh( TRUE
, &rect
);
2427 //-------------------------------------------------------------------------------------
2429 //-------------------------------------------------------------------------------------
2431 wxLayoutConstraints
*wxWindow::GetConstraints(void) const
2433 return m_constraints
;
2436 void wxWindow::SetConstraints( wxLayoutConstraints
*constraints
)
2440 UnsetConstraints(m_constraints
);
2441 delete m_constraints
;
2443 m_constraints
= constraints
;
2446 // Make sure other windows know they're part of a 'meaningful relationship'
2447 if (m_constraints
->left
.GetOtherWindow() && (m_constraints
->left
.GetOtherWindow() != this))
2448 m_constraints
->left
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2449 if (m_constraints
->top
.GetOtherWindow() && (m_constraints
->top
.GetOtherWindow() != this))
2450 m_constraints
->top
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2451 if (m_constraints
->right
.GetOtherWindow() && (m_constraints
->right
.GetOtherWindow() != this))
2452 m_constraints
->right
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2453 if (m_constraints
->bottom
.GetOtherWindow() && (m_constraints
->bottom
.GetOtherWindow() != this))
2454 m_constraints
->bottom
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2455 if (m_constraints
->width
.GetOtherWindow() && (m_constraints
->width
.GetOtherWindow() != this))
2456 m_constraints
->width
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2457 if (m_constraints
->height
.GetOtherWindow() && (m_constraints
->height
.GetOtherWindow() != this))
2458 m_constraints
->height
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2459 if (m_constraints
->centreX
.GetOtherWindow() && (m_constraints
->centreX
.GetOtherWindow() != this))
2460 m_constraints
->centreX
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2461 if (m_constraints
->centreY
.GetOtherWindow() && (m_constraints
->centreY
.GetOtherWindow() != this))
2462 m_constraints
->centreY
.GetOtherWindow()->AddConstraintReference((wxWindow
*)this);
2468 void wxWindow::SetAutoLayout( bool autoLayout
)
2470 m_autoLayout
= autoLayout
;
2473 bool wxWindow::GetAutoLayout(void) const
2475 return m_autoLayout
;
2478 wxSizer
*wxWindow::GetSizer(void) const
2480 return m_windowSizer
;
2483 void wxWindow::SetSizerParent( wxWindow
*win
)
2485 m_sizerParent
= win
;
2488 wxWindow
*wxWindow::GetSizerParent(void) const
2490 return m_sizerParent
;
2493 // This removes any dangling pointers to this window
2494 // in other windows' constraintsInvolvedIn lists.
2495 void wxWindow::UnsetConstraints(wxLayoutConstraints
*c
)
2499 if (c
->left
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2500 c
->left
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2501 if (c
->top
.GetOtherWindow() && (c
->top
.GetOtherWindow() != this))
2502 c
->top
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2503 if (c
->right
.GetOtherWindow() && (c
->right
.GetOtherWindow() != this))
2504 c
->right
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2505 if (c
->bottom
.GetOtherWindow() && (c
->bottom
.GetOtherWindow() != this))
2506 c
->bottom
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2507 if (c
->width
.GetOtherWindow() && (c
->width
.GetOtherWindow() != this))
2508 c
->width
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2509 if (c
->height
.GetOtherWindow() && (c
->height
.GetOtherWindow() != this))
2510 c
->height
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2511 if (c
->centreX
.GetOtherWindow() && (c
->centreX
.GetOtherWindow() != this))
2512 c
->centreX
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2513 if (c
->centreY
.GetOtherWindow() && (c
->centreY
.GetOtherWindow() != this))
2514 c
->centreY
.GetOtherWindow()->RemoveConstraintReference((wxWindow
*)this);
2518 // Back-pointer to other windows we're involved with, so if we delete
2519 // this window, we must delete any constraints we're involved with.
2520 void wxWindow::AddConstraintReference(wxWindow
*otherWin
)
2522 if (!m_constraintsInvolvedIn
)
2523 m_constraintsInvolvedIn
= new wxList
;
2524 if (!m_constraintsInvolvedIn
->Member(otherWin
))
2525 m_constraintsInvolvedIn
->Append(otherWin
);
2528 // REMOVE back-pointer to other windows we're involved with.
2529 void wxWindow::RemoveConstraintReference(wxWindow
*otherWin
)
2531 if (m_constraintsInvolvedIn
)
2532 m_constraintsInvolvedIn
->DeleteObject(otherWin
);
2535 // Reset any constraints that mention this window
2536 void wxWindow::DeleteRelatedConstraints(void)
2538 if (m_constraintsInvolvedIn
)
2540 wxNode
*node
= m_constraintsInvolvedIn
->First();
2543 wxWindow
*win
= (wxWindow
*)node
->Data();
2544 wxNode
*next
= node
->Next();
2545 wxLayoutConstraints
*constr
= win
->GetConstraints();
2547 // Reset any constraints involving this window
2550 constr
->left
.ResetIfWin((wxWindow
*)this);
2551 constr
->top
.ResetIfWin((wxWindow
*)this);
2552 constr
->right
.ResetIfWin((wxWindow
*)this);
2553 constr
->bottom
.ResetIfWin((wxWindow
*)this);
2554 constr
->width
.ResetIfWin((wxWindow
*)this);
2555 constr
->height
.ResetIfWin((wxWindow
*)this);
2556 constr
->centreX
.ResetIfWin((wxWindow
*)this);
2557 constr
->centreY
.ResetIfWin((wxWindow
*)this);
2562 delete m_constraintsInvolvedIn
;
2563 m_constraintsInvolvedIn
= (wxList
*) NULL
;
2567 void wxWindow::SetSizer(wxSizer
*sizer
)
2569 m_windowSizer
= sizer
;
2571 sizer
->SetSizerParent((wxWindow
*)this);
2578 bool wxWindow::Layout(void)
2580 if (GetConstraints())
2583 GetClientSize(&w
, &h
);
2584 GetConstraints()->width
.SetValue(w
);
2585 GetConstraints()->height
.SetValue(h
);
2588 // If top level (one sizer), evaluate the sizer's constraints.
2592 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
2593 GetSizer()->LayoutPhase1(&noChanges
);
2594 GetSizer()->LayoutPhase2(&noChanges
);
2595 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
2600 // Otherwise, evaluate child constraints
2601 ResetConstraints(); // Mark all constraints as unevaluated
2602 DoPhase(1); // Just one phase need if no sizers involved
2604 SetConstraintSizes(); // Recursively set the real window sizes
2610 // Do a phase of evaluating constraints:
2611 // the default behaviour. wxSizers may do a similar
2612 // thing, but also impose their own 'constraints'
2613 // and order the evaluation differently.
2614 bool wxWindow::LayoutPhase1(int *noChanges
)
2616 wxLayoutConstraints
*constr
= GetConstraints();
2619 return constr
->SatisfyConstraints((wxWindow
*)this, noChanges
);
2625 bool wxWindow::LayoutPhase2(int *noChanges
)
2635 // Do a phase of evaluating child constraints
2636 bool wxWindow::DoPhase(int phase
)
2638 int noIterations
= 0;
2639 int maxIterations
= 500;
2643 while ((noChanges
> 0) && (noIterations
< maxIterations
))
2647 wxNode
*node
= GetChildren()->First();
2650 wxWindow
*child
= (wxWindow
*)node
->Data();
2651 if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && !child
->IsKindOf(CLASSINFO(wxDialog
)))
2653 wxLayoutConstraints
*constr
= child
->GetConstraints();
2656 if (succeeded
.Member(child
))
2661 int tempNoChanges
= 0;
2662 bool success
= ( (phase
== 1) ? child
->LayoutPhase1(&tempNoChanges
) : child
->LayoutPhase2(&tempNoChanges
) ) ;
2663 noChanges
+= tempNoChanges
;
2666 succeeded
.Append(child
);
2671 node
= node
->Next();
2678 void wxWindow::ResetConstraints(void)
2680 wxLayoutConstraints
*constr
= GetConstraints();
2683 constr
->left
.SetDone(FALSE
);
2684 constr
->top
.SetDone(FALSE
);
2685 constr
->right
.SetDone(FALSE
);
2686 constr
->bottom
.SetDone(FALSE
);
2687 constr
->width
.SetDone(FALSE
);
2688 constr
->height
.SetDone(FALSE
);
2689 constr
->centreX
.SetDone(FALSE
);
2690 constr
->centreY
.SetDone(FALSE
);
2692 wxNode
*node
= GetChildren()->First();
2695 wxWindow
*win
= (wxWindow
*)node
->Data();
2696 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2697 win
->ResetConstraints();
2698 node
= node
->Next();
2702 // Need to distinguish between setting the 'fake' size for
2703 // windows and sizers, and setting the real values.
2704 void wxWindow::SetConstraintSizes(bool recurse
)
2706 wxLayoutConstraints
*constr
= GetConstraints();
2707 if (constr
&& constr
->left
.GetDone() && constr
->right
.GetDone() &&
2708 constr
->width
.GetDone() && constr
->height
.GetDone())
2710 int x
= constr
->left
.GetValue();
2711 int y
= constr
->top
.GetValue();
2712 int w
= constr
->width
.GetValue();
2713 int h
= constr
->height
.GetValue();
2715 // If we don't want to resize this window, just move it...
2716 if ((constr
->width
.GetRelationship() != wxAsIs
) ||
2717 (constr
->height
.GetRelationship() != wxAsIs
))
2719 // Calls Layout() recursively. AAAGH. How can we stop that.
2720 // Simply take Layout() out of non-top level OnSizes.
2721 SizerSetSize(x
, y
, w
, h
);
2730 char *windowClass
= this->GetClassInfo()->GetClassName();
2733 if (GetName() == "")
2734 winName
= _("unnamed");
2736 winName
= GetName();
2737 wxDebugMsg(_("Constraint(s) not satisfied for window of type %s, name %s:\n"), (const char *)windowClass
, (const char *)winName
);
2738 if (!constr
->left
.GetDone())
2739 wxDebugMsg(_(" unsatisfied 'left' constraint.\n"));
2740 if (!constr
->right
.GetDone())
2741 wxDebugMsg(_(" unsatisfied 'right' constraint.\n"));
2742 if (!constr
->width
.GetDone())
2743 wxDebugMsg(_(" unsatisfied 'width' constraint.\n"));
2744 if (!constr
->height
.GetDone())
2745 wxDebugMsg(_(" unsatisfied 'height' constraint.\n"));
2746 wxDebugMsg(_("Please check constraints: try adding AsIs() constraints.\n"));
2751 wxNode
*node
= GetChildren()->First();
2754 wxWindow
*win
= (wxWindow
*)node
->Data();
2755 if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && !win
->IsKindOf(CLASSINFO(wxDialog
)))
2756 win
->SetConstraintSizes();
2757 node
= node
->Next();
2762 // This assumes that all sizers are 'on' the same
2763 // window, i.e. the parent of this window.
2764 void wxWindow::TransformSizerToActual(int *x
, int *y
) const
2766 if (!m_sizerParent
|| m_sizerParent
->IsKindOf(CLASSINFO(wxDialog
)) ||
2767 m_sizerParent
->IsKindOf(CLASSINFO(wxFrame
)) )
2771 m_sizerParent
->GetPosition(&xp
, &yp
);
2772 m_sizerParent
->TransformSizerToActual(&xp
, &yp
);
2777 void wxWindow::SizerSetSize(int x
, int y
, int w
, int h
)
2781 TransformSizerToActual(&xx
, &yy
);
2782 SetSize(xx
, yy
, w
, h
);
2785 void wxWindow::SizerMove(int x
, int y
)
2789 TransformSizerToActual(&xx
, &yy
);
2793 // Only set the size/position of the constraint (if any)
2794 void wxWindow::SetSizeConstraint(int x
, int y
, int w
, int h
)
2796 wxLayoutConstraints
*constr
= GetConstraints();
2801 constr
->left
.SetValue(x
);
2802 constr
->left
.SetDone(TRUE
);
2806 constr
->top
.SetValue(y
);
2807 constr
->top
.SetDone(TRUE
);
2811 constr
->width
.SetValue(w
);
2812 constr
->width
.SetDone(TRUE
);
2816 constr
->height
.SetValue(h
);
2817 constr
->height
.SetDone(TRUE
);
2822 void wxWindow::MoveConstraint(int x
, int y
)
2824 wxLayoutConstraints
*constr
= GetConstraints();
2829 constr
->left
.SetValue(x
);
2830 constr
->left
.SetDone(TRUE
);
2834 constr
->top
.SetValue(y
);
2835 constr
->top
.SetDone(TRUE
);
2840 void wxWindow::GetSizeConstraint(int *w
, int *h
) const
2842 wxLayoutConstraints
*constr
= GetConstraints();
2845 *w
= constr
->width
.GetValue();
2846 *h
= constr
->height
.GetValue();
2852 void wxWindow::GetClientSizeConstraint(int *w
, int *h
) const
2854 wxLayoutConstraints
*constr
= GetConstraints();
2857 *w
= constr
->width
.GetValue();
2858 *h
= constr
->height
.GetValue();
2861 GetClientSize(w
, h
);
2864 void wxWindow::GetPositionConstraint(int *x
, int *y
) const
2866 wxLayoutConstraints
*constr
= GetConstraints();
2869 *x
= constr
->left
.GetValue();
2870 *y
= constr
->top
.GetValue();
2876 bool wxWindow::AcceptsFocus() const
2878 return IsEnabled() && IsShown();
2881 void wxWindow::OnIdle(wxIdleEvent
& WXUNUSED(event
) )